Detection rules
The bundled rule pack runs on Semgrep. Rules are grouped into high-confidence rules, which flag code that is very rarely legitimate, and low-confidence rules, which flag risky capabilities worth a look. Low-confidence rules report at MEDIUM, so --min-severity HIGH hides them.
Use the rule ID in the ruleId field of the ignore file.
Dynamic execution & obfuscation
| Rule ID | Lang | Severity | Detects |
|---|---|---|---|
js-exec-decoded-payload | JS/TS | CRITICAL | eval/Function on a decoded or obfuscated payload |
py-exec-decoded-payload | Python | CRITICAL | exec/eval on a decoded or obfuscated payload |
php-exec-decoded-payload | PHP | CRITICAL | eval on a decoded or obfuscated payload |
js-obfuscation-global-loader-marker | JS/TS | CRITICAL | Obfuscated loader marker (global assigned via a symbolic key) |
js-obfuscation-fromcharcode-chain | JS/TS | HIGH | Long String.fromCharCode chains assembling hidden strings |
obf-packed-line (heuristic) | all | HIGH | Very long line carrying several obfuscation markers |
js-dynamic-eval-nonliteral | JS/TS | MEDIUM | eval/Function on a non-literal |
py-dynamic-exec-nonliteral | Python | MEDIUM | eval/exec/compile on a non-literal |
php-eval-nonliteral | PHP | MEDIUM | eval on a non-literal |
Exfiltration & credential theft
| Rule ID | Lang | Severity | Detects |
|---|---|---|---|
js-exfil-to-network | JS/TS | CRITICAL | Cookies, env or storage flowing to a network request |
py-env-exfiltration | Python | CRITICAL | Environment or credential data flowing to a network request |
net-canary-domain | any | CRITICAL | Known exfiltration, OAST canary or webhook domains |
js-serialize-environment | JS/TS | HIGH | Serialising the whole process.env |
sensitive-credential-file-access | any | MEDIUM | References to credential files (~/.aws/credentials, SSH keys…) |
js-network-to-ip | JS/TS | MEDIUM | Requests to a hard-coded IP address |
py-network-to-ip | Python | MEDIUM | Requests to a hard-coded IP address |
Command execution & webshells
| Rule ID | Lang | Severity | Detects |
|---|---|---|---|
php-webshell-superglobal-to-shell | PHP | CRITICAL | $_GET/$_POST/… flowing into a shell function |
py-shell-tainted | Python | CRITICAL | Untrusted input flowing into a shell command |
py-process-exec-lolbin | Python | CRITICAL | Spawning download tools / LOLBins (curl, wget, …) |
js-child-process-exec | JS/TS | MEDIUM | Command execution via child_process |
py-subprocess-shell-true | Python | MEDIUM | subprocess with shell=True, no taint detected |
php-shell-nonliteral | PHP | MEDIUM | Shell function called on a non-literal |
Deserialisation
| Rule ID | Lang | Severity | Detects |
|---|---|---|---|
py-deserialization-untrusted | Python | CRITICAL | Untrusted data passed to pickle/marshal |
php-unserialize-untrusted | PHP | CRITICAL | Request data passed to unserialize() |
py-unsafe-deserialization | Python | MEDIUM | pickle/marshal loading, source unknown |
php-unserialize-call | PHP | MEDIUM | unserialize() on a non-literal |
Supply chain (install-time code)
| Rule ID | Lang | Severity | Detects |
|---|---|---|---|
npm-install-hook-command | package.json | CRITICAL | preinstall/postinstall scripts that download or run shells |
py-setuptools-install-hook | Python | MEDIUM | setup.py overriding install commands to run code |
Scan coverage
These findings mean code was not fully checked. Malware can hide in code a scanner can't read, so they are reported instead of being skipped silently.
| Rule ID | Severity | Meaning |
|---|---|---|
engine-scan-failed | HIGH | Semgrep couldn't analyse the file at all (e.g. a timeout) |
engine-partial-parse | MEDIUM | Some lines couldn't be parsed; the finding points at the skipped lines |
If one of these appears on code you trust, for example a file using syntax the parser doesn't support yet, suppress it for that file in the ignore file:
json
{ "path": "src/legacy/template.php", "ruleId": "engine-partial-parse", "reason": "Mixed HTML/PHP template; reviewed by hand" }Other engines
- GuardDog (
deps) findings keep GuardDog's own rule IDs.threat-*rules map to CRITICAL,capability-*rules to MEDIUM, and metadata rules to HIGH. Details → - malcontent (
--with-malcontent) findings keep malcontent's rule IDs. On source files they are capped at MEDIUM.
The rule sources live in src/malware_detector/rules/.