Here’s a fun security fact: most PHP application vulnerabilities aren’t in PHP itself — they’re in your code or your plugins. And most WAFs (Web Application Firewalls) sit at the HTTP layer, sniffing requests for suspicious patterns. That works okay. But what if the attacker’s payload gets through anyway? What if it’s encoded weirdly, or the WAF has a blind spot?
That’s where PHP-Snuffleupagus comes in. It’s a PHP extension that adds a security layer inside PHP itself — at the interpreter level, where every function call happens, every variable gets read, and every cookie gets set. An attacker can trick your WAF. They can’t trick the PHP interpreter. Snuffleupagus runs inside it.
Think of it as a bouncer who lives in your kitchen instead of at the front door. Even if someone sneaks in through the window, they still can’t touch the stove.

What Does PHP-Snuffleupagus Actually Block?
- Dangerous function calls —
system(),exec(),eval(),shell_exec(),passthru(). If your app gets code-injected, these are the functions the attacker wants. Snuffleupagus blocks them at the interpreter, before they run. - SQL injection and XSS patterns — detected in function arguments before they reach your database or output.
- Type juggling exploits — PHP’s famously weird
==behaviour ("0e12345" == "0"istrue!) can bypass password checks. Snuffleupagus enforces strict comparisons. - Unsafe file uploads — validate uploads with a script before PHP processes them. Block PHP files disguised as images.
- Deserialization attacks — PHP’s
unserialize()is a classic attack vector. Disable it for untrusted input. - Cookie security — enforce
Secure,HttpOnly, andSameSiteflags on every cookie your app sets, even if your app code forgot.
PHP-Snuffleupagus vs ModSecurity: Different Layers, Both Useful
People often ask: “I already have ModSecurity WAF on NGINX. Do I need Snuffleupagus too?” Yes — they’re complementary, not competing.
| ModSecurity (NGINX WAF) | PHP-Snuffleupagus | |
|---|---|---|
| Where it runs | NGINX process, HTTP layer | PHP interpreter, inside PHP-FPM |
| What it sees | Raw HTTP headers, URL, request body | PHP function calls, arguments, variables |
| What it blocks | Malicious HTTP patterns (SQLi in URL, XSS in form) | Dangerous functions, type juggling, bad cookies |
| Bypass risk | Encoding tricks, HTTP-level obfuscation | Very hard to bypass — runs inside the interpreter |
Run both. ModSecurity filters bad HTTP traffic before it reaches PHP. Snuffleupagus controls what PHP is allowed to do if something gets through. Defence in depth — the thing security people keep saying that actually makes sense here.
Installation
PHP-Snuffleupagus is available from the myguard repository for PHP 7.0 through 8.4 on Debian and Ubuntu:
# Add the myguard repository (if not already done)
wget -qO- https://deb.myguard.nl/gpg.key
| gpg --dearmor > /usr/share/keyrings/myguard-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/myguard-archive-keyring.gpg]
https://deb.myguard.nl stable main"
| tee /etc/apt/sources.list.d/myguard.list
apt update
# Install for your PHP version
apt install php8.3-snuffleupagus
# Verify it loaded
php-fpm8.3 -m | grep snuffleupagus
# Restart PHP-FPM
systemctl restart php8.3-fpm
New to the myguard repository? Follow the setup guide to add it in under a minute.
Replace 8.3 with your PHP version. Supported: 7.0, 7.1, 7.2, 7.3, 7.4, 8.0, 8.1, 8.2, 8.3, 8.4.
Configuration: The Good Stuff
The config lives at /etc/php/8.3/fpm/conf.d/snuffleupagus.ini and references rule files at /etc/snuffleupagus/default.rules. The golden rule: start with simulation mode, not blocking. Log what Snuffleupagus would block, tune out false positives, then switch to enforcement.
Block Dangerous Functions
# Simulation mode first (logs but doesn't block)
sp.disable_function.function("system").simulation();
sp.disable_function.function("exec").simulation();
sp.disable_function.function("eval").simulation();
sp.disable_function.function("shell_exec").simulation();
sp.disable_function.function("passthru").simulation();
sp.disable_function.function("proc_open").simulation();
sp.disable_function.function("unserialize").simulation();
# Once confirmed no false positives: switch .simulation() to .drop()
sp.disable_function.function("system").drop();
Enforce Cookie Security Flags
# Force Secure + SameSite on session cookies
# Catches cookies your app sets without proper flags
sp.cookie.name("PHPSESSID").samesite("strict").secure();
sp.cookie.name("wordpress_logged_in*").samesite("lax").secure();
Block PHP File Uploads
# Validate uploads with a script (exit non-zero to reject)
sp.upload_validation.script("/usr/bin/check-upload.sh").drop();
#!/bin/bash
# /usr/bin/check-upload.sh
# Reject PHP files disguised as images
file "$1" | grep -qi php && exit 1
exit 0
Per-Pool Rules (Different Rules Per Site)
Apply different rule sets per PHP-FPM pool. Strict rules for one legacy app, relaxed rules for a modern one on the same server:
; /etc/php/8.3/fpm/pool.d/myapp.conf
php_admin_value[snuffleupagus.config] = /etc/snuffleupagus/myapp.rules
Monitor the Log
tail -f /var/log/snuffleupagus.log
Each blocked (or simulated) event is logged with the rule that triggered it, the function called, and the arguments. Use this to tune your rules and catch false positives before going into enforcement mode. Don’t skip this step — seriously.

Frequently Asked Questions
- Does PHP-Snuffleupagus work with WordPress?
- Yes, with care. WordPress and its plugins use a broad set of PHP functions. Always start with .simulation() mode to log what would be blocked, identify false positives, then switch to .drop(). The official docs include a WordPress-specific rule set as a starting point.
- Will Snuffleupagus break my application?
- Possibly — which is exactly why simulation mode exists. Start with .simulation(), read the logs, whitelist legitimate function calls, then enforce. Jumping straight to .drop() on a live site is how you get 2am emergency calls.
- Can I run PHP-Snuffleupagus and ModSecurity at the same time?
- Yes. They operate at completely different layers and don’t interfere with each other. ModSecurity is in the NGINX process; Snuffleupagus is inside PHP-FPM. Both can be active simultaneously and complement each other perfectly.
- Does PHP-Snuffleupagus affect performance?
- Minimally. Most rules are checked at function call time, not on every opcode. For a typical PHP-FPM application the overhead is under 1% of request time — completely imperceptible to users.
- What PHP versions are supported?
- PHP 7.0 through 8.4. Install the package matching your PHP version: php7.4-snuffleupagus, php8.1-snuffleupagus, etc. Multiple versions can coexist on the same server.
- What is type juggling and why is it dangerous in PHP?
- PHP’s loose comparison (==) has famous quirks: ‘0e12345’ == ‘0’ is true because both are treated as floating-point zero in scientific notation. Attackers exploit this to bypass password hash comparisons. Snuffleupagus enforces strict comparisons in sensitive contexts with sp.type_juggling.enable().
Related Posts
- How to Optimize NGINX and Angie for Maximum Performance and Security — full security guide including ModSecurity WAF
- TLS Configuration for NGINX: Getting A+ on SSL Labs — harden TLS alongside your PHP security stack
- openssl-nginx: Dedicated OpenSSL for NGINX and Angie — the TLS performance layer underneath your stack
- NGINX and Angie on Kubernetes: Helm, Ingress, WAF — WAF in containerised environments