T09 · Insecure Skill Coding Practices
- Location
scripts/export_candidate.py:232- Finding
Path Traversal and Arbitrary File Overwrite via Unsanitized Candidate ID
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill mostly matches its research-ticket purpose, but it has review-worthy risks around arbitrary local command execution and unsafe file export paths.
Review before installing. Use it only in a constrained project workspace, avoid --llm-ideas-cmd unless the executable is trusted, do not export untrusted ticket files, and avoid --force until candidate IDs are restricted to safe names and contained under the intended strategies directory.
scripts/export_candidate.py:232Path Traversal and Arbitrary File Overwrite via Unsanitized Candidate ID
The supplied code chunk is only a test configuration helper. It modifies sys.path so tests can import modules from the parent directory. It does not implement any of the declared business functionality around equity research ticket generation, candidate spec export, or compatibility checking. This is a materially different primary purpose, so the description does not accurately represent this code chunk.
The description presents a research-ticket generation and candidate-export skill with optional compatibility checking. The actual code chunk is not such a generator/exporter; it is a test suite for a validator. It exercises validation of strategy YAML files, pipeline-schema checks, subprocess-based UV validation parsing, and command-line error handling. While this partially aligns with the declared preflight-check aspect, the primary purpose is materially different and much narrower than the declared end-to-end research-ticket generation/export workflow. Therefore the description does not accurately represent this code chunk.
This code path broadens the skill from research-ticket generation into a generic command launcher by permitting any external program to be run for 'LLM ideas'. In the context of an agent skill, that scope expansion is security-significant: a caller or chained workflow can turn a market-analysis feature into arbitrary process execution, with access to local environment permissions and to the generated payload data.
Code enumerates, copies, or searches environment variables for secrets. Bulk environment access can collect credentials unrelated to the skill's stated purpose.
def _uv_env() -> dict[str, str]:
"""Return subprocess environment with writable uv cache."""
env = os.environ.copy()
env.setdefault("UV_CACHE_DIR", "/tmp/uv-cache-edge-candidate-agent") # nosec B108
return env
The skill describes shell commands and file creation/export behavior but does not declare any explicit tool scope or allowed-tools policy. In an agent environment, this creates ambiguity about whether shell, file read/write, or environment access is permitted, which can lead to over-privileged execution, unsafe tool invocation, or policy bypass if a runner infers capabilities from content instead of an allowlist.
The script accepts a user-supplied --llm-ideas-cmd, tokenizes it, and executes it with subprocess.run, allowing the skill to invoke arbitrary local programs. Even without shell=True, this is still dangerous because the command itself is fully attacker-controlled and the process receives structured market/anomaly data on stdin, enabling arbitrary code execution or unintended data exfiltration in the skill's execution environment.
if not command_parts:
raise AutoDetectError("--llm-ideas-cmd is empty")
result = subprocess.run(
command_parts,
input=json.dumps(payload),
text=True,
The manifest centers on generating/prioritizing research tickets and exporting pipeline-ready candidate specs, but this code also performs downstream artifact export through another module and pipeline-context validation. That behavior reaches into strategy-artifact generation and validation workflows rather than staying within pure candidate/ticket creation.
The external hint-generation command is fed market summary and anomaly data without a strong user-facing security boundary or disclosure beyond CLI help text. In an agent/skill setting, this can lead to silent transmission of potentially sensitive research context to an untrusted local tool or wrapper, especially when combined with the arbitrary executable design.
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
]
)
result = subprocess.run( # nosec B607 - uv is a known local tool
["uv", "run", "python", "-c", snippet],
cwd=str(pipeline_root),
env=_uv_env(),
The function writes data to disk via path.write_text(), which is a safety-relevant file modification. Although the function has a technical docstring, there is no user-facing confirmation, warning, or visible disclosure about overwriting or modifying files in this code.
No suspicious patterns detected.