Skip to content

Commit c4514ee

Browse files
antonisclaude
andcommitted
fix(playground): Handle ESM open package, sanitize logged URLs
- Handle both CJS and ESM exports from the `open` package (v8+ is ESM-only and `require` returns `{ default: fn }` instead of `fn`) - Sanitize URLs before logging to prevent terminal escape sequence injection via control characters Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 86b0af9 commit c4514ee

File tree

1 file changed

+18
-5
lines changed

1 file changed

+18
-5
lines changed

packages/core/src/js/metro/openUrlMiddleware.ts

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,10 @@ export async function openURLMiddleware(req: IncomingMessage, res: ServerRespons
2424
if (!open) {
2525
try {
2626
// oxlint-disable-next-line import/no-extraneous-dependencies
27-
open = require('open');
27+
const imported = require('open');
28+
// Handle both CJS (`module.exports = fn`) and ESM default export (`{ default: fn }`)
29+
// oxlint-disable-next-line typescript-eslint(no-unsafe-member-access)
30+
open = typeof imported === 'function' ? imported : imported?.default;
2831
} catch (e) {
2932
// noop
3033
}
@@ -56,15 +59,17 @@ export async function openURLMiddleware(req: IncomingMessage, res: ServerRespons
5659

5760
if (!isTrustedSentryHost(url)) {
5861
// oxlint-disable-next-line no-console
59-
console.log(`${S} Untrusted host, not opening automatically. Open manually if you trust this URL: ${url}`);
62+
console.log(
63+
`${S} Untrusted host, not opening automatically. Open manually if you trust this URL: ${sanitizeForLog(url)}`,
64+
);
6065
res.writeHead(200);
6166
res.end();
6267
return;
6368
}
6469

6570
if (!open) {
6671
// oxlint-disable-next-line no-console
67-
console.log(`${S} Could not open URL automatically. Open manually: ${url}`);
72+
console.log(`${S} Could not open URL automatically. Open manually: ${sanitizeForLog(url)}`);
6873
res.writeHead(500);
6974
res.end('Failed to open URL. The "open" package is not available. Install it or open the URL manually.');
7075
return;
@@ -74,18 +79,26 @@ export async function openURLMiddleware(req: IncomingMessage, res: ServerRespons
7479
await open(url);
7580
} catch (e) {
7681
// oxlint-disable-next-line no-console
77-
console.log(`${S} Failed to open URL automatically. Open manually: ${url}`);
82+
console.log(`${S} Failed to open URL automatically. Open manually: ${sanitizeForLog(url)}`);
7883
res.writeHead(500);
7984
res.end('Failed to open URL.');
8085
return;
8186
}
8287

8388
// oxlint-disable-next-line no-console
84-
console.log(`${S} Opened URL: ${url}`);
89+
console.log(`${S} Opened URL: ${sanitizeForLog(url)}`);
8590
res.writeHead(200);
8691
res.end();
8792
}
8893

94+
/**
95+
* Strip control characters to prevent terminal escape sequence injection when logging URLs.
96+
*/
97+
function sanitizeForLog(value: string): string {
98+
// oxlint-disable-next-line no-control-regex
99+
return value.replace(/[\x00-\x1f\x7f]/g, '');
100+
}
101+
89102
function isTrustedSentryHost(url: string): boolean {
90103
try {
91104
const { hostname } = new URL(url);

0 commit comments

Comments
 (0)