Skip to content

fix(core): reject ZIP entries not listed in MANIFEST (closes #1)#3

Merged
emretinaztepe merged 3 commits into
mainfrom
fix/issue-1-zip-extraneous-files
Apr 26, 2026
Merged

fix(core): reject ZIP entries not listed in MANIFEST (closes #1)#3
emretinaztepe merged 3 commits into
mainfrom
fix/issue-1-zip-extraneous-files

Conversation

@emretinaztepe

Copy link
Copy Markdown
Contributor

Summary

Closes #1 — ZIP verification bypass via unsigned extra files (CWE-349).

verifyManifestHashes only walked manifest.files, so any extra file appended to a signed ZIP was silently accepted as part of the authenticated package. The reporter's PoC (re-zip a signed package with an injected evil.sh) still returned valid: true.

Changes

  • New VerifyErrorCode.UNEXPECTED_FILE.
  • New findUnexpectedFiles helper that fails closed for any ZIP entry not in manifest.files (excluding MANIFEST.json itself).
  • Wired into both verifyPackage and verifyZipFromAuthor so the fix covers both verification entry points.
  • Centralized failure-reason formatting via failedFileReason.
  • Regression test: rejects ZIP with extra unsigned file not in manifest (reproduces the PoC from issue ZIP verification bypass — unsigned extra files accepted as valid package content #1).

Test plan

Notes

Patch release will follow once #2 is also merged.

Made with Cursor

verifyManifestHashes only walked manifest.files, so any extra file
appended to a signed ZIP was silently accepted as part of the
authenticated package. After signing, an attacker could re-zip the
archive with additional files (e.g. postinstall.sh) and verifyPackage
/ verifyFromAuthor still returned valid: true.

Add a bidirectional check that fails closed when a ZIP entry is not
listed in the manifest (MANIFEST.json itself excepted). Apply in both
verifyPackage and verifyZipFromAuthor. Introduce
VerifyErrorCode.UNEXPECTED_FILE and a regression test reproducing the
PoC from issue #1.

Fixes #1

Made-with: Cursor
-e
Signed-off-by: Emre Tinaztepe <emre@binalyze.com>

Copilot AI 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.

Pull request overview

Fixes a ZIP verification bypass where unsigned extra ZIP entries could be appended after signing and still pass verification, by failing closed on any ZIP entry not listed in MANIFEST.json.

Changes:

  • Added VerifyErrorCode.UNEXPECTED_FILE and surfaced it through verification results.
  • Implemented findUnexpectedFiles() and wired it into both verifyPackage() and verifyZipFromAuthor().
  • Added a regression test reproducing the PoC (extra unsigned file appended to a signed ZIP).

Reviewed changes

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

File Description
packages/core/src/types.ts Adds UNEXPECTED_FILE error code for unexpected ZIP entries.
packages/core/src/verify.ts Rejects ZIP entries not present in manifest.files and centralizes file-failure reason formatting.
packages/core/test/verify.spec.ts Adds a regression test ensuring appended unsigned files are rejected.

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

Comment on lines 732 to 736
}

const fileResults = await verifyManifestHashes(manifest, files);
const extras = findUnexpectedFiles(manifest, files);
const fileResults = [...(await verifyManifestHashes(manifest, files)), ...extras];
const hasFailedFile = fileResults.some((f) => !f.valid);

Copilot AI Apr 26, 2026

Copy link

Choose a reason for hiding this comment

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

verifyZipFromAuthor() now rejects ZIP entries not present in manifest.files, but there’s no regression test exercising this code path (only verifyPackage() is covered). Add a test that calls verifyFromAuthor(tamperedZip, { fetch: mockFetchWithKeys([...]), resolveTxt: false }) and asserts it returns valid: false with VerifyErrorCode.UNEXPECTED_FILE and includes the unexpected entry in details.files.

This ensures the security fix can’t regress in the author-verification entry point.

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good catch — added in 1ea22de. New test rejects ZIP with extra unsigned file via verifyFromAuthor (UNEXPECTED_FILE) exercises verifyFromAuthor with the same tampered-ZIP scenario and asserts code: UNEXPECTED_FILE and that evil.sh shows up in details.files as a failed entry.

Address Copilot review feedback on #3: the fix is applied in both
verifyPackage and verifyZipFromAuthor, but only verifyPackage was
covered by a regression test. Add a test exercising verifyFromAuthor
with an injected unsigned file to ensure the author-verification
entry point cannot regress.

Made-with: Cursor
-e
Signed-off-by: Emre Tinaztepe <emre@binalyze.com>
…neous-files

Made-with: Cursor

# Conflicts:
#	packages/core/test/verify.spec.ts
-e
Signed-off-by: Emre Tinaztepe <emre@binalyze.com>
Copilot AI review requested due to automatic review settings April 26, 2026 15:16
@emretinaztepe
emretinaztepe merged commit d205516 into main Apr 26, 2026
4 checks passed

Copilot AI 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.

Pull request overview

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


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

Comment thread packages/core/src/types.ts
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.

ZIP verification bypass — unsigned extra files accepted as valid package content

2 participants