npm / playwright / 1.65.0-alpha-2026-10-22

playwright 1.65.0-alpha-2026-10-22

Source
https://github.com/microsoft/playwright
Artifact scanned
playwright-1.65.0-alpha-2026-10-22.tgz (npm tarball · 888.5 KB · SHA-256 aef2f018c63a…)
Compared with
playwright-1.65.0-alpha-2026-10-21.tgz (0 signals introduced since)
Files
55 scanned, 5 skipped (binary, oversized, or unrecognised)
Signals
0 critical · 0 warn · 60 info
Scan time
29.6 s
LLM review
Reviewed by claude-haiku-5-5 (Anthropic): 32 of 32 warn and critical signals; 32 demoted to info.
Disclude version
4.3.0
Scanned (UTC)
2026-10-24 00:09

Signals

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

  1. info long-line README.md:3:1

    line length 742 characters (raw pass, confidence 0.50)

    [![npm version]https://img.shields.io/npm/v/playwright.svg]https://www.npmjs.com/package/playwright <!-- GEN:chromium-version-badge -->[![Chromium version]https://img.shields.io/badge/chromium-156.0.8078.12-blue.svg?logo=google-chrome]https://www.chromium.org/Home<!-- GEN:stop --> <!-- GEN:firefox-version-badge
  2. info warn → info by review dynamic-import lib/common/index.js:1124:30

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

      process.env.BROWSERSLIST_IGNORE_OLD_DATA = "true";
      const { babelTransform } = require((0, import_package3.libPath)("transform", "babelBundle"));
      const babelResult = babelTransform(originalCode, filename, !!moduleUrl, pluginsEpilogue, useDefineForClassFields, jsx);
      if (!babelResult?.code)
    likely benign LLM, confidence 0.80 Loads the internal babel transform bundle through a path helper.
    Reasoning

    The require resolves an internal bundled helper path via libPath("transform", "babelBundle") and then calls babelTransform on source code. This is an ordinary internal module load inside a test runner's transform pipeline, with no decoding or network activity visible.

  3. info critical → info by review dynamic-execution lib/common/index.js:1141:29

    `eval` called with a non-literal expression (ast pass, confidence 0.90)

        const fileName = import_url2.default.pathToFileURL(file);
        const esmImport = () => eval(`import(${JSON.stringify(fileName)})`);
        if (loaderChannel) {
    likely benign LLM, confidence 0.75 Uses eval to perform a native dynamic import of a local file URL for ESM test loading.
    Reasoning

    eval is used only to wrap a dynamic import() of a file URL built with JSON.stringify. This is a known workaround so that a CommonJS-compiled build keeps native ESM import semantics. Eval is a risky construct, but the input is a local file path and no attacker-controlled data reaches it.

  4. info critical → info by review dynamic-execution lib/common/index.js:1143:13

    `eval` called with a non-literal expression (ast pass, confidence 0.90)

        if (loaderChannel) {
          await eval(`import(${JSON.stringify(fileName + ".esm.preflight")})`).catch((error) => debugTest("Failed to load preflight for " + file + ", source maps may be missing for errors thrown during loading.", error)).finally(nextTask);
        }
        return await esmImport().finally(nextTask);
    likely benign LLM, confidence 0.75 Uses eval to dynamically import a preflight module next to a test file.
    Reasoning

    Same eval(import(...)) workaround, here loading a sibling '.esm.preflight' file for source-map setup. The specifier is derived from the test file path, and the surrounding code handles errors and calls a debug logger. No obfuscation or malicious behavior is present.

  5. info warn → info by review dynamic-import lib/common/index.js:1147:18

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

      }
      const result = require(file);
      const depsCollector = currentFileDepsCollector();
      if (depsCollector) {
    likely benign LLM, confidence 0.80 Requires a test file path during test loading.
    Reasoning

    require(file) loads the test file being run, which is the core job of a test runner. The file comes from the project's own test discovery, and the surrounding code only collects dependencies.

  6. line length 572 characters (raw pass, confidence 0.50)

          return "string" === typeof type || "function" === typeof type || type === REACT_FRAGMENT_TYPE || type === REACT_PROFILER_TYPE || type === REACT_STRICT_MODE_TYPE || type === REACT_SUSPENSE_TYPE || type === REACT_SUSPENSE_LIST_TYPE || "object" === typeof type && null !== type && (type.$$typeof === REACT_LAZY_TYPE |
  7. line length 997 characters (raw pass, confidence 0.50)

          var REACT_ELEMENT_TYPE = /* @__PURE__ */ Symbol.for("react.transitional.element"), REACT_PORTAL_TYPE = /* @__PURE__ */ Symbol.for("react.portal"), REACT_FRAGMENT_TYPE = /* @__PURE__ */ Symbol.for("react.fragment"), REACT_STRICT_MODE_TYPE = /* @__PURE__ */ Symbol.for("react.strict_mode"), REACT_PROFILER_TYPE = /* 
  8. line length 574 characters (raw pass, confidence 0.50)

            return "string" === typeof type || "function" === typeof type || type === REACT_FRAGMENT_TYPE || type === REACT_PROFILER_TYPE || type === REACT_STRICT_MODE_TYPE || type === REACT_SUSPENSE_TYPE || type === REACT_SUSPENSE_LIST_TYPE || "object" === typeof type && null !== type && (type.$$typeof === REACT_LAZY_TYPE
  9. line length 638 characters (raw pass, confidence 0.50)

        exports2.default = /((['"])(?:(?!\2|\\).|\\(?:\r\n|[\s\S]))*(\2)?|`(?:[^`\\$]|\\[\s\S]|\$(?!\{)|\$\{(?:[^{}]|\{[^}]*\}?)*\}?)*(`)?)|(\/\/.*)|(\/\*(?:[^*]|\*(?!\/))*(\*\/)?)|(\/(?!\*)(?:\[(?:(?![\]\\]).|\\.)*\]|(?![\/\]\\]).|\\.)+\/(?:(?!\s*(?:\b|[\u0080-\uFFFF$\\'"~({]|[+\-!](?!=)|\.?\d))|[gmiyus]{1,6}\b(?![\u0080-
  10. info warn → info by review long-line lib/matchers/expect.js:5876:1

    line length 2269 characters (raw pass, confidence 0.65)

        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, 13, 10, 2, 14, 2, 6, 2, 1, 2, 10, 2, 14, 2, 6, 2, 1, 4, 51, 13, 310, 10, 21, 11, 7, 25, 5, 2, 41, 2, 8, 70, 5, 3, 0, 2, 
    dismissed LLM, confidence 0.90 A long array literal of Unicode code point ranges used for identifier parsing.
    Reasoning

    The long line is a numeric table of Unicode astral identifier-start code points, the kind of data emitted by Babel-style identifier tables. It is a data constant, not executable obfuscation.

  11. info warn → info by review dynamic-import lib/matchers/expect.js:10216:44

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

                  const moduleUrl = (0, _nodeUrl().pathToFileURL)(filePath);
                  const importedModule = await import(
                    /* webpackIgnore: true */
                    moduleUrl.href
    likely benign LLM, confidence 0.80 Dynamically imports a user module by file URL in a module loader.
    Reasoning

    This dynamic import of pathToFileURL(filePath) with a webpackIgnore hint is the standard module loader for user-configured files in a test framework's ESM support. The path comes from configuration, not untrusted input.

  12. info warn → info by review dynamic-import lib/matchers/expect.js:10242:38

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

                  }
                  const requiredModule = require(filePath);
                  if (!applyInteropRequireDefault) {
                    return requiredModule;
    likely benign LLM, confidence 0.80 CommonJS fallback that requires a user module by path.
    Reasoning

    This require(filePath) is the CommonJS fallback of the same module loader. It loads a configured module path and then applies interop handling, which is ordinary loader behavior.

  13. line length 543 characters (raw pass, confidence 0.50)

        const message = pass ? () => matcherHint(matcherName, void 0, void 0, options) + "\n\n" + printExpectedConstructorNameNot("Expected constructor", expected) + (typeof received.constructor === "function" && received.constructor !== expected ? printReceivedConstructorNameNot("Received constructor", received.constructo
  14. line length 766 characters (raw pass, confidence 0.50)

      const message = pass ? () => matcherHint(matcherName, void 0, void 0, options) + "\n\n" + formatExpected("Expected asymmetric matcher: not ", expected) + "\n" + (thrown !== null && thrown.hasMessage ? formatReceived("Received name:    ", thrown, "name") + formatReceived("Received message: ", thrown, "message") + form
  15. line length 539 characters (raw pass, confidence 0.50)

      const message = pass ? () => matcherHint(matcherName, void 0, void 0, options) + "\n\n" + formatExpected(`Expected ${messageAndCause(expected)}: not `, expectedMessageAndCause) + (thrown !== null && thrown.hasMessage ? formatStack(thrown) : formatReceived("Received value:       ", thrown, "value")) : () => matcherHin
  16. line length 756 characters (raw pass, confidence 0.50)

      const message = pass ? () => matcherHint(matcherName, void 0, void 0, options) + "\n\n" + printExpectedConstructorNameNot("Expected constructor", expected) + (thrown !== null && thrown.value !== null && thrown.value !== void 0 && typeof thrown.value.constructor === "function" && thrown.value.constructor !== expected 
  17. info warn → info by review dynamic-import lib/package.js:38:21

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

    const packageRoot = import_path.default.join(__dirname, "..");
    const packageJSON = require(import_path.default.join(packageRoot, "package.json"));
    function libPath(...parts) {
      return import_path.default.join(packageRoot, "lib", ...parts);
    likely benign LLM, confidence 0.90 Reads the package's own package.json for its metadata.
    Reasoning

    This require loads the package's own package.json from a path built relative to __dirname. It is a standard metadata read with no dynamic execution or remote data.

  18. info warn → info by review dynamic-execution lib/runner/index.js:283:80

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

      _onStdIO(type, testId, resultId, data, isBase64) {
        const chunk = isBase64 ? globalThis.Buffer ? Buffer.from(data, "base64") : atob(data) : data;
        const test = testId ? this._tests.get(testId) : void 0;
        const result = test && resultId ? test.results.find((r) => r._id === resultId) : void 0;
    likely benign LLM, confidence 0.85 Decodes base64-encoded stdio data from a test worker into a chunk.
    Reasoning

    atob or Buffer.from decodes base64 stdio chunks forwarded from worker processes. The decoded data is treated as text output and stored in result objects. It is not fetched or evaluated, and the base64 path is a standard transport for stdout forwarding.

  19. info warn → info by review dynamic-import lib/runner/index.js:3285:27

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

          const resolveFrom = (name) => require.resolve(name, { paths: [this._options.configDir] });
          const libCoverage = require(resolveFrom("istanbul-lib-coverage"));
          const libReport = require(resolveFrom("istanbul-lib-report"));
          const reports = require(resolveFrom("istanbul-reports"));
    likely benign LLM, confidence 0.90 Loads the istanbul coverage library for report generation.
    Reasoning

    The require targets istanbul-lib-coverage, resolved from the configured config directory. This is the normal way a test runner loads coverage tooling for reporting.

  20. info warn → info by review dynamic-import lib/runner/index.js:3286:25

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

          const libCoverage = require(resolveFrom("istanbul-lib-coverage"));
          const libReport = require(resolveFrom("istanbul-lib-report"));
          const reports = require(resolveFrom("istanbul-reports"));
          const context = libReport.createContext({
    likely benign LLM, confidence 0.90 Loads the istanbul report library for coverage output.
    Reasoning

    The require targets istanbul-lib-report, which is part of the standard coverage reporting stack, and is resolved relative to the project config. It matches the surrounding coverage setup.

  21. info warn → info by review dynamic-import lib/runner/index.js:3287:23

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

          const libReport = require(resolveFrom("istanbul-lib-report"));
          const reports = require(resolveFrom("istanbul-reports"));
          const context = libReport.createContext({
            dir: outputDir,
    likely benign LLM, confidence 0.90 Loads the istanbul reports package for coverage reporters.
    Reasoning

    The require targets the istanbul-reports package, used to generate coverage reporters. This is the standard coverage reporting setup and has no suspicious behavior.

  22. info whitespace-anomaly lib/transform/babelBundle.js:9:1

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

    var __commonJS = (cb, mod) => function __require() {
      try {
        return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
      } catch (e) {
  23. info warn → info by review long-line lib/transform/babelBundle.js:3079:1

    line length 2269 characters (raw pass, confidence 0.65)

        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, 13, 10, 2, 14, 2, 6, 2, 1, 2, 10, 2, 14, 2, 6, 2, 1, 4, 51, 13, 310, 10, 21, 11, 7, 25, 5, 2, 41, 2, 8, 70, 5, 3, 0, 2, 
    likely benign LLM, confidence 0.93 Generated Unicode astral identifier-start code table inside a Babel bundle.
    Reasoning

    A 2269-character line of numeric code-point ranges (astralIdentifierStartCodes) is the standard generated Unicode identifier table used by Babel's parser. Long lines are typical of minified or generated bundles and carry no execution.

  24. line length 584 characters (raw pass, confidence 0.50)

        exports2.UPDATE_OPERATORS = exports2.UNARY_OPERATORS = exports2.STRING_UNARY_OPERATORS = exports2.STATEMENT_OR_BLOCK_KEYS = exports2.NUMBER_UNARY_OPERATORS = exports2.NUMBER_BINARY_OPERATORS = exports2.LOGICAL_OPERATORS = exports2.INHERIT_KEYS = exports2.FOR_INIT_KEYS = exports2.FLATTENABLE_KEYS = exports2.EQUALITY
  25. info warn → info by review long-line lib/transform/babelBundle.js:10081:1

    line length 2864 characters (raw pass, confidence 0.65)

        exports2.JSXIdentifier = exports2.JSXFragment = exports2.JSXExpressionContainer = exports2.JSXEmptyExpression = exports2.JSXElement = exports2.JSXClosingFragment = exports2.JSXClosingElement = exports2.JSXAttribute = exports2.IntersectionTypeAnnotation = exports2.InterpreterDirective = exports2.InterfaceTypeAnnotat
    likely benign LLM, confidence 0.93 Long chained exports assignment of Babel AST node type constructors.
    Reasoning

    The long line is a chained export assignment list for Babel AST node types (JSXIdentifier, InterpreterDirective and so on). It is generated bundler output with no dynamic behaviour.

  26. info warn → info by review long-line lib/transform/babelBundle.js:10082:1

    line length 2895 characters (raw pass, confidence 0.65)

        exports2.TSNumberKeyword = exports2.TSNullKeyword = exports2.TSNonNullExpression = exports2.TSNeverKeyword = exports2.TSNamespaceExportDeclaration = exports2.TSNamedTupleMember = exports2.TSModuleDeclaration = exports2.TSModuleBlock = exports2.TSMethodSignature = exports2.TSMappedType = exports2.TSLiteralType = exp
    likely benign LLM, confidence 0.93 Long chained exports assignment of Babel TypeScript AST node types.
    Reasoning

    Same pattern as the neighbouring line: a long chain of TypeScript AST node exports from Babel's generated types module. Length alone is not suspicious in a bundle.

  27. line length 1618 characters (raw pass, confidence 0.50)

        exports2.YieldExpression = exports2.WithStatement = exports2.WhileStatement = exports2.VoidTypeAnnotation = exports2.VoidPattern = exports2.Variance = exports2.VariableDeclarator = exports2.VariableDeclaration = exports2.V8IntrinsicIdentifier = exports2.UpdateExpression = exports2.UnionTypeAnnotation = exports2.Una
  28. line length 1460 characters (raw pass, confidence 0.50)

        exports2.WHILE_TYPES = exports2.USERWHITESPACABLE_TYPES = exports2.UNARYLIKE_TYPES = exports2.TYPESCRIPT_TYPES = exports2.TSTYPE_TYPES = exports2.TSTYPEELEMENT_TYPES = exports2.TSENTITYNAME_TYPES = exports2.TSBASETYPE_TYPES = exports2.TERMINATORLESS_TYPES = exports2.STATEMENT_TYPES = exports2.STANDARDIZED_TYPES = e
  29. info warn → info by review long-line lib/transform/babelBundle.js:15700:1

    line length 2269 characters (raw pass, confidence 0.65)

        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, 13, 10, 2, 14, 2, 6, 2, 1, 2, 10, 2, 14, 2, 6, 2, 1, 4, 51, 13, 310, 10, 21, 11, 7, 25, 5, 2, 41, 2, 8, 70, 5, 3, 0, 2, 
    likely benign LLM, confidence 0.93 Repeated generated Unicode identifier-start code table in the bundle.
    Reasoning

    This is a duplicate of the astral identifier table at line 3079, present again because the bundle inlines the same parser module twice. It is a numeric data array.

  30. line length 509 characters (raw pass, confidence 0.50)

        var reservedWordLikeSet = /* @__PURE__ */ new Set(["break", "case", "catch", "continue", "debugger", "default", "do", "else", "finally", "for", "function", "if", "return", "switch", "throw", "try", "var", "const", "while", "with", "new", "this", "super", "class", "extends", "export", "import", "null", "true", "fals
  31. line length 825 characters (raw pass, confidence 0.50)

            var _node$directive, _node$decorators, _node$optional, _node$typeAnnotation, _node$accessibility, _node$decorators2, _node$override, _node$readonly, _node$static, _node$declare, _node$returnType, _node$typeParameters, _node$optional2, _node$optional3, _node$accessibility2, _node$readonly2, _node$static2, _node$
  32. line length 638 characters (raw pass, confidence 0.50)

        exports2.default = /((['"])(?:(?!\2|\\).|\\(?:\r\n|[\s\S]))*(\2)?|`(?:[^`\\$]|\\[\s\S]|\$(?!\{)|\$\{(?:[^{}]|\{[^}]*\}?)*\}?)*(`)?)|(\/\/.*)|(\/\*(?:[^*]|\*(?!\/))*(\*\/)?)|(\/(?!\*)(?:\[(?:(?![\]\\]).|\\.)*\]|(?![\/\]\\]).|\\.)+\/(?:(?!\s*(?:\b|[\u0080-\uFFFF$\\'"~({]|[+\-!](?!=)|\.?\d))|[gmiyus]{1,6}\b(?![\u0080-
  33. info warn → info by review long-line lib/transform/babelBundle.js:49254:1

    line length 7125 characters (raw pass, confidence 0.65)

        module2.exports.ID_Start = /[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u06
    likely benign LLM, confidence 0.92 Large generated regex of Unicode ID_Start code point ranges.
    Reasoning

    The line is a large regex character class of Unicode ID_Start ranges, as generated by regenerate tooling for the unicode-property tables of a parser. It is data and does not execute anything.

  34. info warn → info by review long-line lib/transform/babelBundle.js:49255:1

    line length 8583 characters (raw pass, confidence 0.65)

        module2.exports.ID_Continue = /[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0300-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u0483-\u0487\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u
    likely benign LLM, confidence 0.92 Large generated regex of Unicode ID_Continue code point ranges.
    Reasoning

    A Unicode ID_Continue regex class of the same generated kind as ID_Start. It is a lookup table with no behaviour beyond matching.

  35. line length 738 characters (raw pass, confidence 0.50)

        var a = { c: { longName: "chrome" }, ca: { longName: "chrome_android" }, e: { longName: "edge" }, f: { longName: "firefox" }, fa: { longName: "firefox_android" }, s: { longName: "safari" }, si: { longName: "safari_ios" }, o: { longName: "opera", engine: "Blink" }, oa: { longName: "opera_android", engine: "Blink" },
  36. line length 664 characters (raw pass, confidence 0.50)

          let g = null != e2 ? e2 : {}, q = { listAllCompatibleVersions: null !== (s2 = g.listAllCompatibleVersions) && void 0 !== s2 && s2, includeDownstreamBrowsers: null !== (o2 = g.includeDownstreamBrowsers) && void 0 !== o2 && o2, widelyAvailableOnDate: null !== (f2 = g.widelyAvailableOnDate) && void 0 !== f2 ? f2 : v
  37. line length 681 characters (raw pass, confidence 0.50)

              e3.setMonth(e3.getMonth() - 2), n2 > e3 && (null != a2 ? a2 : 1787873932909) < e3.getTime() && (console.warn("[baseline-browser-mapping] The data in this module is over two months old and you are targetting a recent feature cut off date of " + n2.toISOString().slice(0, 10) + ". To ensure accurate Baseline dat
  38. line length 2949 characters (mostly string/comment) (raw pass, confidence 0.39)

        module2.exports = { "0": "116", "1": "117", "2": "118", "3": "119", "4": "120", "5": "121", "6": "122", "7": "123", "8": "124", "9": "125", A: "10", B: "11", C: "12", D: "7", E: "8", F: "9", G: "15", H: "80", I: "151", J: "4", K: "27", L: "6", M: "13", N: "14", O: "16", P: "17", Q: "18", R: "79", S: "81", T: "83", 
  39. info warn → info by review long-line lib/transform/babelBundle.js:53869:1

    line length 31391 characters (raw pass, confidence 0.65)

        module2.exports = { A: { A: { L: 0, D: 0, E: 0, F: 0, A: 0, B: 0.266336, AD: 0 }, B: "ms", C: ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "
    likely benign LLM, confidence 0.92 Bundled caniuse-lite browser compatibility data object.
    Reasoning

    The 31k-character line is a caniuse-lite browser-support data object (feature keys with version and percentage values). It is static data bundled with browserslist, not code.

  40. line length 19244 characters (mostly string/comment) (raw pass, confidence 0.39)

        module2.exports = { "0": "_I _IB", "1": "_d ZD", "2": "_qS _uI", "3": "_4 _e", "4": "J jB", "5": "B C", "6": "_Y _RF", "7": "_vS _qI", "8": "_BE _AB", "9": "gD _AB", A: "A B", B: "D A", C: "FE GE", D: "_DE _aP", E: "_PC AD", F: "J _U", G: "_FD _rS", H: "_NC _JP", I: "_v _UB", J: "_YH _tI", K: "_H _tI", L: "FD GD", 
  41. info warn → info by review dynamic-import lib/transform/babelBundle.js:54747:23

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

            }
            var queries = require(require.resolve(name, { paths: [".", ctx.path] }));
            if (typeof queries === "object" && queries !== null && queries.__esModule) {
              queries = queries.default;
    likely benign LLM, confidence 0.85 Browserslist loading a config module via require.resolve with a variable name.
    Reasoning

    Browserslist resolves custom config or query modules with require.resolve over a caller-supplied name and paths, which is the documented way to load shared configs. The target is a local module resolved from the project's own configuration, not a remote payload.

  42. info warn → info by review dynamic-import lib/transform/babelBundle.js:54767:21

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

            }
            var stats = require(
              // Use forward slashes for module paths, also on Windows.
              require.resolve(path.posix.join(name, "browserslist-stats.json"), {
    likely benign LLM, confidence 0.85 Browserslist reading its browserslist-stats.json data file via require.resolve.
    Reasoning

    This loads browserslist-stats.json from a resolved package path, using forward-slash normalisation for Windows. It is a standard data read with a fixed filename.

  43. info warn → info by review dynamic-import lib/transform/babelBundle.js:54817:26

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

              try {
                compressed = require("caniuse-lite/data/regions/" + code + ".js");
              } catch (e) {
                throw new BrowserslistError("Unknown region name `" + code + "`.");
    likely benign LLM, confidence 0.88 Browserslist loading caniuse-lite region data by code.
    Reasoning

    Browserslist requires caniuse-lite region data using a concatenated region code, wrapped in try/catch that rethrows a BrowserslistError on failure. This is the library's normal data lookup, and the path is confined to the caniuse-lite data directory.

  44. info warn → info by review dynamic-import lib/transform/babelBundle.js:54836:24

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

            try {
              compressed = require("caniuse-lite/data/features/" + name + ".js");
            } catch (e) {
              throw new BrowserslistError("Unknown feature name `" + name + "`.");
    likely benign LLM, confidence 0.88 Browserslist loading caniuse-lite feature data by name.
    Reasoning

    Browserslist loads caniuse-lite feature data by name under caniuse-lite/data/features, with a try/catch error path. The concatenated name is confined to a fixed data directory, which is ordinary behaviour.

  45. info warn → info by review dynamic-execution lib/transform/babelBundle.js:60803:40

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

        function decodeBase64WithAtob(base64) {
          return decodeURIComponent(escape(atob(base64)));
        }
        function stripComment(sm) {
    likely benign LLM, confidence 0.80 Base64 decode helper used for inline source-map comments in the bundle.
    Reasoning

    decodeBase64WithAtob sits beside stripComment, which points to inline source-map handling. It decodes an embedded base64 sourcemap comment to a UTF-8 string, which is a common and benign technique. The snippet shows no fetch or eval consuming the output.

  46. info dynamic-execution lib/transform/babelBundle.js:60865:14

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

          var json = this.toJSON();
          return btoa(unescape(encodeURIComponent(json)));
        }
        Converter.prototype.toURI = function() {
  47. info warn → info by review dynamic-import lib/transform/babelBundle.js:62117:14

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

        module2.exports = function import_(filepath) {
          return import(filepath);
        };
      }
    likely benign LLM, confidence 0.85 A helper that wraps dynamic import() of a file path, as build tooling commonly does.
    Reasoning

    The function wraps a dynamic import() of a caller-supplied path. This is a common helper for loading config or plugin modules in build tooling, and the snippet shows no decoding, network access or hidden payload.

  48. line length 529 characters (raw pass, confidence 0.50)

              if (parentParentPath.node.type === "AssignmentExpression" && parentParentPath.node.left === parentPath.node || parentParentPath.node.type === "UpdateExpression" || parentParentPath.node.type === "RestElement" || parentParentPath.node.type === "ArrayPattern" || parentParentPath.node.type === "ObjectProperty" &
  49. line length 712 characters (raw pass, confidence 0.50)

              path.replaceWithMultiple([_core.types.variableDeclaration("let", [_core.types.variableDeclarator(_core.types.cloneNode(classOuterBindingLocal)), _core.types.variableDeclarator(classOuterBindingDelegateLocal)]), _core.types.blockStatement([_core.types.variableDeclaration("let", [_core.types.variableDeclarator(
  50. line length 737 characters (raw pass, confidence 0.50)

              acc.push(_core.types.assignmentExpression("=", _core.types.cloneNode(descriptor), _core.types.callExpression(state.addHelper("applyDecoratedDescriptor"), [_core.types.cloneNode(target), _core.types.cloneNode(property), _core.types.arrayExpression(decorators.map((dec) => _core.types.cloneNode(dec.expression)))
  51. info warn → info by review dynamic-import lib/transform/babelBundle.js:72469:52

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

          ...plugins,
          ...pluginsEpilogue.map(([name, options]) => [require(name), options])
        ],
        compact: false,
    likely benign LLM, confidence 0.80 Babel config plugin names are resolved via require at runtime.
    Reasoning

    Plugin names from the user's Babel configuration are resolved with require(name). This is the standard way Babel loads plugins, and nothing in the snippet is obfuscated or malicious.

  52. info warn → info by review long-line lib/transform/esmLoader.js:2302:1

    line length 7125 characters (raw pass, confidence 0.65)

        module2.exports.ID_Start = /[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u06
    dismissed LLM, confidence 0.90 A generated Unicode ID_Start regex table on one long line.
    Reasoning

    A very long line holding Unicode ID_Start character-class ranges. This is generated lookup-table data from a Unicode regex library, a known false positive for the raw long-line signal.

  53. info warn → info by review long-line lib/transform/esmLoader.js:2303:1

    line length 8583 characters (raw pass, confidence 0.65)

        module2.exports.ID_Continue = /[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0300-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u0483-\u0487\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u
    dismissed LLM, confidence 0.90 A generated Unicode ID_Continue regex table on one long line.
    Reasoning

    Same as the ID_Start finding: a generated Unicode ID_Continue range table, typical minified or generated library data with no executable payload.

  54. info warn → info by review dynamic-import lib/transform/esmLoader.js:7880:30

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

      process.env.BROWSERSLIST_IGNORE_OLD_DATA = "true";
      const { babelTransform } = require((0, import_package2.libPath)("transform", "babelBundle"));
      const babelResult = babelTransform(originalCode, filename, !!moduleUrl, pluginsEpilogue, useDefineForClassFields, jsx);
      if (!babelResult?.code)
    likely benign LLM, confidence 0.80 Internal require of a bundled transform module via a computed path.
    Reasoning

    The require path is built from a bundled package's libPath helper and resolves to the package's own transform module. It is internal module loading inside the library, not a remote or attacker-chosen specifier.

  55. info critical → info by review dynamic-execution lib/transform/esmLoader.js:7897:29

    `eval` called with a non-literal expression (ast pass, confidence 0.90)

        const fileName = import_url2.default.pathToFileURL(file);
        const esmImport = () => eval(`import(${JSON.stringify(fileName)})`);
        if (loaderChannel) {
    likely benign LLM, confidence 0.75 eval used to emit a native dynamic import() of a local file URL, hidden from the bundler.
    Reasoning

    eval wraps import() of a file URL built with JSON.stringify from a local file path. This is a known pattern for hiding import() from bundlers so it stays a native dynamic import at runtime. The input is a local test or config path, not untrusted network data, so the eval is not an obvious dropper.

  56. info critical → info by review dynamic-execution lib/transform/esmLoader.js:7899:13

    `eval` called with a non-literal expression (ast pass, confidence 0.90)

        if (loaderChannel) {
          await eval(`import(${JSON.stringify(fileName + ".esm.preflight")})`).catch((error) => debugTest("Failed to load preflight for " + file + ", source maps may be missing for errors thrown during loading.", error)).finally(nextTask);
        }
        return await esmImport().finally(nextTask);
    likely benign LLM, confidence 0.75 eval of import() of a local .esm.preflight file, with errors caught and logged.
    Reasoning

    Same pattern as the sibling eval: a preflight module import of a local file path derived from the file name, wrapped in eval so bundlers leave it alone. It is a legitimate ESM loader technique and the input is not attacker-controlled.

  57. info warn → info by review dynamic-import lib/transform/esmLoader.js:7903:18

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

      }
      const result = require(file);
      const depsCollector = currentFileDepsCollector();
      if (depsCollector) {
    likely benign LLM, confidence 0.80 Loader requires a user-supplied test or config file by path.
    Reasoning

    This is the ESM loader requiring the user's test or config file by path, which is its core purpose. Without the surrounding code it is not possible to see the origin of the path, but the context is a standard file loader with dependency collection.

  58. info whitespace-anomaly lib/worker/workerProcessEntry.js:9:1

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

    var __copyProps = (to, from, except, desc) => {
      if (from && typeof from === "object" || typeof from === "function") {
        for (let key of __getOwnPropNames(from))
          if (!__hasOwnProp.call(to, key) && key !== except)
  59. line length 833 characters (raw pass, confidence 0.50)

        const snapshotPath = template.replace(/\{(.)?testDir\}/g, "$1" + this.project.testDir).replace(/\{(.)?snapshotDir\}/g, "$1" + this.project.snapshotDir).replace(/\{(.)?snapshotSuffix\}/g, this.snapshotSuffix ? "$1" + this.snapshotSuffix : "").replace(/\{(.)?testFileDir\}/g, "$1" + parsedRelativeTestFilePath.dir).rep
  60. info long-line types/test.d.ts:7632:1

    line length 560 characters (raw pass, confidence 0.50)

      video: VideoMode | /** deprecated */ 'retry-with-video' | { mode: VideoMode, size?: ViewportSize, fps?: number, show?: { actions?: { duration?: number, position?: 'top-left' | 'top' | 'top-right' | 'bottom-left' | 'bottom' | 'bottom-right', /** @deprecated Use `style.title` instead. */ fontSize?: number, cursor?: 'no

Reproduce This Scan

Run disclude locally to verify. These commands scan the published file; the "new in this release" marks come from comparing it with the previous release's file, which they don't repeat. 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.3.0
curl -fsSL -o playwright-1.65.0-alpha-2026-10-22.tgz https://registry.npmjs.org/playwright/-/playwright-1.65.0-alpha-2026-10-22.tgz
printf '%s  %s\n' aef2f018c63a372987773f2de15714fffbe382b480c60c2a444ffdb3226bf44a playwright-1.65.0-alpha-2026-10-22.tgz | shasum -a 256 -c -
mkdir pkg && tar -xzf playwright-1.65.0-alpha-2026-10-22.tgz -C pkg --strip-components 1
disclude scan --untrusted --severity info pkg