fix(mock): keep a header named __proto__ in snapshots - #5668
Open
luantaraschi wants to merge 1 commit into
Open
Conversation
normalizeHeaders and both header filters assigned into a plain object, so the __proto__ key reached the Object.prototype setter and the header was dropped. formatRequestKey feeds those headers to createRequestHash, so two requests differing only by that header produced the same snapshot key: one entry in record mode, the wrong response in playback. Writes now go through a setHeader helper using Object.defineProperty, the guard parseHeaders already uses.
7 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This relates to...
I raised this in a comment on #5667 and offered to send it separately. Sending it now that #5663 was approved, since it is the same guard on a subsystem where the consequence is different.
Rationale
Three places in the snapshot mock build a plain object keyed by header name and assign into it:
normalizeHeadersinlib/mock/snapshot-utils.js, both the array and the object branchfilterHeadersForMatchingandfilterHeadersForStorageinlib/mock/snapshot-recorder.js__proto__is a valid header name, and assigning it on a plain object reaches theObject.prototypesetter instead of creating an own property. The value is a string, so the setter does nothing and the header is dropped.It does not stop at a lost header.
formatRequestKeyfeeds those headers tocreateRequestHash, which walksObject.keys(...).sort(), so two different requests produce one snapshot key:In record mode the two collapse into one entry, and in playback the recorded response for one is served for the other.
JSON.parseis the everyday way an own__proto__key shows up, which is exactly how snapshots arrive from disk.There is no
Object.prototypepollution: the setter refuses a string, so the global prototype is untouched.Changes
A
setHeaderhelper insnapshot-utils.jswrites the__proto__key withObject.defineProperty, the guardparseHeadersalready uses inlib/core/util.js. It is exported and used by all three writers.The object stays plain rather than switching to a null prototype, because it is serialized into snapshot files and handed back to user code.
After the change the same pair hashes differently and the header survives:
One test in
test/snapshot-recorder.js, next to the existingformatRequestKeytests.test/snapshot*.js48 passing,test/mock*.js339 passing, lint clean.Features
N/A
Bug Fixes
A header named
__proto__is no longer dropped from a recorded snapshot and no longer makes two different requests share a snapshot key.Breaking Changes and Deprecations
None.
Status