mleczakm / zip-bomb-honeypot
Symfony event subscriber that traps vulnerability scanners probing for common exploit paths (.env, wp-admin, PHP shells, ...) by serving a small, highly compressible zip bomb instead of a 404.
Requires
- php: ^8.4
- symfony/event-dispatcher: ^6.4 || ^7.0 || ^8.0
- symfony/http-foundation: ^6.4 || ^7.0 || ^8.0
- symfony/http-kernel: ^6.4 || ^7.0 || ^8.0
Requires (Dev)
- phpunit/phpunit: ^11.0 || ^12.0
Suggests
None
Provides
None
Conflicts
None
Replaces
None
README
A Symfony event subscriber that traps vulnerability scanners and bots probing for common
exploit paths — .env, wp-admin, PHP shells, SQL dumps, .aws/credentials, etc. — by
serving a small, highly compressible zip bomb instead of a 404.
The zip bomb is built from the "overlapping local file headers + DEFLATE quoting" technique described in David Fifield's USENIX WOOT 2019 paper "A better zip bomb": a single highly-compressed "kernel" is referenced by many overlapping local file headers, so the file on the wire stays tiny (a few hundred bytes by default) while unzip tools that don't guard against overlapping entries can expand it to gigabytes.
Install
composer require mleczakm/zip-bomb-honeypot
Usage
In a Symfony app with autoconfiguration enabled (the default in services.yaml), the
subscriber is picked up automatically once it's registered as a service:
# config/services.yaml services: Mleczakm\ZipBombHoneypot\MaliciousRequestSubscriber: ~ Mleczakm\ZipBombHoneypot\HoneypotResponder: ~ Mleczakm\ZipBombHoneypot\MaliciousRequestPathMatcher: ~
That's it — any request whose path matches a known scanner pattern (checked both on the
initial kernel.request and again on a resulting 404 via kernel.exception) gets a zip
bomb response instead of continuing through routing or your 404 page.
What it matches
See MaliciousRequestPathMatcher for the exact
pattern list — PHP file probes, .env* files, .aws/, WordPress paths, common config/backup
filenames, .vscode/, *.sql dumps, and app_dev.php/.
Tuning the payload
HoneypotResponder builds the response via ZipBombGenerator::generate(), which you can call
directly if you want a different size/shape:
use Mleczakm\ZipBombHoneypot\ZipBombGenerator; $zip = new ZipBombGenerator()->generate( numFiles: 10, // overlapping local file header entries kernelSize: 100_000, // uncompressed kernel size in bytes, before overlap multiplication );
License
MIT