Skip to content

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 IDLangSeverityDetects
js-exec-decoded-payloadJS/TSCRITICALeval/Function on a decoded or obfuscated payload
py-exec-decoded-payloadPythonCRITICALexec/eval on a decoded or obfuscated payload
php-exec-decoded-payloadPHPCRITICALeval on a decoded or obfuscated payload
js-obfuscation-global-loader-markerJS/TSCRITICALObfuscated loader marker (global assigned via a symbolic key)
js-obfuscation-fromcharcode-chainJS/TSHIGHLong String.fromCharCode chains assembling hidden strings
obf-packed-line (heuristic)allHIGHVery long line carrying several obfuscation markers
js-dynamic-eval-nonliteralJS/TSMEDIUMeval/Function on a non-literal
py-dynamic-exec-nonliteralPythonMEDIUMeval/exec/compile on a non-literal
php-eval-nonliteralPHPMEDIUMeval on a non-literal

Exfiltration & credential theft ​

Rule IDLangSeverityDetects
js-exfil-to-networkJS/TSCRITICALCookies, env or storage flowing to a network request
py-env-exfiltrationPythonCRITICALEnvironment or credential data flowing to a network request
net-canary-domainanyCRITICALKnown exfiltration, OAST canary or webhook domains
js-serialize-environmentJS/TSHIGHSerialising the whole process.env
sensitive-credential-file-accessanyMEDIUMReferences to credential files (~/.aws/credentials, SSH keys…)
js-network-to-ipJS/TSMEDIUMRequests to a hard-coded IP address
py-network-to-ipPythonMEDIUMRequests to a hard-coded IP address

Command execution & webshells ​

Rule IDLangSeverityDetects
php-webshell-superglobal-to-shellPHPCRITICAL$_GET/$_POST/… flowing into a shell function
py-shell-taintedPythonCRITICALUntrusted input flowing into a shell command
py-process-exec-lolbinPythonCRITICALSpawning download tools / LOLBins (curl, wget, …)
js-child-process-execJS/TSMEDIUMCommand execution via child_process
py-subprocess-shell-truePythonMEDIUMsubprocess with shell=True, no taint detected
php-shell-nonliteralPHPMEDIUMShell function called on a non-literal

Deserialisation ​

Rule IDLangSeverityDetects
py-deserialization-untrustedPythonCRITICALUntrusted data passed to pickle/marshal
php-unserialize-untrustedPHPCRITICALRequest data passed to unserialize()
py-unsafe-deserializationPythonMEDIUMpickle/marshal loading, source unknown
php-unserialize-callPHPMEDIUMunserialize() on a non-literal

Supply chain (install-time code) ​

Rule IDLangSeverityDetects
npm-install-hook-commandpackage.jsonCRITICALpreinstall/postinstall scripts that download or run shells
py-setuptools-install-hookPythonMEDIUMsetup.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 IDSeverityMeaning
engine-scan-failedHIGHSemgrep couldn't analyse the file at all (e.g. a timeout)
engine-partial-parseMEDIUMSome 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/.