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

playwright 1.65.0-alpha-2026-10-15

Source
https://github.com/microsoft/playwright
Commit scanned
a038fe7e0eb9 (recorded by npm)
Directory
packages/playwright (only this part of the repository was scanned)
Compared with
647e485f2ba5 (0 signals introduced since)
Files
133 scanned, 13 skipped (binary, oversized, or unrecognised)
Signals
0 critical · 0 warn · 12 info
Scan time
6.5 s
LLM review
Reviewed by claude-haiku-5-5 (Anthropic): 10 of 10 warn and critical signals; 10 demoted to info.
Disclude version
4.0.0
Scanned (UTC)
2026-10-15 14:11

Signals

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

  1. info warn → info by review dynamic-execution packages/playwright/src/isomorphic/teleReceiver.ts:462:90

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

      private _onStdIO(type: JsonStdIOType, testId: string | undefined, resultId: string | undefined, data: string, isBase64: boolean) {
        const chunk = isBase64 ? ((globalThis as any).Buffer ? Buffer.from(data, 'base64') : atob(data)) : data;
        const test = testId ? this._tests.get(testId) : undefined;
    likely benign LLM, confidence 0.90 Base64 decoding of test stdio output with Buffer/atob fallback.
    Reasoning

    atob is used as a fallback decoder for stdio chunk data in a test reporter receiver. The decoded value is treated as data, not evaluated or fetched dynamically. Legitimate browser/Node compatibility code.

  2. info warn → info by review dynamic-import packages/playwright/src/package.ts:22:28

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

    export const packageRoot = path.join(__dirname, '..');
    export const packageJSON = require(path.join(packageRoot, 'package.json'));
    
    export function libPath(...parts: string[]): string {
    likely benign LLM, confidence 0.85 Loads the package's own package.json via a computed path.
    Reasoning

    require of path.join(packageRoot, 'package.json') is a standard way to load the package's own manifest. The path is built from __dirname, not attacker input.

  3. info warn → info by review dynamic-import packages/playwright/src/reporters/coverage.ts:120:27

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

          const resolveFrom = (name: string) => 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 Requires istanbul coverage library resolved from config dir.
    Reasoning

    Resolves istanbul modules relative to the configured config directory, a common plugin-resolution pattern for optional coverage dependencies. No untrusted input appears in the snippet.

  4. info warn → info by review dynamic-import packages/playwright/src/reporters/coverage.ts:121: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 Requires istanbul-lib-report via resolved path.
    Reasoning

    Same resolveFrom pattern loading istanbul-lib-report; the specifiers are hardcoded package names.

  5. info warn → info by review dynamic-import packages/playwright/src/reporters/coverage.ts:122: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 Requires istanbul-reports via resolved path.
    Reasoning

    Same resolveFrom pattern loading istanbul-reports with hardcoded names; standard optional dependency loading.

  6. info warn → info by review dynamic-import packages/playwright/src/transform/babelBundle.ts:169: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.85 Loads Babel plugins by name from configuration.
    Reasoning

    Requires Babel plugin names from a configured list to build the transform pipeline. This is the expected plugin loading mechanism for a bundler; the names come from the project's own configuration.

  7. info warn → info by review dynamic-import packages/playwright/src/transform/transform.ts:268:74

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

    
      const { babelTransform }: { babelTransform: BabelTransformFunction } = require(libPath('transform', 'babelBundle'));
      const babelResult = babelTransform(originalCode, filename, !!moduleUrl, pluginsEpilogue, useDefineForClassFields, jsx);
      if (!babelResult?.code)
    likely benign LLM, confidence 0.85 Requires internal babelBundle module by computed path.
    Reasoning

    Loads the internal babelBundle module via libPath with fixed segments. Internal modularization, not attacker-controlled.

  8. info critical → info by review dynamic-execution packages/playwright/src/transform/transform.ts:296:29

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

        const fileName = url.pathToFileURL(file);
        const esmImport = () => eval(`import(${JSON.stringify(fileName)})`);
    
        // For ESM imports handled by the asynchronous loader, issue a preflight to populate
    likely benign LLM, confidence 0.80 eval-based dynamic import of test file URL to load ESM modules.
    Reasoning

    eval is used to perform a dynamic import of a file URL so that ESM loading works from CommonJS context, avoiding TypeScript rewriting import() into require. The argument is JSON.stringify of a file URL derived from the test file path. Unusual but a known, purposeful pattern in test runners; the critical severity reflects the eval pattern rather than malicious content.

  9. info critical → info by review dynamic-execution packages/playwright/src/transform/transform.ts:303: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: any) => debugTest('Failed to load preflight for ' + file + ', source maps may be missing for errors thrown during loading.', error))
              .finally(nextTask);
    likely benign LLM, confidence 0.80 eval-based dynamic import of ESM preflight module.
    Reasoning

    Same eval(import()) trick to preload an ESM preflight module from a file-derived name, guarded by loaderChannel and with error handling. Legitimate loader mechanism; the eval wrapper is a known workaround for import() transpilation.

  10. info warn → info by review dynamic-import packages/playwright/src/transform/transform.ts:315:18

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

      }
      const result = require(file);
      const depsCollector = cc.currentFileDepsCollector();
      if (depsCollector) {
    likely benign LLM, confidence 0.90 Requires the test file during module loading.
    Reasoning

    Requires the test file being loaded, which is the core purpose of a test runner's module loader. Expected behavior.

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

    interface TsConfig {
      extends?: string;
      compilerOptions?: {
        baseUrl?: string;
  12. 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. 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/microsoft/playwright playwright && cd playwright
git checkout a038fe7e0eb955ef41db53d40a859ce487889b6d
disclude scan --severity info --diff 647e485f2ba563ef055e2368fcc67bde67789cf0 packages/playwright