npm / playwright / 1.64.1-beta-1792067398000

playwright 1.64.1-beta-1792067398000

Source
https://github.com/microsoft/playwright
Commit scanned
0915b2e91289 (recorded by npm)
Directory
packages/playwright (only this part of the repository was scanned)
Compared with
cfe490d941f9 (0 signals introduced since)
Files
130 scanned, 13 skipped (binary, oversized, or unrecognised)
Signals
0 critical · 0 warn · 12 info
Scan time
7.6 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 a Buffer/atob fallback.
    Reasoning

    atob is used only as a fallback when Buffer is absent, to decode base64 stdio chunks from the test runner's own JSON output. It decodes data into a log chunk and never feeds eval, fetch, or a dropper.

  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.90 Loads the package's own package.json via a computed path.
    Reasoning

    The require target is path.join of the package root and the literal 'package.json', a fixed local metadata file read at load time. The non-literal specifier is a bundler-compatibility pattern, not an attack.

  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-lib-coverage resolved relative to the config directory.
    Reasoning

    The module is resolved with require.resolve from the configured config directory, for standard istanbul packages. The specifier is a fixed string passed through resolution, which is ordinary plugin-loading behaviour.

  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 resolved relative to the config directory.
    Reasoning

    Same resolveFrom pattern loading the fixed istanbul-lib-report package. Nothing is decoded or fetched from an untrusted source.

  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 resolved relative to the config directory.
    Reasoning

    Same resolveFrom pattern loading the fixed istanbul-reports package, a normal coverage reporter dependency.

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

    The specifier is a plugin name from the configured epilogue list, so it is a dynamic plugin load. This is how Babel plugins are normally attached, and the name comes from the project's own build configuration.

  7. info warn → info by review dynamic-import packages/playwright/src/transform/transform.ts:234: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, jsx);
      if (!babelResult?.code)
    likely benign LLM, confidence 0.90 Loads the internal babelBundle module through a path helper.
    Reasoning

    The require loads the bundled babelBundle module through libPath with fixed literal segments. This is internal module loading with no untrusted input.

  8. info critical → info by review dynamic-execution packages/playwright/src/transform/transform.ts:260: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.85 Uses eval to issue a native dynamic import of a local ESM file URL.
    Reasoning

    eval wraps a dynamic import() of a file URL built with JSON.stringify. This is a known workaround so the TypeScript transpiler does not rewrite import() into require() for ESM loading. The input is a local test file path, not attacker-supplied data.

  9. info critical → info by review dynamic-execution packages/playwright/src/transform/transform.ts:267: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.85 Uses eval to dynamically import a local ESM preflight module.
    Reasoning

    Same eval-wrapped import() trick, here loading a local preflight marker for source-map handling. Errors are caught and logged, and the path is derived from the test file being loaded.

  10. info warn → info by review dynamic-import packages/playwright/src/transform/transform.ts:279: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 being loaded by the runner.
    Reasoning

    require(file) loads the test file the runner was asked to run, with dependency collection around it. Loading user test code is the tool's core function, not obfuscation.

  11. file mixes tab and space indentation (9 tab-indented and 90 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 0915b2e9128968bba8f5fdfee57b6bca3dab5fbe
disclude scan --severity info --diff cfe490d941f992655948eee8fd4fd94e1c4234bf packages/playwright