VNX-506: Embedded Malicious Code: execution of decoded payload
Detects code that decodes an encoded blob (base64, hex, rot13, zlib, marshal, atob, Buffer.from, String.fromCharCode) and executes it with exec/eval, new Function, vm or child_process. Python, JavaScript and TypeScript.
| Field | Value |
|---|---|
| Rule ID | VNX-506 |
| Severity | Medium |
| SARIF level | warning |
| Kind | sast |
| Languages | JavaScript / TypeScript, Python |
| CWE | CWE-506 |
| CAPEC | CAPEC-66 |
| ATT&CK | T1190 |
| CWSS vector | CWSS:1.0/TI:M/AP:RU/AL:S/IC:N/FC:LT/RP:RU/RL:S/AV:L/AS:N/IN:A/SC:A/BI:M/DI:H/EX:M/EC:N/P:C |
| Tags | embedded-malicious obfuscation dropper cwe-506 |
| Source | internal/sast/rules/vnx-506.rego |
Overview
VNX-506 maps to CWE-506: Embedded Malicious Code. Legitimate code has no reason to hide its source. Decoding a blob and executing the result is how droppers in install scripts and backdoored packages keep a reviewer from reading what they do.
- Python:
exec()/eval()(bare, viabuiltins, or__import__) whose argument isb64decode,b32decode,b85decode,a85decode,decodebytes,a2b_base64,bytes.fromhex,unhexlify,codecs.decode,zlib/bz2/lzma/gzip.decompressormarshal.loads. - JavaScript/TypeScript:
eval(),new Function()/Function(),vm.runInThisContext/runInNewContext/runInContext/new vm.Script, andchild_processexec/execSync, whose argument isatob(),Buffer.from(..., 'base64' | 'hex'),String.fromCharCode()orBase64.decode().
The decoder may be inline or assigned to a variable within the 15 lines above (one intermediate assignment allowed).
What Gets Flagged
exec(base64.b64decode(BLOB)) # FLAGGED
raw = zlib.decompress(base64.b64decode(_STAGE))
source = raw.decode("utf-8")
exec(source) # FLAGGED
eval(atob(stage)); // FLAGGED
new Function(Buffer.from(data.p, 'base64').toString('utf8'))(); // FLAGGED
What Is Not Flagged
- Decoded data that is parsed, written or returned:
json.loads(base64.b64decode(...)),JSON.parse(atob(...)),ast.literal_eval(...). - A regular expression’s
.exec(atob(token)). - Executing a constant, or a variable unrelated to the decoded value.
- A decoder applied to request data, or to the output of an encoder (an encode/decode round trip such as
bar = base64.b64decode(base64.b64encode(param.encode()))). The value executed is the program’s own input, not an embedded payload: it is code injection, reported by VNX-94 when it can follow the request, and otherwise by VNX-PY-002 or VNX-NODE-002 as a non-constant eval. - The pattern in comments or string literals, and minified bundles.
On a Python exec/eval of a decoded blob this rule owns the line: VNX-PY-002, which reports any non-constant eval/exec, does not report it as well.
Remediation
- Treat the finding as a possible compromise: find out who added the code and what the payload does (decode it offline, never by running it).
- If the code is legitimate, ship it as plain source.
References
Suppressing this rule
Put a nosec comment on the line, or on line 1 to cover the whole file. Use the comment marker of the file’s language (#, //, -- or ;):
# nosec vnx-506
// nosec vnx-506
Or record an ignore rule: vulnetix ignore add --rule vnx-506 --reason "...". See Suppressing findings.