Skip to content

fix: address open CodeQL findings#11609

Merged
zkochan merged 9 commits into
mainfrom
codeql-fixes
May 12, 2026
Merged

fix: address open CodeQL findings#11609
zkochan merged 9 commits into
mainfrom
codeql-fixes

Conversation

@zkochan

@zkochan zkochan commented May 12, 2026

Copy link
Copy Markdown
Member

Summary

Resolves the 15 open alerts on https://github.com/pnpm/pnpm/security/code-scanning by addressing all four categories that CodeQL flagged.

Prototype-polluting assignment (3 alerts, product code)

  • pkg-manifest/utils/src/convertEnginesRuntimeToDependencies.ts: the inner write now dispatches over a literal switch on runtimeName, so the assignment is always keyed by 'node' | 'deno' | 'bun'.
  • pkg-manifest/utils/src/updateProjectManifestObject.ts: added an isProtoPollutionKey barrier at the top of the loop so packageSpec.alias can never reach the dynamic property write with __proto__ / constructor / prototype.
  • installing/deps-installer/src/uninstall/removeDeps.ts: the package list is filtered through isProtoPollutionKey once up front, and the dependency record is captured into a local before the loop.

Polynomial ReDoS (2 alerts)

  • deps/inspection/list/src/renderDependentsTree.ts: replace(/\n+$/, '') swapped for a constant-time charCodeAt trim.
  • resolving/npm-resolver/src/fetch.ts: removed the super-linear-backtracking semverRegex and replaced it with an O(n) stripTrailingSemverSuffix that splits on the rightmost @ and semver.valids, with a digit-block fallback so foo1.0.0-style names still produce the existing "Did you mean foo?" hint.

Bad code sanitization (8 alerts, test infrastructure)

  • __utils__/test-ipc-server/src/TestIpcServer.ts: the JSON.stringify(...).slice(1, -1) smell at the source of all 8 test-file alerts is gone. Both sendLineScript and generateSendStdinScript now build the JS source with plain JSON.stringify and delegate shell wrapping to a new wrapNodeEval helper that escapes \\ and " for the outer double-quoted shell argument.

Incomplete sanitization (2 alerts, test file)

  • releasing/commands/test/publish/oidcProvenance.test.ts: .replace('/', '%2f').replaceAll(...) on both flagged lines.

Test plan

  • compile clean across the five touched packages
  • lint clean (only pre-existing jest/no-disabled-tests warnings)
  • pkg-manifest/utils unit tests: 14/14 pass
  • deps/inspection/list unit tests: 21/21 that run pass (two suites fail with a pre-existing module is already linked ESM/Jest issue that reproduces on main)
  • Manual sanity check of TestIpcServer.generateSendStdinScript() / sendLineScript() output – escaping is correct on macOS
  • CI green
  • CodeQL re-scan shows the 15 alerts closed

Written by an agent (Claude Code, claude-opus-4-7).

Summary by CodeRabbit

  • Bug Fixes

    • Secured manifest and dependency operations against prototype-pollution keys to prevent unsafe writes/removals.
    • Replaced a backtracking regex with a linear-time semver-suffix detector for clearer registry 404 hints.
    • Trimmed trailing newlines from rendered dependency trees for cleaner output.
  • Tests

    • Fixed URL-encoding expectations in package-visibility tests.
    • Added coverage for registry-404 hint behavior, edge cases and performance on adversarial inputs.
    • Added tests ensuring prototype-polluting aliases are skipped without mutating Object.prototype.
  • Chores

    • Bumped patch versions for multiple packages.
    • Improved test IPC helpers to use on-disk helper scripts and ensure temp-file cleanup.

Review Change Stack

zkochan added 2 commits May 12, 2026 22:28
* Reject prototype-polluting keys (`__proto__`, `constructor`, `prototype`)
  before dynamic manifest property writes in
  `convertEnginesRuntimeToDependencies`, `updateProjectManifestObject`, and
  `removeDeps`.
* Replace the super-linear-backtracking `semverRegex` in the npm-resolver 404
  hint with an O(n) `stripTrailingSemverSuffix` scanner.
* Swap the `\n+$` regex in `renderDependentsTree` for a constant-time trailing
  newline trim.
* Properly escape `listenPath` and message values in the test IPC server's
  generated `node -e` scripts (no more `JSON.stringify(...).slice(1, -1)`).
* Use `replaceAll` in the oidcProvenance test's URL-encoding stand-in.
Copilot AI review requested due to automatic review settings May 12, 2026 20:32
@coderabbitai

coderabbitai Bot commented May 12, 2026

Copy link
Copy Markdown

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds prototype-pollution guards to manifest writes, replaces a super-linear semver regex with an O(n) scanner for registry-404 hints, introduces on-disk TestIpcServer helper scripts with safe shell quoting, replaces regex newline trimming with a loop helper, and updates tests and changeset metadata.

Changes

Security Fixes and Performance Optimizations

Layer / File(s) Summary
Prototype pollution prevention in manifest operations
core/types/src/misc.ts, installing/deps-installer/src/uninstall/removeDeps.ts, pkg-manifest/utils/src/updateProjectManifestObject.ts, pkg-manifest/utils/src/convertEnginesRuntimeToDependencies.ts, pkg-manifest/utils/test/updateProjectManifestObject.test.ts
Add isProtoPollutionKey and skip/filter prototype-polluting aliases; use guarded Object.hasOwn checks before deleting dependency keys; initialize/use explicit dependency objects when assigning runtime dependencies.
Performance: regex → linear-time scans
resolving/npm-resolver/src/fetch.ts, resolving/npm-resolver/test/registryResponseError.test.ts
Remove semver-regex, add semver import and stripTrailingSemverSuffix/consumeTrailingDigits O(n) helpers; add tests for hint behavior and adversarial input performance.
Trailing-newline trimming
deps/inspection/list/src/renderDependentsTree.ts
Replace replace(/\n+$/, '') with trimTrailingNewlines implemented via a character-code loop.
Test utilities and assertion corrections
__utils__/test-ipc-server/src/TestIpcServer.ts, releasing/commands/test/publish/oidcProvenance.test.ts
Create on-disk helper scripts for TestIpcServer, add quoteShellArg sanitizer, write/cleanup temp helper dir, and change test expectations to use replaceAll('/', '%2f').
Changeset documentation
.changeset/codeql-security-fixes.md
Bump patch versions and document the prototype-pollution guard and semver-parser optimization.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

I'm a rabbit fixing keys and lines,
I hop past proto traps and costly spines.
I swap regex for a tidy scan,
write helpers to quote each shell-bound span.
Quiet paws, secure repo signs. 🐇

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 23.08% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'fix: address open CodeQL findings' directly and clearly summarizes the main objective: resolving 15 open CodeQL alerts across multiple categories (prototype-pollution, ReDoS, sanitization issues). It accurately reflects the changeset's focus.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codeql-fixes

Comment @coderabbitai help to get the list of available commands and usage tips.

Comment thread __utils__/test-ipc-server/src/TestIpcServer.ts Fixed
Comment thread installing/deps-installer/src/uninstall/removeDeps.ts Fixed

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR addresses multiple open CodeQL security alerts across pnpm’s codebase, covering prototype-pollution guards, ReDoS-safe string handling, and safer construction of test IPC shell scripts.

Changes:

  • Replaces potentially prototype-polluting dynamic dependency writes/deletes with guarded or literal-key updates in manifest-related code paths.
  • Removes/avoids potentially super-linear regex patterns (notably semver detection in 404 hints and newline trimming in tree rendering).
  • Refactors TestIpcServer script generation to avoid the JSON.stringify(...).slice(1, -1) pattern by introducing a wrapNodeEval helper.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
resolving/npm-resolver/src/fetch.ts Replaces semver regex matching with an O(n) suffix parser using semver.valid().
releasing/commands/test/publish/oidcProvenance.test.ts Uses replaceAll() for more complete URL encoding in tests.
pkg-manifest/utils/src/updateProjectManifestObject.ts Skips prototype-polluting keys before manifest dependency writes.
pkg-manifest/utils/src/convertEnginesRuntimeToDependencies.ts Uses literal keys in dependency assignment to avoid prototype-polluting assignment alerts.
installing/deps-installer/src/uninstall/removeDeps.ts Filters prototype-polluting keys before dependency deletes and avoids repeated dynamic indexing.
deps/inspection/list/src/renderDependentsTree.ts Replaces trailing-newline regex with a linear scan helper.
.changeset/codeql-security-fixes.md Adds a changeset describing the CodeQL security fixes.
utils/test-ipc-server/src/TestIpcServer.ts Refactors generated scripts and adds wrapNodeEval() to escape code passed to node -e.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread __utils__/test-ipc-server/src/TestIpcServer.ts Outdated
zkochan added 2 commits May 12, 2026 22:49
* `removeDeps`: gate dynamic property reads/deletes behind `Object.hasOwn`
  so the saveType/dependency keys can never resolve to `Object.prototype`
  (closes CodeQL alert 158).
* `TestIpcServer`: stop embedding the listen path and message in `node -e`
  source. Helper scripts are now written to a per-server temp dir at
  `listen()` time and invoked with the path/message passed via argv, so no
  dynamic data flows through shell-quoted JavaScript source. A
  regex-anchored `quoteShellArg` rejects anything outside a known-safe
  character set, removing the cross-platform escaping risk Copilot called
  out (closes CodeQL alert 157).

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
__utils__/test-ipc-server/src/TestIpcServer.ts (1)

81-100: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Clean up the helper temp dir on failure paths too.

helperDir is only removed on the happy-path dispose. If helper-file creation, server.listen(), or server.close() fails, these temp directories are left behind under the system temp dir.

♻️ Suggested cleanup pattern
  public static async listen (handle?: string): Promise<TestIpcServer> {
    const listenPath = computeHandlePath(handle)
    const server = net.createServer()
    const helperDir = await fs.promises.mkdtemp(path.join(os.tmpdir(), 'pnpm-test-ipc-'))
    const stdinHelperPath = path.join(helperDir, 'stdin.cjs')
    const lineHelperPath = path.join(helperDir, 'line.cjs')
-   await Promise.all([
-     fs.promises.writeFile(stdinHelperPath, STDIN_HELPER_SOURCE),
-     fs.promises.writeFile(lineHelperPath, LINE_HELPER_SOURCE),
-   ])
-   const testIpcServer = new TestIpcServer(server, listenPath, {
-     dir: helperDir,
-     stdinHelperPath,
-     lineHelperPath,
-   })
-
-   return new Promise((resolve, reject) => {
-     server.once('error', reject)
-     server.listen(listenPath, () => {
-       resolve(testIpcServer)
-     })
-   })
+   try {
+     await Promise.all([
+       fs.promises.writeFile(stdinHelperPath, STDIN_HELPER_SOURCE),
+       fs.promises.writeFile(lineHelperPath, LINE_HELPER_SOURCE),
+     ])
+     const testIpcServer = new TestIpcServer(server, listenPath, {
+       dir: helperDir,
+       stdinHelperPath,
+       lineHelperPath,
+     })
+     await new Promise<void>((resolve, reject) => {
+       server.once('error', reject)
+       server.listen(listenPath, resolve)
+     })
+     return testIpcServer
+   } catch (err) {
+     server.close()
+     await fs.promises.rm(helperDir, { recursive: true, force: true })
+     throw err
+   }
  }
...
  public [Symbol.asyncDispose] = async (): Promise<void> => {
    const close = promisify(this.server.close).bind(this.server)
-   await close()
-   await fs.promises.rm(this.helperDir, { recursive: true, force: true })
+   try {
+     await close()
+   } finally {
+     await fs.promises.rm(this.helperDir, { recursive: true, force: true })
+   }
  }

Also applies to: 143-146

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@__utils__/test-ipc-server/src/TestIpcServer.ts` around lines 81 - 100, The
temp helper directory (helperDir) and its files (stdinHelperPath,
lineHelperPath) must be removed on all failure paths: wrap the async setup
(mkdtemp + writeFile + new TestIpcServer + server.listen) so that any thrown
error or the server.once('error') rejection triggers cleanup of helperDir (use
fs.promises.rm or equivalent with recursive/force), and also ensure the same
cleanup runs if server.close()/dispose in TestIpcServer fails (add a finally or
error handler in the dispose flow). Update the Promise returned around
server.listen and any code paths near TestIpcServer construction and the dispose
logic referenced around the later block (lines ~143-146) to call the same
removal routine for helperDir on rejection/failure.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@__utils__/test-ipc-server/src/TestIpcServer.ts`:
- Around line 131-140: The current allowlist regex used by quoteShellArg is too
restrictive and also unsafe for POSIX double-quoted strings (it accepts a
trailing backslash and rejects valid tokens like `@scope/pkg` or JSON), so update
TestIpcServer to either document the restriction or make quoting robust: replace
the current quoteShellArg implementation with a safe encoder used by
sendLineScript and generateSendStdinScript (e.g., base64-encode the payload and
decode in the helper, or implement proper POSIX-safe escaping that
disallows/escapes a trailing backslash and supports characters such as @, :, and
braces), and ensure tests/helpers (lineHelperPath/stdinHelperPath) decode/handle
the chosen encoding; reference quoteShellArg, sendLineScript,
generateSendStdinScript and TestIpcServer when applying the change.

---

Outside diff comments:
In `@__utils__/test-ipc-server/src/TestIpcServer.ts`:
- Around line 81-100: The temp helper directory (helperDir) and its files
(stdinHelperPath, lineHelperPath) must be removed on all failure paths: wrap the
async setup (mkdtemp + writeFile + new TestIpcServer + server.listen) so that
any thrown error or the server.once('error') rejection triggers cleanup of
helperDir (use fs.promises.rm or equivalent with recursive/force), and also
ensure the same cleanup runs if server.close()/dispose in TestIpcServer fails
(add a finally or error handler in the dispose flow). Update the Promise
returned around server.listen and any code paths near TestIpcServer construction
and the dispose logic referenced around the later block (lines ~143-146) to call
the same removal routine for helperDir on rejection/failure.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: c40b51ca-6038-4309-aa5a-7c7a21be52fd

📥 Commits

Reviewing files that changed from the base of the PR and between b148eb3 and e2eb44c.

📒 Files selected for processing (2)
  • __utils__/test-ipc-server/src/TestIpcServer.ts
  • installing/deps-installer/src/uninstall/removeDeps.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • installing/deps-installer/src/uninstall/removeDeps.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Analyze (javascript)
  • GitHub Check: Compile & Lint
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{js,ts,tsx,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{js,ts,tsx,jsx}: Use trailing commas in code following Standard Style with modifications
Prefer functions over classes
Declare functions after they are used, relying on hoisting
Functions should have no more than two or three arguments; use a single options object for functions needing more parameters
Organize imports in order: standard libraries, external dependencies (sorted alphabetically), then relative imports

Files:

  • __utils__/test-ipc-server/src/TestIpcServer.ts

Comment thread __utils__/test-ipc-server/src/TestIpcServer.ts
…backslash

Addresses CodeRabbit feedback:
* Add `@` so scoped names like `@scope/pkg` aren't rejected.
* Reject a trailing backslash explicitly — under both POSIX sh and the
  Windows command-line parser the trailing `\\"` consumes the closing
  quote and breaks the command line.
Copilot AI review requested due to automatic review settings May 12, 2026 21:15

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 5 comments.

Comment thread __utils__/test-ipc-server/src/TestIpcServer.ts
Comment thread resolving/npm-resolver/src/fetch.ts
Comment thread pkg-manifest/utils/src/updateProjectManifestObject.ts
Comment thread installing/deps-installer/src/uninstall/removeDeps.ts Outdated
Comment thread pkg-manifest/utils/src/updateProjectManifestObject.ts Outdated
Addresses Copilot PR review:
* Export `isProtoPollutionKey` from `@pnpm/types` and use it from both
  `updateProjectManifestObject` and `removeDeps`, so the allowlist of
  blocked keys lives in one place.
* Add a `RegistryResponseError` hint test covering `foo@1.0.0`,
  `foo1.0.0`, scoped names, and an adversarial all-digits input that
  would have been slow under the old regex.
* Add a test for `updateProjectManifestObject` that verifies the
  prototype-pollution guard skips `__proto__`/`constructor`/`prototype`
  aliases without mutating `Object.prototype`.
* Document the `quoteShellArg` allowlist constraint and the resulting
  throw on `sendLineScript` / `generateSendStdinScript` in the methods'
  JSDoc.
@github-actions

Copy link
Copy Markdown
Contributor

Benchmark Results

# Scenario main branch
1 Headless (warm store+cache) 2.208s ± 0.044s 2.179s ± 0.023s
2 Re-resolution (add dep, warm) 2.862s ± 0.029s 2.846s ± 0.037s
3 Full resolution (warm, no lockfile) 7.285s ± 0.044s 7.259s ± 0.034s
4 Headless (cold store+cache) 5.398s ± 0.124s 5.329s ± 0.126s
5 Cold install (nothing warm) 11.270s ± 0.252s 11.255s ± 0.231s
6 GVS warm reinstall (warm global store) 1.070s ± 0.060s 1.038s ± 0.011s

Run 25763601341 · 10 runs per scenario · triggered by @zkochan

…endencies

The literal-key switch worked but forced a parallel update every time a new
runtime was added to RUNTIME_NAMES. Use the shared `isProtoPollutionKey`
barrier instead — it's unreachable for the current set but keeps the dynamic
assignment safe (and CodeQL quiet) without needing parallel updates.
Copilot AI review requested due to automatic review settings May 12, 2026 21:57
Comment thread pkg-manifest/utils/src/convertEnginesRuntimeToDependencies.ts
…ncies

CodeQL didn't recognise the shared `isProtoPollutionKey` helper as a barrier
on this code path (alert 159 re-opened). Inline the literal equality checks
against `__proto__`/`constructor`/`prototype` so CodeQL accepts them.

A widening `const key: string = runtimeName` is needed so TypeScript allows
the comparison — the loop variable is the narrow `'node' | 'deno' | 'bun'`
literal type. The barrier is still extensible: adding a new runtime to
`RUNTIME_NAMES` requires no change here unless someone tries to add one of
the polluting keys, in which case the guard rejects it.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (1)

utils/test-ipc-server/src/TestIpcServer.ts:100

  • TestIpcServer.listen() creates a temp helperDir and writes helper scripts before calling server.listen(), but if writeFile() or server.listen() fails (e.g. EADDRINUSE/permission errors), the Promise rejects and the temp directory is never cleaned up. Consider wrapping the setup + listen flow in a try/catch (and also cleaning up on the error path) so helperDir is removed when listen() fails.
  public static async listen (handle?: string): Promise<TestIpcServer> {
    const listenPath = computeHandlePath(handle)
    const server = net.createServer()
    const helperDir = await fs.promises.mkdtemp(path.join(os.tmpdir(), 'pnpm-test-ipc-'))
    const stdinHelperPath = path.join(helperDir, 'stdin.cjs')
    const lineHelperPath = path.join(helperDir, 'line.cjs')
    await Promise.all([
      fs.promises.writeFile(stdinHelperPath, STDIN_HELPER_SOURCE),
      fs.promises.writeFile(lineHelperPath, LINE_HELPER_SOURCE),
    ])
    const testIpcServer = new TestIpcServer(server, listenPath, {
      dir: helperDir,
      stdinHelperPath,
      lineHelperPath,
    })

    return new Promise((resolve, reject) => {
      server.once('error', reject)

      server.listen(listenPath, () => {
        resolve(testIpcServer)
      })
    })

Comment thread pkg-manifest/utils/src/updateProjectManifestObject.ts Outdated
Comment thread installing/deps-installer/src/uninstall/removeDeps.ts Outdated
…oveDeps

Addresses Copilot review feedback: silently skipping aliases like
\`constructor\` and \`prototype\` would have broken \`pnpm add constructor\`
and \`pnpm remove prototype\`, even though those are legitimate npm package
names.

* \`updateProjectManifestObject\`: instead of skipping, use a small
  \`defineDepEntry\` helper that goes through \`Object.defineProperty\` so
  pollution-key aliases become regular own data properties (and CodeQL
  recognises defineProperty as a sanitiser). \`findSpec\`/\`guessDependencyType\`
  now check ownership with \`Object.hasOwn\` so a missing pollution-key
  alias no longer reads through to the prototype chain.
* \`removeDeps\`: drop the up-front filter. Every dynamic delete is already
  guarded by \`Object.hasOwn\`, so pollution-key names are safe to pass
  through and are removed only if they're real own properties.
* Drop the now-unused \`isProtoPollutionKey\` export from \`@pnpm/types\`
  and its changeset entry — no published API churn.
@zkochan zkochan merged commit 50b33c1 into main May 12, 2026
15 checks passed
@zkochan zkochan deleted the codeql-fixes branch May 12, 2026 22:51
zkochan added a commit that referenced this pull request May 12, 2026
CodeQL alert 159 (js/prototype-polluting-assignment) stayed open after
#11609 was merged: the barrier I added in convertEnginesRuntimeToDependencies
checked a re-aliased `key` variable, but the actual write went through the
original loop variable `runtimeName`. CodeQL's local data-flow analysis
followed `runtimeName` and didn't see the barrier.

Replace the inline barrier + dynamic assignment with `Object.defineProperty`,
which is the CodeQL-blessed sanitiser for this pattern. The dependency-map
write now produces a regular own data property even if a future entry in
`RUNTIME_NAMES` happens to match an inherited name like `__proto__`, so the
analyser is happy without depending on any pre-write check.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants