npm / es-module-lexer / 3.0.3

es-module-lexer 3.0.3

Source
https://github.com/guybedford/es-module-lexer
Commit scanned
ced104c6395a (recorded by npm)
Compared with
47811a8dedfd (0 signals introduced since)
Files
32 scanned, 3 skipped (binary, oversized, or unrecognised)
Signals
0 critical · 0 warn · 29 info
Scan time
13.4 s
LLM review
Reviewed by claude-haiku-5-5 (Anthropic): 13 of 13 warn and critical signals; 13 demoted to info.
Disclude version
4.0.0
Scanned (UTC)
2026-10-14 19:55

Signals

Ordered by severity, then signals introduced in this release. Hidden characters are shown as ⟨U+…⟩.

  1. info warn → info by review dynamic-import bench/index.js:37:32

    dynamic `import(...)` with a non-literal specifier (ast pass, confidence 0.65)

    	const loadStart = process.hrtime.bigint();
    	const { parse, init } = await import(build.path);
    	if (init) await init;
    	const load = ms(loadStart, process.hrtime.bigint());
    likely benign LLM, confidence 0.80 Benchmark harness dynamically imports a build artifact by path.
    Reasoning

    The import specifier is `build.path`, a build-output path used by a benchmark harness to load a parser module. The benchmark loads its own built artifact, so there is no sign of attacker-controlled input. The only doubt is that the path is not visible in the snippet.

  2. info whitespace-anomaly build/combine-asm.mjs:25:1

    file mixes tab and space indentation (7 tab-indented and 33 space-indented lines) (raw pass, confidence 0.40)

    const replacements = [
      [/Module\["asm"\]=\s?\(\/\*\* @suppress {uselessCode} \*\/ function\(/, 'function asmInit('],
      [/\)$/, ''],
      [/,\s?_(\w+):/g, ',$1:', null, endFuncs],
  3. info warn → info by review dynamic-execution src/lexer.ts:723:23

    `atob` decodes a base64 value at runtime — common step before dynamic fetch or eval (ast pass, confidence 0.75)

        ? Buffer.from(binary, 'base64')
        : Uint8Array.from(atob(binary), x => x.charCodeAt(0))
    )('WASM_BINARY');
    likely benign LLM, confidence 0.85 Base64-embedded WASM binary is decoded at runtime for instantiation.
    Reasoning

    This is the standard pattern for embedding a WebAssembly binary as base64 in a library build. It uses Buffer in Node and atob in browsers to produce the wasm bytes, which are then instantiated. The decoded data is a wasm module, not code run through eval, and this is a common technique in parser libraries.

  4. info warn → info by review dynamic-import test/_lexer.cjs:8:36

    dynamic `import(...)` with a non-literal specifier (ast pass, confidence 0.65)

      if (process.env.ASM) {
        ({ parse: lexerParse } = await import(
          minimal ? '../dist/lexer.minimal.asm.js' : '../dist/lexer.asm.js'
        ));
    dismissed LLM, confidence 0.92 Test selects between local minimal and full lexer builds via dynamic import.
    Reasoning

    The import chooses between two fixed local dist files based on a test flag. Nothing in the specifier is external or user-controlled.

  5. info warn → info by review dynamic-import test/_lexer.cjs:13:25

    dynamic `import(...)` with a non-literal specifier (ast pass, confidence 0.65)

      else {
        const lexer = await import(minimal ? '../dist/lexer.minimal.js' : '../dist/lexer.js');
        await lexer.init();
        lexerParse = lexer.parse;
    dismissed LLM, confidence 0.92 Test helper dynamically imports one of two local lexer builds.
    Reasoning

    The specifier is a ternary over two fixed local dist paths in a test helper. This is ordinary test-harness module loading.

  6. info unicode-mixed-script test/_unit.cjs:832:41

    identifier `statehashထ` mixes scripts: Latin + Other (in string/comment) (raw pass, confidence 0.40)

        assert.strictEqual(imports.length, 1);
        assert.strictEqual(imports[0].n, './statehashထ.js');
        assert.strictEqual(source.slice(imports[0].s, imports[0].e), '"./statehash\\u1011.js"');
      });
  7. info warn → info by review encoding-base64 test/_unit.cjs:996:47

    base64-like blob (78 bytes, compression ratio 1.01) (raw pass, confidence 0.60)

      test('Multiline string escapes', () => {
        parse("const str = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAABmJLR0QA/wAAAAAzJ3zzAAAGTElEQV\\\r\n\t\tRIx+VXe1BU1xn/zjn7ugvL4sIuQnll5U0ELAQxig7WiQYz6NRHa6O206qdSXXSxs60dTK200zNY9q0dcRpMs1jkrRNWmaijCVoaU';\r\n");
      });
    dismissed LLM, confidence 0.93 Base64 data URI used as literal test input for string escape parsing.
    Reasoning

    The blob is a data URI inside a string literal passed to the parser in a test named 'Multiline string escapes'. It is test input for string-escape handling, not an encoded payload, and it is never decoded or executed.

  8. info warn → info by review encoding-base64 test/_unit.cjs:996:134

    base64-like blob (101 bytes, compression ratio 1.11) (raw pass, confidence 0.60)

      test('Multiline string escapes', () => {
        parse("const str = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAABmJLR0QA/wAAAAAzJ3zzAAAGTElEQV\\\r\n\t\tRIx+VXe1BU1xn/zjn7ugvL4sIuQnll5U0ELAQxig7WiQYz6NRHa6O206qdSXXSxs60dTK200zNY9q0dcRpMs1jkrRNWmaijCVoaU';\r\n");
      });
    dismissed LLM, confidence 0.93 Second base64 data URI fragment in the same multiline-escape test string.
    Reasoning

    This is the same embedded data-URI test string as the other finding on that line. It is passed to the parser as data and never decoded or executed.

  9. info unicode-mixed-script test/_unit.cjs:1044:32

    identifier `p𓀀s` mixes scripts: Latin + Other (in string/comment) (raw pass, confidence 0.40)

      test('Simple export with unicode conversions', () => {
        const source = `export var p𓀀s,q`;
        const [imports, exports] = parse(source);
        assert.strictEqual(imports.length, 0);
  10. info unicode-mixed-script test/_unit.cjs:1048:45

    identifier `p𓀀s` mixes scripts: Latin + Other (in string/comment) (raw pass, confidence 0.40)

        assert.strictEqual(exports.length, 2);
        assertExportIs(source, exports[0], {n: 'p𓀀s', ln: 'p𓀀s' });
        assertExportIs(source, exports[1], {n: 'q', ln: 'q' });
      });
  11. info unicode-mixed-script test/_unit.cjs:1048:59

    identifier `p𓀀s` mixes scripts: Latin + Other (in string/comment) (raw pass, confidence 0.40)

        assert.strictEqual(exports.length, 2);
        assertExportIs(source, exports[0], {n: 'p𓀀s', ln: 'p𓀀s' });
        assertExportIs(source, exports[1], {n: 'q', ln: 'q' });
      });
  12. info unicode-mixed-script test/_unit.cjs:1116:23

    identifier `a𓀀` mixes scripts: Latin + Other (in string/comment) (raw pass, confidence 0.40)

        const source = `
          export function a𓀀 () {
    
          }
  13. info unicode-mixed-script test/_unit.cjs:1125:45

    identifier `a𓀀` mixes scripts: Latin + Other (in string/comment) (raw pass, confidence 0.40)

        assert.strictEqual(exports.length, 2);
        assertExportIs(source, exports[0], {n: 'a𓀀', ln: 'a𓀀' });
        assertExportIs(source, exports[1], {n: 'Q', ln: 'Q' });
      });
  14. info unicode-mixed-script test/_unit.cjs:1125:58

    identifier `a𓀀` mixes scripts: Latin + Other (in string/comment) (raw pass, confidence 0.40)

        assert.strictEqual(exports.length, 2);
        assertExportIs(source, exports[0], {n: 'a𓀀', ln: 'a𓀀' });
        assertExportIs(source, exports[1], {n: 'Q', ln: 'Q' });
      });
  15. info unicode-mixed-script test/_unit.cjs:1579:9

    identifier `x𓀀` mixes scripts: Latin + Other (in string/comment) (raw pass, confidence 0.40)

            braced as bracedOut,
            x𓀀 as astral
          };
          import {
  16. info warn → info by review dynamic-import test/_unit.cjs:2907:31

    dynamic `import(...)` with a non-literal specifier (ast pass, confidence 0.65)

          // file imported has already awaited init.
          const { parse } = await import(min ? '../dist/lexer.minimal.js?preinit' : '../dist/lexer.js?preinit');
          const [imports, exports] = parse(`import 'a'; export var p = 5`);
          assert.strictEqual(imports.length, 1);
    dismissed LLM, confidence 0.92 Unit test dynamically imports local lexer build with a preinit query.
    Reasoning

    The import selects between two fixed local builds with a query string used to test pre-init behavior. It is test scaffolding with no external or attacker-controlled input.

  17. info warn → info by review dynamic-import test/_unit.cjs:2914:31

    dynamic `import(...)` with a non-literal specifier (ast pass, confidence 0.65)

        test('Sourcename on the pre-init path', async () => {
          const { parse } = await import(min ? '../dist/lexer.minimal.js?preinit-err' : '../dist/lexer.js?preinit-err');
          assert.throws(() => parse('import{', 'my-file.js'), /^Error: Parse error my-file\.js:\d+:\d+$/);
        });
    dismissed LLM, confidence 0.92 Unit test dynamically imports local lexer build for error-path checks.
    Reasoning

    The specifier is a ternary over two local dist builds with a query string, used in a test for error sourcename reporting. This is benign test code.

  18. info warn → info by review dynamic-import test/_unit.cjs:2960:21

    dynamic `import(...)` with a non-literal specifier (ast pass, confidence 0.65)

      test('Entry point exports parse and init only', async () => {
        const m = await import(process.env.ASM
          ? (min ? '../dist/lexer.minimal.asm.js' : '../dist/lexer.asm.js')
          : (min ? '../dist/lexer.minimal.js' : '../dist/lexer.js'));
    dismissed LLM, confidence 0.92 Test imports one of four fixed local lexer builds based on env flags.
    Reasoning

    The specifier comes from an environment flag and a minimal flag, and resolves only to fixed local dist files. This is a test checking the entry point's exports.

  19. info warn → info by review dynamic-import test/fuzz-ts.mjs:32:19

    dynamic `import(...)` with a non-literal specifier (ast pass, confidence 0.65)

      : '../dist/lexer.js';
    const mod = await import(new URL(ENGINE, import.meta.url).href);
    if (mod.init) await mod.init();
    const parse = mod.parse;
    dismissed LLM, confidence 0.92 Fuzz test loads the local engine build via a URL relative to the module.
    Reasoning

    The import URL is built from a fixed ENGINE constant resolved relative to import.meta.url. It loads a local build for a fuzz test, with no external input.

  20. info whitespace-anomaly test/integration.cjs:5:1

    file mixes tab and space indentation (9 tab-indented and 27 space-indented lines) (raw pass, confidence 0.40)

    const init = (async () => {
      if (parse) return;
      if (process.env.WASM) {
        const m = await import('../dist/lexer.js');
  21. info warn → info by review dynamic-import test/no-eval/index.cjs:10:9

    `require` called with a non-literal specifier (ast pass, confidence 0.60)

        const lexer = commonjs
          ? require(minimal ? '../../dist/lexer.minimal.cjs' : '../../dist/lexer.cjs')
          : await import(minimal ? '../../dist/lexer.minimal.js' : '../../dist/lexer.js');
        await lexer.init();
    dismissed LLM, confidence 0.92 No-eval test loads local lexer builds via require or dynamic import.
    Reasoning

    The require and import calls choose between fixed local dist files based on flags. This test harness is checking that no eval is used, and the dynamic loading itself targets local builds only.

  22. info warn → info by review dynamic-import test/no-eval/index.cjs:11:15

    dynamic `import(...)` with a non-literal specifier (ast pass, confidence 0.65)

          ? require(minimal ? '../../dist/lexer.minimal.cjs' : '../../dist/lexer.cjs')
          : await import(minimal ? '../../dist/lexer.minimal.js' : '../../dist/lexer.js');
        await lexer.init();
        parse = lexer.parse;
    likely benign LLM, confidence 0.90 Test file conditionally loads one of two local lexer builds via dynamic import.
    Reasoning

    The dynamic import specifier is a ternary choosing between two fixed local module paths (lexer.minimal.js or lexer.js). The specifier is not attacker-controlled; this is a conditional module load in a test harness that mirrors a require branch above it. Non-literal specifier alone is a weak signal.

  23. info unicode-mixed-script test/no-eval/index.cjs:22:48

    identifier `unicode𠈄` mixes scripts: Latin + Other (in string/comment) (raw pass, confidence 0.40)

          [String.raw`import 'escaped\x2dspecifier'`, 'escaped-specifier'],
          [String.raw`import 'unicode\u{20204}'`, 'unicode𠈄'],
          ["import 'line\\\ncontinuation'", 'linecontinuation'],
          [String.raw`import 'nul\0character'`, 'nul\0character'],
  24. info warn → info by review long-line test/samples/d3.js:17439:1

    line length 10326 characters (raw pass, confidence 0.65)

    export { version, bisectRight as bisect, bisectRight, bisectLeft, ascending, bisector, cross, descending, deviation, extent, histogram, freedmanDiaconis as thresholdFreedmanDiaconis, scott as thresholdScott, thresholdSturges, max, mean, median, merge, min, pairs, permute, threshold as quantile, sequence as range, scan,
    dismissed LLM, confidence 0.93 Bundled d3 sample file with a very long export statement line.
    Reasoning

    A 10k-character line is the single export statement of a minified/bundled d3 library sample. Long lines in bundled JavaScript are normal, and the snippet shows only a plain export list of identifiers with no encoded content or dynamic execution. Raw long-line is a low-value signal here.

  25. info dynamic-execution test/samples/magic-string.js:181:57

    `btoa` encodes a value as base64 at runtime — used in exfiltration patterns (ast pass, confidence 0.55)

    SourceMap.prototype.toUrl = function toUrl () {
    	return 'data:application/json;charset=utf-8;base64,' + btoa(this.toString());
    };
  26. info whitespace-anomaly test/samples/rollup.js:2:1

    file mixes tab and space indentation (931 tab-indented and 19838 space-indented lines) (raw pass, confidence 0.40)

    /*
    	Rollup.js v0.65.0
    	Sat, 25 Aug 2018 13:41:58 GMT - commit 903516a760ce02804e7c5e4578ddce56e6f6bd17
  27. info dynamic-execution test/samples/rollup.js:907:57

    `btoa` encodes a value as base64 at runtime — used in exfiltration patterns (ast pass, confidence 0.55)

    SourceMap.prototype.toUrl = function toUrl () {
    	return 'data:application/json;charset=utf-8;base64,' + btoa(this.toString());
    };
  28. line length 1190 characters (raw pass, confidence 0.50)

    var astralIdentifierStartCodes = [0,11,2,25,2,18,2,1,2,14,3,13,35,122,70,52,268,28,4,48,48,31,14,29,6,37,11,29,3,35,5,7,2,4,43,157,19,35,5,35,5,39,9,51,157,310,10,21,11,7,153,5,3,0,2,43,2,1,4,0,3,22,11,22,10,30,66,18,2,1,11,21,11,25,71,55,7,1,65,0,16,3,2,2,2,28,43,28,4,28,36,7,2,27,28,53,11,21,11,18,14,17,111,72,56,50,
  29. line length 594 characters (raw pass, confidence 0.50)

    var astralIdentifierCodes = [509,0,227,0,150,4,294,9,1368,2,2,1,6,3,41,2,5,0,166,1,574,3,9,9,525,10,176,2,54,14,32,9,16,3,46,10,54,9,7,2,37,13,2,9,6,1,45,0,13,2,49,13,9,3,4,9,83,11,7,0,161,11,6,9,7,3,56,1,2,6,3,1,3,2,10,0,11,1,3,6,4,4,193,17,10,9,5,0,82,19,13,9,214,6,3,8,28,1,83,16,16,9,82,12,9,9,84,14,5,9,243,14,166,9

Reproduce This Scan

Run disclude locally to verify. Add --format sarif for SARIF output. Add --llm (with an API key in the environment) to include the LLM review.

cargo install disclude --version 4.0.0
git clone https://github.com/guybedford/es-module-lexer es-module-lexer && cd es-module-lexer
git checkout ced104c6395afaff72ad8f74fa53901185004e30
disclude scan --severity info --diff 47811a8dedfd2dedbe84f0d4940a2be013b82b8b .