Snuffleupagus: a PHP extension that blocks functions and virtual-patches vulnerabilities
Security module for php7 and php8 - Killing bugclasses and virtual-patching the rest!
At a glance
- What is it?
- Snuffleupagus is a PHP 7 and 8 module that raises the cost of attacking a PHP application by killing whole classes of bugs and by letting administrators write rules that abort specific calls. It works at the engine level rather than in application code, which is what makes it able to stop things like unserialize based code execution.
- Who is it for?
- Snuffleupagus suits a PHP operator who cannot patch application code quickly, because it can block a function call or a dangerous argument pattern from configuration alone and log the violation. It does not suit a team that wants per-request policy in application logic, since the rules live in a separate configuration file evaluated by the engine, and it does not suit a PHP version outside the 7 and 8 range the module targets.
- Can I use it commercially?
- Yes, with conditions. LGPL-3.0 is a weak copyleft licence: you can use it inside commercial and closed-source software, but if you distribute changes to its own files, you must publish those changes under the same licence.
- Is it still maintained?
- Yes. The repository last received commits 7 days ago.
- What is it written in?
- Mainly PHP, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Rules live in a config file and abort the call at the engine level
Snuffleupagus is a PHP 7 and 8 module designed to drastically raise the cost of attacks against websites by killing entire bug classes. It also provides a virtual-patching system, which the documentation describes as letting administrators fix specific vulnerabilities and audit suspicious behaviours without touching the PHP code.
The mechanism is rule files. The project ships various example rules in a config directory, and the syntax is compact.
# Harden the `chmod` function
sp.disable_function.function("chmod").param("mode").value_r("^[0-9]{2}[67]$").drop();
# Mitigate command injection in `system`
sp.disable_function.function("system").param("command").value_r("[$|;&`\\n]").drop();Each rule names a function, names a parameter, and matches the parameter's value against a regular expression. When the value matches, the call is aborted. The first example neutralises chmod calls with a dangerous mode, and the second blocks a system() argument containing a shell metacharacter.
The value_r construct is doing the real work. It is a regular expression match against the argument, not an equality check, which is what lets one rule cover a class of attack rather than a single known bad string. That is the difference between virtual patching and a blacklist, and it is why the documentation calls the rules powerful yet simple to write.
When a rule fires, the log records what happened.
[snuffleupagus][0.0.0.0][disabled_function][drop] The execution has been aborted in /var/www/index.php:2, because the return value (0) of the function 'strpos' matched a rule.The line carries the client address, the rule category, the action taken, the file and line where the call happened, and the function involved. That is a genuinely useful incident record, because it points at the source location rather than only at the fact that something was blocked.
The bug classes it kills are named specifically
The list of killed vulnerability classes is more useful than the general claim, because each entry tells you what kind of rule you would write.
Unserialize-based code execution is on the list, which is the classic PHP object injection problem where a crafted serialized string triggers magic methods during deserialization. mail-based code execution is there too, referring to the case where a mail header carries an injection payload. Cookie-stealing XSS is covered, so a rule can prevent a script from reading the cookie that a cross-site scripting payload needs. File-upload based code execution is on the list, weak PRNG is covered, XXE is covered, and filter based remote code execution with assorted shenanigans is covered.
The unserialize entry is the one that makes this project different from an application-level filter. An unserialize gadget chain works because the engine calls magic methods on objects it constructs from attacker data. A PHP function filter or a library check in application code can be bypassed by finding another path into the same behaviour. A module that can disable the unserialize call itself removes the class of attack rather than one instance of it.
The project credits the Suhosin project as a huge source of inspiration, and also credits Suhosin-ng for its experimentations and contributions, with NLNet listed as a sponsor of that work. Suhosin was the well known PHP hardening extension of the earlier era, and the lineage explains the design: this is a return to the idea of doing security enforcement in the engine.
The audience is PHP operators and administrators, not application developers. The documentation frames the value in terms of what an administrator can do without a code change, and the topics on the repository include hardening, virtual-patching and security.
The hardening features are configuration, not code changes
Beyond the rules, there is a set of hardening features that switch on behaviour rather than block specific calls.
Automatic secure and samesite flags for cookies means the module sets those attributes on responses so a session cookie is not sent over plain HTTP and is not attached to cross-site requests. Bundled sets of rules detect post-compromise behaviours, which is a different category from preventing the initial intrusion: these rules look for the traces an attacker leaves after they are already in, and they are the virtual-patching system's other half.
Global strict mode and type-juggling prevention address a PHP-specific class of bug. Strict types makes comparisons behave as declared rather than coercing, and type juggling prevention stops the loose comparison behaviour that has produced authentication bypasses.
Whitelisting of stream wrappers restricts which PHP stream wrappers a script can use, which limits the file access an attacker can reach through a URL include or similar mechanism. Preventing writable files execution stops a script that has been dropped in a writable directory from being run. A whitelist and blacklist for eval controls dynamic code execution. Enforcing TLS certificate validation when using curl makes the library refuse to talk to a server with an invalid certificate. Request dumping capability is the debugging counterpart, letting an operator capture raw requests for audit.
All of these live outside the PHP code, which is the point. An administrator can turn them on for an entire server, or for a specific site, without editing a line of application source, and without depending on the application's own quality.
The project also states that there is no noticeable performance impact, linking to a benchmark write-up, and that the code base is relatively sane, with a test suite close to full coverage, every commit tested on several distributions, an enforced clang-format style, and the use of coverity, codeql and scan-build.
Building it means phpize, configure and a shared object
Snuffleupagus is a C extension for PHP, so installation is a compilation step rather than a package manager operation. The Makefile at the root of the repository is the reference for the process.
The release target runs phpize, configures with the module enabled, builds, and strips the resulting shared object.
cd $(SRC); phpize
cd $(SRC); ./configure --enable-snuffleupagus
make -C $(SRC)
strip $(SRC)/.libs/snuffleupagus.soThe install target depends on release and then runs make install from the source directory. A debug build is a separate target that adds debug flags.
cd $(SRC); if [[ ! -f configure ]]; then phpize; fi; \
./configure --enable-snuffleupagus --enable-debug --enable-debug-stderr && \
make clean ; make -j4A Docker target exists for working against a current PHP image, bind-mounting the repository.
docker run -it -v "$$(pwd)":/sp $(DOCKER_IMAGE) /bin/bashThe linked-clone target is the one worth understanding, because it is how a developer works on the module against several PHP versions at once. It creates a directory named after the clone, symlinks the shared source files into it, copies the tests, and tells you to compile with a debug build and a SRC override. The target refuses to run without a CLONE argument, printing an example of the form to use, and refuses to overwrite an existing clone directory. The message it prints tells you to compile a debug build with make compile_debug and a SRC override pointing at the clone you just made.
make linked-clone CLONE=php8.1For end users there is a download page with packages for each distribution, and the release binaries are on GitHub. A repology badge shows the packaging status across distributions.
Tests run through a target that builds a release build and then an incremental build followed by the test suite, with the exit status reported so a failure is not swallowed.
Release naming and cadence
The project uses an unusual version naming scheme, and the recent tags make it obvious what it is.
The three most recent releases are v0.14.0 named Blumenbach, v0.13.0 named Elephas and v0.12.0 named Stegodontidae. The naming is taxonomic: an elephant is an elephant, which is what the project calls itself in the logo, and the species names track the version number.
The version numbers themselves show a steady cadence rather than a burst. v0.12.0 landed on 2025-08-19, v0.13.0 on 2026-01-07, and v0.14.0 on 2026-09-01. The last push to the repository was on 2026-10-16, so work continued after the 0.14.0 tag.
The project is LGPL-3.0 licensed, and the repository carries both a LICENSE file and a PHP_LICENSE file, which is the convention for a PHP extension that links against the PHP runtime.
Two badges tell you something about how the code is checked. There is a Coverity Scan badge, pointing at a project page for static analysis, and a CodeQL badge. The CI workflows are split by PHP major version, with separate distributions_php7.yml and distributions_php8.yml workflows, which matches the module's support for both lines. The documentation is hosted on readthedocs, and the repository contains a doc/ directory that the documentation states you can build yourself.
Where Snuffleupagus is the wrong tool
The first wrong-tool case is a PHP application outside the 7 and 8 range. The module is described as a security module for php7 and php8, and the two CI workflows cover exactly those lines. There is no path for an application still on PHP 5.
The second case is a team that wants policy in application code. Snuffleupagus rules are evaluated by the engine, globally or per site, and they are written in their own configuration syntax rather than in PHP. That is the right place for a blanket rule like blocking unserialize, and the wrong place for a rule that depends on the business context of a particular call, such as allowing a specific upload path only for one internal service. Application-level frameworks own that.
The third case is a team expecting the module to be a complete security programme. Blocking unserialize is valuable, but it does not remove the need to fix the injection that produced the malicious payload in the first place, and the bundled post-compromise detection rules are explicitly about what happens after an intrusion, not a substitute for preventing it. The documentation is careful to say the virtual patching system lets an administrator fix specific vulnerabilities, which is a stopgap by construction.
There is also an operational constraint that comes with being a compiled extension. It has to be built against your PHP, it has to be loaded into every SAPI that serves your sites, and an extension fault takes down the process rather than degrading gracefully. The bundled rules are examples to adapt rather than a finished policy, and getting the regular expressions right for your own application is where the real work is.
For an organisation that has to reason about who is responsible for security, the LGPL-3.0 licence matters in a specific way. The module is a shared library loaded into PHP, and the LGPL conditions are written for that kind of linking, which lets you use it in a proprietary stack while keeping modifications to the module itself open. Read the PHP_LICENSE file as well as the main one, since the extension links against the PHP runtime.
Editorial conclusion
Snuffleupagus suits a PHP operator who cannot patch application code quickly, because it can block a function call or a dangerous argument pattern from configuration alone and log the violation. It does not suit a team that wants per-request policy in application logic, since the rules live in a separate configuration file evaluated by the engine, and it does not suit a PHP version outside the 7 and 8 range the module targets. Before adopting, build it from source with the release target or take a distribution package, confirm the module loads in your SAPI, and test the log format of a dropped call, since the example log line shows the file, the line number and the value that matched.
Frequently asked questions
What is Snuffleupagus used for?
Snuffleupagus is a PHP 7 and 8 module that raises the cost of attacks against a website by killing whole classes of bugs and by providing virtual patching. Administrators can write rules that abort specific function calls and audit suspicious behaviour without changing the PHP code.
How do I write a Snuffleupagus rule?
Rules name a function, a parameter and a regular expression to match the argument value, with the drop action aborting the call. The shipped examples harden chmod by matching its mode parameter and mitigate command injection in system by matching shell metacharacters in the command parameter.
How do I build Snuffleupagus from source?
The Makefile release target runs phpize, configures with --enable-snuffleupagus, builds and strips the shared object, and the install target installs it. A debug build is available through the compile_debug target, and a linked-clone target lets you build against a specific PHP version such as php8.1.
Which vulnerability classes does Snuffleupagus block?
The documentation lists unserialize-based code execution, mail-based code execution, cookie-stealing XSS, file-upload based code execution, weak PRNG, XXE, and filter based remote code execution. On the hardening side it offers automatic secure and samesite cookie flags, global strict mode, type-juggling prevention, stream wrapper whitelisting and TLS certificate validation for curl.
What license is Snuffleupagus released under?
Snuffleupagus is licensed under LGPL-3.0, with the LICENSE file and a separate PHP_LICENSE file in the repository. The releases are named v0.12.0 Stegodontidae, v0.13.0 Elephas and v0.14.0 Blumenbach, and the last push was on 2026-10-16.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/jvoisin-snuffleupagus)Was this useful?