fix(config): use Object.hasOwn instead of in operator in restoreOriginalValueOrThrow#99152
Conversation
|
Codex review: needs maintainer review before merge. Reviewed July 3, 2026, 6:35 AM ET / 10:35 UTC. Summary PR surface: Source 0, Tests +10. Total +10 across 2 files. Reproducibility: yes. Source inspection shows current main accepts inherited prototype keys through Review metrics: none identified. Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Risk before merge
Maintainer options:
Next step before merge
Security Review detailsBest possible solution: Land the narrow helper-level own-property check with the focused restore regression once the normal required merge gates are satisfied. Do we have a high-confidence way to reproduce the issue? Yes. Source inspection shows current main accepts inherited prototype keys through Is this the best way to solve the issue? Yes. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against f84bcdb4d79c. Label changesLabel changes:
Label justifications:
Evidence reviewedPR surface: Source 0, Tests +10. Total +10 across 2 files. View PR surface stats
What I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
|
Onyx_bot ReviewBug confirmed. The restoreOriginalValueOrThrow function uses params.key in params.original — the in operator traverses the prototype chain, so toString in {} returns true, silently returning an inherited prototype method instead of throwing. Fix confirmed. Object.hasOwn(params.original, params.key) checks own enumerable properties only — correct. Test confirmed. Regression test iterates 4 prototype-key names against an empty original and asserts result.ok === false. Directly exercises the previously-broken path. Assessment: Correct. 1-line fix, right API, adequate regression coverage. Ready to merge. |
|
Maintainer deep review and proof for exact head
No config shape, persisted data, protocol, docs, or migration surface changes. |
Dependency graph guard clearedThis PR no longer has blocked dependency graph changes. A future dependency graph change requires a fresh
|
c8ed81f to
d5700c0
Compare
|
Merged via squash.
|
Summary
Use
Object.hasOwn()instead of theinoperator inrestoreOriginalValueOrThrow()to prevent prototype chain pollution when restoring redacted config values.What Problem This Solves
When a config key named after an
Object.prototypeproperty (e.g.,toString) is redacted and needs restoration,restoreOriginalValueOrThrowuseskey in originalto check if the original value exists. On a plain object without that key,"toString" in originalreturnstrue(matchingObject.prototype.toString), causing the function to return a native function instead of the expected config value.Code evidence: In
src/config/redact-snapshot.ts:541,if (params.key in params.original)traverses the prototype chain.params.originalis aRecord<string, unknown>plain object, andparams.keycomes from redacted config paths.Root Cause
inoperator checks the entire prototype chain, not just own propertiesObject.hasOwn()(ES2022+) correctly checks only own propertiesWhy This Fix
Object.hasOwnpattern as fix(markdown-core): use Object.hasOwn instead of in operator in parseFrontmatterBlock #99129 and fix(config): use Object.hasOwn instead of in operator in unsetConfigValueAtPath #99148Evidence
restoreRedactedValues({toString: REDACTED}, {}, hints)returns ok=true with a function valueReal Behavior Proof
Before (on main)
After (with fix)
Tests and Validation
src/config/redact-snapshot.test.tscovering 4 prototype keys