Repository navigation
fix(artifacts): refuse an ASAR header that declares one member name twice - #10552
Merged
Merged
Conversation
…wice JSON.parse keeps only the last value for a repeated name, so an ASAR header that declared a path twice listed one member, hid the other and still reported complete coverage. Add findDuplicateJsonMember, an iterative scan of validated JSON text that does not recurse, so the deeply nested headers REA already admits stay readable. readAsarHeader now refuses a repeated member name as a malformed index, the same way the listing refuses unsafe path components.
Codex Review Summary: ✅ CompletedThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
Contributor
[Medium impact] The PR appears safe to merge; no actionable defect was found. SummaryThe PR rejects repeated JSON member names at
Reviews (2) · Last reviewed commit: "fix(artifacts): refuse an ASAR header th..." · Reviewed by Greptile |
4 of 15 tasks
11 tasks done
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.
Summary
An ASAR header that declares the same member name twice in one directory listed only the last declaration. The first member disappeared from the listing while coverage still read as complete. No issue was filed; this was found by a structural audit and reproduced by running the listing on such a header.
Problem and expected behavior
{"files":{"a.js":{"size":10,"offset":"0"},"a.js":{"size":5,"offset":"10"},"b.js":{...}}}.a.jssize 5,b.js), no limitation, and complete coverage. The 10-byte declaration is silently dropped.format) archive. This matches how the listing already refuses unsafe path components and how extraction refuses colliding paths.Change and scope
src/domain/jsonDuplicateMember.ts:findDuplicateJsonMember(text)scans already-validated JSON text and returns the first repeated member name and its offset. The scan is iterative because REA admits ASAR headers nested thousands of levels deep (asarListingAdmission.test.tsuses 3,500), which a recursive parser would refuse or overflow on.readAsarHeaderruns it afterJSON.parsesucceeds and throwsArtifactReaderFailure("format", ...)naming the member and offset.src/browser/ElectronFileScope.tshas its own headerJSON.parsefor live Electron file scope. There, last-wins matches what Electron itself loads, so it is left alone.Contract and boundary impact
Semantic owner and earliest changed stage:
readAsarHeader(src/artifacts/AsarHeader.ts), before the listing is built. All ASAR readers that use it are affected.Contribution scope fit and linked maintainer decision: not applicable.
CLI and MCP/tool-catalog contract: no schema change. Archives with repeated member names now fail as malformed instead of listing a partial tree.
Provider, bridge, target-format, or platform compatibility: Electron's own reader keeps the last value. REA now refuses these archives instead of choosing one.
Evidence, artifact, provenance, or reconstruction contract: no partial listing is produced for an ambiguous index.
Target selection, authority, upstream behavior, and cleanup details: none.
Generated metadata, package, or installation impact: none.
Read existing files or captured data.
Evidence and regression coverage
src/artifacts/AsarHeader.test.ts: "refuses a header that declares one member name twice".src/domain/jsonDuplicateMember.test.ts: escaped names, nested scopes, arrays, string values equal to names, and 200,000 levels of nesting.Validation performed
npm run test:local -- src/artifacts/AsarHeader.test.tson unfixed source: the new test failed (1 failed, 4 passed).npm run test:focused --onjsonDuplicateMember.test.tsplus all 19 ASAR test files: 20 files and 158 tests passed. An earlier attempt using the recursive lossless JSON parser failed the 3,500-level nesting test, which is why the scan is iterative.npm run check:fastpassed.oxfmtpassed on the changed files.Compatibility, safety, and release
Author readiness
Human owner:
Before merge
type(scope): outcome.