blob: 40c324400817f5458b44f49206ed268e75857e7b [file] [edit]
// Copyright (c) 2026, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:io';
import 'package:test/test.dart';
import 'utils/server_driver.dart';
void main() {
group('DevTools Server Security', () {
group('Host and Origin validation (Enabled by default)', () {
late DevToolsServerDriver server;
late Uri serverUri;
late HttpClient client;
setUpAll(() async {
server = await DevToolsServerDriver.create();
final event = (await server.stdout.firstWhere(
(map) => map!['event'] == 'server.started',
))!;
final port = event['params']['port'] as int;
serverUri = Uri.parse('http://127.0.0.1:$port/');
client = HttpClient();
});
tearDownAll(() async {
client.close();
server.kill();
});
test('allows legitimate GET request to /api/ping', () async {
final request = await client.getUrl(serverUri.resolve('api/ping'));
final response = await request.close();
expect(response.statusCode, HttpStatus.ok);
await response.drain();
});
test('forbids GET request with bad Host Header to /api/ping', () async {
final request = await client.getUrl(serverUri.resolve('api/ping'));
request.headers.set(HttpHeaders.hostHeader, 'evil.example.com');
final response = await request.close();
expect(response.statusCode, HttpStatus.forbidden);
await response.drain();
});
test('forbids GET request with bad Origin Header to /api/sse', () async {
final request = await client.getUrl(serverUri.resolve('api/sse'));
request.headers.set('Origin', 'http://evil.example.com');
final response = await request.close();
expect(response.statusCode, HttpStatus.forbidden);
await response.drain();
});
});
group('Disable Origin Check', () {
late DevToolsServerDriver server;
late Uri serverUri;
late HttpClient client;
setUpAll(() async {
server = await DevToolsServerDriver.create(
additionalArgs: ['--disable-service-origin-check'],
);
final event = (await server.stdout.firstWhere(
(map) => map!['event'] == 'server.started',
))!;
final port = event['params']['port'] as int;
serverUri = Uri.parse('http://127.0.0.1:$port/');
client = HttpClient();
});
tearDownAll(() async {
client.close();
server.kill();
});
test('allows bad Host Header to /api/ping', () async {
final request = await client.getUrl(serverUri.resolve('api/ping'));
request.headers.set(HttpHeaders.hostHeader, 'evil.example.com');
final response = await request.close();
expect(response.statusCode, HttpStatus.ok);
await response.drain();
});
test('allows bad Origin Header to /api/sse', () async {
final request = await client.getUrl(serverUri.resolve('api/sse'));
request.headers.set('Origin', 'http://evil.example.com');
final response = await request.close();
expect(response.statusCode, isNot(HttpStatus.forbidden));
await response.drain();
});
});
}, timeout: const Timeout.factor(10));
}