fix: prevent zip-slip path traversal when extracting project archives - #44
Open
Waynting wants to merge 1 commit into
Open
fix: prevent zip-slip path traversal when extracting project archives#44Waynting wants to merge 1 commit into
Waynting wants to merge 1 commit into
Conversation
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
olcli pullandolcli syncextract project zip archives by joining eachentry name directly onto the target directory:
Entry names are taken from the archive as-is, with no check for
..segments, absolute paths, or Windows drive letters. A malicious or
compromised server can therefore craft an archive containing entries like
../../../../home/user/.bashrcand write files outside the targetdirectory on the user's machine (zip-slip, CWE-22).
This matters in practice because olcli explicitly supports self-hosted
Overleaf/ShareLaTeX instances, so the server is not always overleaf.com.
Note that adm-zip's built-in
extractAllTo()has its own traversalprotection, but olcli extracts manually via
entry.getData()+writeFileSync(), which bypasses it.Fix
resolveWithin(baseDir, relativePath)helper insrc/paths.ts.It resolves the candidate path against the base directory and returns
nullunless the result is strictly inside it. This rejects..escapes, absolute paths, Windows drive letters, and sibling-prefix
edge cases (
/tmp/project-evilstring-prefixed by/tmp/project).listed) instead of being written. They are also excluded from the
remoteManifestwritten to.olcli.json, so they can't pollute thedeletion-propagation logic on subsequent syncs.
remoteFilesmap, with a spinner warning. The write loop additionallyre-checks via
resolveWithinas defense in depth.Legitimate archives are unaffected — safe entry names resolve to exactly
the same paths as before.
Testing
test/paths.test.ts(6 cases) using Node's built-innode:test,runnable with the existing
tsxdev dependency — no new dependencies.names on creation, I crafted the zip with Python's
zipfile(whichstores arcnames verbatim) and ran the extraction filter over it:
npx tsc --noEmitpasses with no errors.Side change
Added a
"test": "tsx --test test/*.test.ts"script topackage.json.The publish workflow already runs
npm test --if-present, which waspreviously a no-op — with this script it now acts as a real verification
gate before publishing. Happy to drop this from the PR if you'd prefer to
keep it strictly scoped to the fix.
Checklist
npm test— 6/6 passingnpx tsc --noEmit— clean