T03 · Remote Payload Retrieval and Execution
- Location
SKILL.md:32- Finding
Mutable Remote Python Payload Downloaded Without Integrity Verification
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill appears to be a document text extractor, but its install instructions tell users to download and run mutable remote Python code that is not pinned or verified.
Review before installing. Prefer running the bundled doc_extractor.py from the reviewed package instead of following the curl command, or require a pinned commit plus checksum/signature verification. Limit batch extraction to directories you intentionally choose, and pin PyMuPDF if you need PDF support.
SKILL.md:32Mutable Remote Python Payload Downloaded Without Integrity Verification
doc_extractor.py:72Unpinned PyMuPDF Dependency Installation Guidance
The skill description emphasizes PDF/DOCX/TXT extraction, but the documentation also advertises batch folder processing, output writing, format listing, and self-tests. In an agent environment, undeclared recursive directory processing and file writes broaden the operational scope beyond simple single-document extraction, which can expose more data than users expect or modify the filesystem unexpectedly.
The skill description emphasizes PDF/DOCX/TXT extraction, but the documentation also advertises batch folder processing, output writing, format listing, and self-tests. In an agent environment, undeclared recursive directory processing and file writes broaden the operational scope beyond simple single-document extraction, which can expose more data than users expect or modify the filesystem unexpectedly.
The skill description emphasizes PDF/DOCX/TXT extraction, but the documentation also advertises batch folder processing, output writing, format listing, and self-tests. In an agent environment, undeclared recursive directory processing and file writes broaden the operational scope beyond simple single-document extraction, which can expose more data than users expect or modify the filesystem unexpectedly.
The skill advertises downloadable Python code and shell-based usage, but the manifest shown here declares no explicit tool scope or permissions boundaries. In an agent setting, missing scope declarations can cause the runner to grant broader file and shell access than users expect, increasing the chance of unintended filesystem reads/writes or command execution.
This function executes an arbitrary Python file from the target product folder as part of verification. In a CI or local review workflow, a malicious skill author can place code in that file so the verifier runs attacker-controlled code automatically, turning validation into code execution.
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
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)
This code executes any test_*.py or *_test.py file found in the untrusted product folder. An attacker can submit a malicious test file and gain code execution during CI verification, potentially exposing CI secrets, modifying artifacts, or pivoting into the build environment.
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):
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)")
The skill description emphasizes page/paragraph structure, and the DOCX extractor comment says it adds paragraph breaks, but the code first collects all text nodes and only afterward appends newline markers for every paragraph. That behavior does not preserve actual paragraph boundaries and can contradict the documented extraction intent.
The manifest description limits supported inputs to PDF, DOCX, and TXT with structure preservation, but the implementation accepts and extracts plain text from additional formats including Markdown, CSV, JSON, XML, HTML, logs, YAML, TOML, INI, and CFG. This expands the skill's advertised scope beyond the stated document types.
No suspicious patterns detected.