Skip to content

Commit 385f24c

Browse files
aduh95targos
authored andcommitted
esm: protect ERR_UNSUPPORTED_DIR_IMPORT against prototype pollution
PR-URL: #49060 Backport-PR-URL: #50669 Reviewed-By: Geoffrey Booth <[email protected]> Reviewed-By: Jacob Smith <[email protected]>
1 parent d5a1153 commit 385f24c

File tree

3 files changed

+24
-25
lines changed

3 files changed

+24
-25
lines changed

lib/internal/errors.js

+5-2
Original file line numberDiff line numberDiff line change
@@ -1692,8 +1692,11 @@ E('ERR_UNKNOWN_FILE_EXTENSION', (ext, path, suggestion) => {
16921692
E('ERR_UNKNOWN_MODULE_FORMAT', 'Unknown module format: %s for URL %s',
16931693
RangeError);
16941694
E('ERR_UNKNOWN_SIGNAL', 'Unknown signal: %s', TypeError);
1695-
E('ERR_UNSUPPORTED_DIR_IMPORT', "Directory import '%s' is not supported " +
1696-
'resolving ES modules imported from %s', Error);
1695+
E('ERR_UNSUPPORTED_DIR_IMPORT', function(path, base, exactUrl) {
1696+
lazyInternalUtil().setOwnProperty(this, 'url', exactUrl);
1697+
return `Directory import '${path}' is not supported ` +
1698+
`resolving ES modules imported from ${base}`;
1699+
}, Error);
16971700
E('ERR_UNSUPPORTED_ESM_URL_SCHEME', (url, supported) => {
16981701
let msg = `Only URLs with a scheme in: ${formatList(supported)} are supported by the default ESM loader`;
16991702
if (isWindows && url.protocol.length === 2) {

lib/internal/modules/esm/resolve.js

+1-3
Original file line numberDiff line numberDiff line change
@@ -282,9 +282,7 @@ function finalizeResolution(resolved, base, preserveSymlinks) {
282282

283283
// Check for stats.isDirectory()
284284
if (stats === 1) {
285-
const err = new ERR_UNSUPPORTED_DIR_IMPORT(path, fileURLToPath(base));
286-
err.url = String(resolved);
287-
throw err;
285+
throw new ERR_UNSUPPORTED_DIR_IMPORT(path, fileURLToPath(base), String(resolved));
288286
} else if (stats !== 0) {
289287
// Check for !stats.isFile()
290288
if (process.env.WATCH_REPORT_DEPENDENCIES && process.send) {
+18-20
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,22 @@
1-
import '../common/index.mjs';
1+
import { mustNotCall } from '../common/index.mjs';
2+
import * as fixtures from '../common/fixtures.mjs';
23
import assert from 'assert';
34

4-
async function main() {
5-
let mod;
6-
try {
7-
mod = await import('../fixtures/es-modules/pjson-main');
8-
} catch (e) {
9-
assert.strictEqual(e.code, 'ERR_UNSUPPORTED_DIR_IMPORT');
10-
}
5+
Object.defineProperty(Error.prototype, 'url', {
6+
get: mustNotCall('get %Error.prototype%.url'),
7+
set: mustNotCall('set %Error.prototype%.url'),
8+
});
9+
Object.defineProperty(Object.prototype, 'url', {
10+
get: mustNotCall('get %Object.prototype%.url'),
11+
set: mustNotCall('set %Object.prototype%.url'),
12+
});
1113

12-
assert.strictEqual(mod, undefined);
14+
await assert.rejects(import('../fixtures/es-modules/pjson-main'), {
15+
code: 'ERR_UNSUPPORTED_DIR_IMPORT',
16+
url: fixtures.fileURL('es-modules/pjson-main').href,
17+
});
1318

14-
try {
15-
mod = await import('../fixtures/es-modules/pjson-main/main.mjs');
16-
} catch (e) {
17-
console.log(e);
18-
assert.fail();
19-
}
20-
21-
assert.strictEqual(mod.main, 'main');
22-
}
23-
24-
main();
19+
assert.deepStrictEqual(
20+
{ ...await import('../fixtures/es-modules/pjson-main/main.mjs') },
21+
{ main: 'main' },
22+
);

0 commit comments

Comments
 (0)