T09 · Insecure Skill Coding Practices
- Location
scripts/pdf-to-md.py:20- Finding
Predictable Shared Temporary Dependency Directory Enables Local Module Poisoning
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill is a coherent document converter, but it needs review because it automatically installs runtime packages and can upload document images to an external API with weak enforcement boundaries.
Review this skill before installing if you handle confidential documents. Use it only in a sandboxed environment, avoid the vision option unless you are comfortable sending document images to Anthropic, and prefer a version that preinstalls locked dependencies instead of running pip during each conversion.
scripts/pdf-to-md.py:20Predictable Shared Temporary Dependency Directory Enables Local Module Poisoning
scripts/pdf-to-md.py:21Runtime Dependency Downloads Lack Cryptographic Integrity Verification
The skill text claims optional outbound API use for vision extraction while the permissions list is empty, which is a concrete security governance issue, not just a product mismatch. In a document-conversion context, this is more dangerous because uploaded files often contain confidential business or personal information, and undeclared network transmission undermines informed consent and policy enforcement.
The skill text claims optional outbound API use for vision extraction while the permissions list is empty, which is a concrete security governance issue, not just a product mismatch. In a document-conversion context, this is more dangerous because uploaded files often contain confidential business or personal information, and undeclared network transmission undermines informed consent and policy enforcement.
The skill text claims optional outbound API use for vision extraction while the permissions list is empty, which is a concrete security governance issue, not just a product mismatch. In a document-conversion context, this is more dangerous because uploaded files often contain confidential business or personal information, and undeclared network transmission undermines informed consent and policy enforcement.
The skill text claims optional outbound API use for vision extraction while the permissions list is empty, which is a concrete security governance issue, not just a product mismatch. In a document-conversion context, this is more dangerous because uploaded files often contain confidential business or personal information, and undeclared network transmission undermines informed consent and policy enforcement.
The skill declares shell, file-write, and external-network behavior in its workflow, but it does not declare any explicit tool scope or permission boundaries. That creates an authorization/visibility gap: reviewers and enforcement systems cannot easily restrict the skill from writing files, invoking scripts, or sending document content to external services, which is especially risky because uploaded documents may contain sensitive data.
The script invokes pip at runtime via subprocess, which introduces package-management and network-fetch capability into a document conversion tool. Even though the command is argument-safe and versions are pinned, this still expands the attack surface: execution now depends on external package indexes, installer behavior, and whatever code runs during package installation or import in the execution environment.
# ── isolated dependency install ───────────────────────────────────────────────
_DEP_DIR = Path("/tmp/office_md_deps")
_DEP_DIR.mkdir(exist_ok=True)
subprocess.run(
[
sys.executable, "-m", "pip", "install", "--quiet",
"--target", str(_DEP_DIR),
Runtime pip installation gives this CSV-to-Markdown utility capabilities beyond simple file conversion, including network access and package installation side effects. In the context of an agent skill, that is dangerous because a benign-seeming conversion request can trigger code that reaches out to package infrastructure and executes installer/import-time code not directly related to the user's document.
The script performs a runtime pip install via subprocess, which expands its behavior from document conversion into package installation and code retrieval. Even though the package is version-pinned and shell=False avoids classic command injection, this still introduces supply-chain and network-execution risk because every run may fetch and install code into /tmp before processing the document.
# ── isolated dependency install ───────────────────────────────────────────────
_DEP_DIR = Path("/tmp/office_md_deps")
_DEP_DIR.mkdir(exist_ok=True)
subprocess.run(
[
sys.executable, "-m", "pip", "install", "--quiet",
"--target", str(_DEP_DIR),
Installing dependencies at runtime is not necessary for ordinary DOCX-to-Markdown conversion and gives the skill a broader capability than its stated purpose. This creates avoidable exposure to dependency confusion, compromised package sources, and unexpected network activity during execution.
Although the broader manifest mentions Claude vision for scanned/image-based documents with user confirmation, this script directly performs an HTTP POST to an external API when --allow-vision is set. For a local DOCX-to-Markdown converter, outbound network access is a sensitive capability that should be explicitly declared and tightly controlled rather than embedded as an implementation surprise.
When --allow-vision is supplied, embedded images are sent to an external API without any in-script confirmation or prominent transmission warning at the moment data leaves the system. Because DOCX files may contain sensitive screenshots, scanned pages, or embedded documents, this can lead to unintended disclosure if the flag is passed by upstream automation or user misunderstanding.
The script installs Python packages at runtime by invoking pip, which introduces unnecessary network activity and code supply-chain risk for a document conversion tool. Even though versions are pinned and shell injection is avoided by passing an argument list, package installation still executes untrusted third-party code during install/import time and can fail or be influenced by the runtime environment.
# environment is NOT modified.
_DEP_DIR = Path("/tmp/office_md_deps")
_DEP_DIR.mkdir(exist_ok=True)
subprocess.run(
[
sys.executable, "-m", "pip", "install", "--quiet",
"--target", str(_DEP_DIR),
Runtime dependency installation is not required for the core task of converting PDFs to Markdown and expands the attack surface beyond the skill's stated purpose. This creates supply-chain and integrity risks because the tool reaches out to package infrastructure and executes installer/package code before processing the user document.
The vision fallback sends base64-encoded page images to an external API, which can expose sensitive document contents to a third party. Although the code gates this behind an --allow-vision flag, the script itself does not present a user-facing disclosure, validate consent, or handle credentials explicitly, so misuse by a caller or wrapper remains possible.
This code transmits document page data to an external Anthropic endpoint, creating a real data exfiltration path for potentially confidential PDFs. In the context of an office document conversion skill, external transmission is especially sensitive because users may process proprietary, regulated, or personal documents.
}]
}
req = urllib.request.Request(
"https://api.anthropic.com/v1/messages",
data=json.dumps(payload).encode("utf-8"),
headers={"Content-Type": "application/json", "anthropic-version": "2023-06-01"},
method="POST",
The script installs a Python package at runtime by invoking pip, which introduces unnecessary code-execution and supply-chain risk for a document conversion tool. Even with a pinned version and a fixed target directory, this behavior permits network retrieval and execution of package installation logic in the runtime environment, expanding the attack surface beyond simple file conversion.
# ── isolated dependency install ───────────────────────────────────────────────
_DEP_DIR = Path("/tmp/office_md_deps")
_DEP_DIR.mkdir(exist_ok=True)
subprocess.run(
[
sys.executable, "-m", "pip", "install", "--quiet",
"--target", str(_DEP_DIR),
A document-to-Markdown converter should not need package-management capabilities during normal operation. Runtime pip installation broadens the skill's privileges and creates a supply-chain and environmental integrity risk, because execution now depends on fetching and installing code at the moment the converter runs.
When --allow-vision is used, slide images are base64-encoded and sent to an external API, but the script itself does not present an in-band warning or confirmation at the moment of transmission. For potentially sensitive presentation content, this can lead to unintended external disclosure if the flag is passed without the user's informed understanding of what data leaves the system.
Although the manifest mentions Claude vision for scanned documents, the code here is a PPTX converter script whose core task is document conversion, while this function transmits slide images to an external API. Network exfiltration of document contents is a distinct capability and is not inherent to converting office files locally.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
}]
}
req = urllib.request.Request(
"https://api.anthropic.com/v1/messages",
data=json.dumps(payload).encode("utf-8"),
headers={"Content-Type": "application/json", "anthropic-version": "2023-06-01"},
method="POST",
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
}]
}
req = urllib.request.Request(
"https://api.anthropic.com/v1/messages",
data=json.dumps(payload).encode("utf-8"),
headers={"Content-Type": "application/json", "anthropic-version": "2023-06-01"},
method="POST",
The script performs a runtime pip install during document conversion, which causes network/package-infrastructure access and executes package installation logic at run time. Even though versions are pinned and subprocess.run is invoked without a shell, this still expands the attack surface to supply-chain compromise, dependency confusion, or unexpected install-time code execution in environments that process untrusted files.
# ── isolated dependency install ───────────────────────────────────────────────
_DEP_DIR = Path("/tmp/office_md_deps")
_DEP_DIR.mkdir(exist_ok=True)
subprocess.run(
[
sys.executable, "-m", "pip", "install", "--quiet",
"--target", str(_DEP_DIR),
The skill is described as a local document conversion tool, but the implementation reaches out to package infrastructure at execution time, which is inconsistent with least-privilege expectations for this context. In a file-conversion pipeline, hidden external fetches are more dangerous because users and operators may assume the action is offline and low-risk, while it actually introduces network egress and supply-chain exposure.
A document-to-Markdown utility should not need to install packages on demand while handling user requests; doing so means a simple conversion action can trigger external dependency retrieval and installation. That behavior is dangerous because package installation is a high-trust operation and may run attacker-influenced code from package infrastructure or from a compromised dependency source.
The manifest describes converting uploaded documents into Markdown, which could reasonably imply returning converted content, but this script performs a filesystem write to an arbitrary output path. That write behavior may be an implementation choice rather than the user-visible behavior described in the manifest, creating a mild description-to-behavior mismatch.
No suspicious patterns detected.