T09 · Insecure Skill Coding Practices
- Location
scripts/create-agent.py:178- Finding
Unescaped User Input Is Embedded into Executable Python Source
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This skill is a plausible Strands agent-building helper, but its scaffolded agents get unrestricted local file and shell powers by default without meaningful safeguards.
Review before installing. This does not look intentionally malicious, but only use the scaffold with trusted prompts and in a sandboxed workspace. Avoid the default generated read/write/shell tools unless you explicitly need them, pin dependencies and MCP server versions, and do not run generated agents where they can access sensitive files or cloud credentials.
scripts/create-agent.py:178Unescaped User Input Is Embedded into Executable Python Source
scripts/create-agent.py:167Agent Name Can Escape the Intended Output Directory and Overwrite Files
scripts/create-agent.py:56Generated Agents Receive Unrestricted Filesystem and Shell Capabilities by Default
SKILL.md:20Documentation Recommends Unpinned Dependencies and Mutable MCP Package Execution
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
from strands import Agent
# No model specified → BedrockModel (Claude Sonnet 4, us-west-2)
# Requires AWS credentials (~/.aws/credentials or env vars)
agent = Agent()
result = agent("Explain quantum computing")
subprocess.run(command, shell=True, ...) executes arbitrary shell text through the system shell, making the tool highly susceptible to prompt-driven command injection and abuse. Because this code is embedded in a scaffold for AI agents that may act on natural-language instructions, the risk is amplified: untrusted prompt content can be translated directly into host-level command execution.
command: Shell command to execute.
"""
import subprocess
result = subprocess.run(command, shell=True, capture_output=True, text=True, timeout=60)
output = result.stdout
if result.stderr:
output += f"\\nSTDERR: {{result.stderr}}"
The skill documents and exemplifies capabilities for reading/writing files, invoking shell commands, and connecting to MCP endpoints, but it does not declare any corresponding permission or allowed-tools scope in metadata. This creates a mismatch between what the skill can encourage or enable and what a caller can audit or constrain, increasing the risk of unintended file modification, command execution, or external connectivity when the skill is used.
The custom tool examples include unrestricted file read and write functions and then instruct the agent to read and summarize a local file, but the documentation does not warn that these tools can alter local files or expose sensitive data. In an agent-skill context, users may copy these examples directly, causing the model to gain broad filesystem access without understanding the consequences.
The built-in tools list prominently includes shell, http_request, file_write, python_repl, and similar powerful capabilities without any safety guidance about command execution, outbound network access, or filesystem changes. In practice, exposing these tools to an LLM materially increases the chance of destructive commands, data exfiltration, or unsafe downloads if a user adopts the examples as-is.
The MCP and A2A sections show how to connect to external servers and cross-process/network services but omit warnings about trust boundaries, remote tool execution, data sharing, and server authenticity. Because MCP and A2A can bridge an agent to untrusted services, this can expand the attack surface well beyond the local process and enable prompt injection, data leakage, or indirect command execution through remote tools.
The generated agent includes a write_file tool that can write arbitrary content to attacker-chosen paths, but the scaffolded documentation does not clearly warn that prompts may modify the local filesystem. In this skill context, that omission matters because the project is intended for autonomous agents, so users may run the scaffold with high trust and unintentionally allow prompt-driven file tampering or persistence.
The scaffolded agent template gives the LLM a run_command tool that executes arbitrary shell commands, yet the generated README and usage text do not warn users that prompts can cause command execution on the host. In an agent-building skill, this is especially dangerous because users may treat the scaffold as a safe starter project and expose it to untrusted prompts, enabling destructive local actions or data exfiltration.
The script dynamically imports and executes an arbitrary Python file supplied on the command line via exec_module(), which will run top-level code immediately during load. In the context of an agent runner, this means a user can easily execute untrusted code by pointing the tool at a malicious agent file, and the script provides no warning, trust boundary, or sandboxing to reduce that risk.
Dynamic import() can load arbitrary modules at runtime, bypassing static analysis and potentially importing malicious code.
("OpenAIRealtime", "strands.experimental.bidi.models.openai_realtime"),
]:
try:
__import__(mod)
models_found.append(name)
except ImportError:
pass
Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.
skipped = []
for name in lazy_names:
try:
cls = getattr(m, name)
assert cls is not None
resolved += 1
except (ImportError, ModuleNotFoundError):
No suspicious patterns detected.