Security Operations
Archive Extraction: Prevent Path Traversal Writes
Extract ZIP and other archives safely with destination containment checks, link policies, resource limits and isolated staging before files reach production.
In this article
An archive extractor must not let an entry name decide an unrestricted output path. A malicious or malformed archive can contain paths that escape the intended directory, symbolic links or resource-expanding content. Validate extraction destinations and limits before writing files, then stage the result in an isolated location.
This is a defensive guide for upload and import services you control. It is distinct from checking whether an uploaded file has the right extension: a correctly identified archive can still contain dangerous filesystem instructions.
Define the destination boundary
Choose a fresh extraction directory that is not served publicly and contains no application configuration, credentials or executable files. Give the extractor only the filesystem permissions it needs. Do not extract user archives directly into a deployment directory.
For each entry, combine its name with the extraction root, normalize the result using the platform's path library and confirm it remains inside the intended root. Compare paths structurally, not with a naive string prefix. A sibling directory whose name begins like the root is still outside it.
Be careful with absolute paths, drive letters and separator rules across operating systems. An archive prepared on Windows may be handled by a Linux service, or vice versa. The extractor's documented behavior matters more than how a filename looks in an upload form.
Treat links as a separate policy
A safe-looking entry can write through a symbolic link created by an earlier entry. Containment checks based only on a lexical path may not detect that filesystem behavior. Decide whether links are needed at all; many content-import services can reject them.
If links must be supported, use an extraction implementation with a documented safe policy and test it against the target filesystem. Do not build an ad hoc link resolver around untrusted input and assume it handles every race or platform edge case.
Also reject device entries and other special filesystem types unless your service explicitly requires and safely handles them. A content upload should ordinarily produce ordinary files and directories, not a reconstruction of an arbitrary machine's filesystem.
Limit expanded work, not only upload size
An archive can be small in transit and large after decompression. Set limits for total expanded bytes, entry count, individual entry size, path length, nesting depth and processing time. Enforce limits during streaming extraction where possible.
Stop the operation when a limit is reached and remove the isolated temporary output using your normal cleanup procedure. Do not continue publishing a partial directory as though import succeeded. Track failures as failures even when some files were written successfully.
The OWASP file-upload guidance provides broader upload controls. For archives, the important extra decision is what expanded content is permitted to become part of the application.
Create a sanitized extraction manifest
{"archive_id":"fixture-07","entries":12,
"expanded_bytes":24000,"links_allowed":false,
"result":"staged","rejected_entries":[]}The values are illustrative. Record the accepted relative paths, sizes and final disposition. Avoid exposing private customer filenames in unrestricted logs. A redacted manifest can be reviewed with JSON Viewer and compared across extractor versions using JSON Diff.
A manifest helps reconcile what the upload claimed to contain with what was accepted. It does not substitute for containment enforcement. Generate it from the extractor's actual decisions rather than trusting metadata supplied inside the archive.
Test with harmless boundary fixtures
In an isolated test directory, create archives containing ordinary nested files, rejected parent-directory segments, absolute paths, duplicate names and link entries. Assert that no write occurs outside the extraction root. Use harmless text files rather than executable payloads.
Include a destination that already contains a link, repeated entry names and path names that differ only by case. Test the operating systems you actually support. The point is to catch filesystem interpretation differences, not merely to validate a regular expression.
For each rejected case, verify cleanup and the user-facing error. A secure rejection that leaves orphaned files indefinitely can become an operational problem. Keep enough evidence to diagnose the failure without retaining an entire confidential upload unnecessarily.
Publish only after content review
Once extraction succeeds, validate file types and expected structure in staging. An image package should not silently introduce server configuration or scripts. Use an allowlist that matches the import feature and rename accepted files to controlled identifiers where appropriate.
Move the reviewed result into its final destination with a deliberate publication step. Keep extraction and publication separate so a partial failure cannot expose unreviewed files. If import includes database records, plan how filesystem and database outcomes are reconciled.
A clear failure is safer than a partial success
Reject escaped paths, unsupported links and exceeded limits before publication. A useful result states which archive was processed, what was accepted and whether the final content was committed. For structural checks on the manifest, JSON Viewer offers a readable local inspection path without pretending to be an archive security scanner.