A ZIP archive is a list of entry names plus a promise about each entry's size and checksum. Every one of those is attacker-controlled, and extraction code routinely trusts all of them — joining the entry name straight onto an output path, pre-allocating from the declared size, and never checking the CRC it just read.
These archives are built byte by byte rather than with a ZIP library, because a correct library refuses to produce them. That is also why the hex view matters more here than on the text formats: you can see the local file header, the entry name with its traversal sequence intact, and the central directory that declares it.
- What is Zip Slip?
- An archive entry whose name contains ../ sequences, so that joining it onto your extraction directory produces a path outside that directory. An extractor that writes to the joined path without normalising it will write wherever the entry points. The fix is to resolve the final path and verify it is still inside the destination — checking for the literal string '..' is not sufficient, because encodings and backslashes bypass that check.
- Why build these by hand instead of with a ZIP library?
- Because the most valuable fixtures are archives that are wrong, and a correct ZIP library will not produce them. JSZip normalises ../ out of entry names, which removes the entire point of a traversal fixture, and no conforming writer will emit an entry whose declared size disagrees with its data. These are written byte by byte so every header field stays under control.
- Is the compression bomb fixture actually dangerous?
- No. A real decompression bomb is highly repetitive content actually deflated, so a few kilobytes on disk expand to gigabytes in memory. This fixture stores its megabyte uncompressed, so the archive is honest about its size — it demonstrates the content shape without being a weapon. The lesson it teaches is to budget total extracted bytes rather than trusting archive size.
- Are these files dangerous?
- No. They are inert test files for checking your own import pipeline. Nothing here executes on its own — the fixtures that model injection or traversal exist so you can verify your own code rejects them, and the resource-exhaustion ones are deliberately scaled down so they demonstrate the behaviour without taking down the machine you are testing from.
- Why does the page show raw bytes?
- Because most of these cases are invisible in a text preview. A byte order mark renders as nothing, a bare carriage return looks identical to a CRLF, and a NUL looks like the end of the string. The hex view highlights exactly which bytes matter and explains each one when you hover it.
- Does my pass/fail progress get saved?
- Yes, in your own browser only, and separately for each format. The workflow expects you to leave the page, run a fixture through your parser, and come back — so results persist locally. Nothing is uploaded, and clearing site data clears them.
- Is this free?
- Yes. Every fixture is generated in your browser, with no signup and no upload.