SW-SKL-004: Encoded payload decoded and executed (malicious indicator)
Last updated 7 November 2026
| Fact | Value |
|---|---|
| Severity | Critical |
| Checks | Skill package |
| Malicious indicator | Yes. An open finding from this rule quarantines the skill: it cannot be curated while the finding stays open. |
| OWASP Agentic Top 10 | ASI04 |
| OWASP MCP Top 10 | None mapped |
| NIST SP 800-53 | SR-3 (provisional mapping to SP 800-53 base controls) |
| First shipped in | Scanner 0.1.0 |
What it detects
The rule reads every script file of the package (extensions .sh, .bash, .zsh, .py, .js, .mjs, .ts, .rb, .ps1 and .pl) and the fenced code blocks of every Markdown file, and joins lines the shell would join: a trailing backslash, or a line that ends in a pipe, && or ||. A command is reported when it holds both a decoder and an executor.
The decoders are base64 -d (and its long and capital forms), b64decode(, atob(, openssl enc -d, xxd -r, gunzip -c and zcat. The executors are a pipe into sh, bash, zsh, python, node, perl or ruby (with or without sudo), eval(, exec(, subprocess, os.system, child_process, new Function( and sh -c. Each matching command is one finding, critical, and is marked as a malicious indicator.
Why it matters
Code that is stored as an encoded string cannot be read by anyone reviewing the file, and honest scripts have little reason to do it. Decoding and running in one step is the usual shape of a hidden payload, and the agent runs it with the access it already has. The scanner maps this rule to OWASP ASI04, Agentic Supply Chain Vulnerabilities, and to NIST SP 800-53 control SR-3, Supply Chain Controls and Processes.
Example
This skill ships a script that decodes a base64 string and pipes the result into a shell. The string here only encodes a harmless command, but the rule does not decode it: the decoder and the pipe into bash are enough.
.claude/skills/payload-runner/SKILL.md
---
name: payload-runner
description: Runs the helper script for the demo project.
license: MIT
version: 1.0.0
---
# Payload runner
Run scripts/run.sh to set up the demo project..claude/skills/payload-runner/scripts/run.sh
#!/bin/sh
echo "ZWNobyBoZWxsbw==" | base64 -d | bashThe finding is on the script's second line, with the command as its evidence.
How to fix
Write the command out in the script, where a reviewer can read it, and delete the decoding step. If the content really has to be stored encoded, such as a binary asset, decode it to a file in one step and run nothing in the same command.
If it is a false positive
A build script that decodes a certificate or a configuration value with base64 and hands it to a program is not a payload, but it can look like one when the program is a shell or an interpreter. Accept the finding with a note that says what is decoded and where it comes from.
If the finding is not a problem in your case, accept it with a note: in the dashboard a manager or owner can accept a finding and the note is kept with it; with the scanner on its own, add it to the baseline file with a reason and an expiry date.