Back to skill

Security audit

Tdd Helper

Security checks for vulnerabilities and agentic risk

Overview

This small TDD helper is not deceptive, but it exposes broad shell command execution in ways users should review before installing.

Install only if you trust the users, agents, CI jobs, and environment variables that can invoke it. Treat --tests, --run, TEST_CMD, and LINT_CMD as trusted-code inputs, not plain data. A safer version would call pytest and linters with structured argument lists and avoid shell=True for user-controlled values.

Vulnerability Patterns
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (1)

T09 · Insecure Skill Coding Practices

Error
Location
tdd.py:8
Finding

Shell Command Injection Through the Test Path Argument

Content
View full analysis
/tmp/tdd-pwned' --run 'python your_script.py' ``` 3. The program constructs the following effective shell command: ```bash pytest missing; id > /tmp/tdd-pwned ``` 4. `subprocess.run` passes the complete string to the system shell. 5. The shell runs pytest and then executes the injected `id` command. 6. If the injected command returns zero, the wrapper may treat the test stage as successful and proceed to the target command despite the failed or missing tests. ### Impact As ...[truncated 725 chars]
Remediation
View remediation
Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (12)

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
99% confidence
Finding

This is tool parameter abuse because a helper intended to run tests can be repurposed into executing arbitrary shell payloads through TEST_CMD. The skill context makes this more dangerous, not less, because automation frameworks may trust 'test helper' tools and pass control into them with elevated confidence.

Content

Scanner excerpt · tdd.py (reported line 11)May include surrounding context.

python
TEST_CMD = os.getenv('TEST_CMD') or f"pytest {args.tests}" if os.path.isdir(args.tests) else f"pytest {args.tests}"

print(f"Running tests: {TEST_CMD}")
res = subprocess.run(TEST_CMD, shell=True)
if res.returncode != 0:
    print("Tests failed or missing. Aborting run.")
    sys.exit(res.returncode or 1)

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
98% confidence
Finding

This finding is valid because the lint stage can be abused via LINT_CMD to run arbitrary shell commands unrelated to linting. The hidden, environment-driven nature of the parameterization increases the risk of misuse in CI or agent runtimes.

Content

Scanner excerpt · tdd.py (reported line 19)May include surrounding context.

python
if os.getenv('WARN_AS_ERROR') == '1':
    lint = os.getenv('LINT_CMD') or "ruff ."
    print(f"Running lint: {lint}")
    lint_res = subprocess.run(lint, shell=True)
    if lint_res.returncode != 0:
        print("Lint/warnings failed. Aborting run.")
        sys.exit(lint_res.returncode or 1)

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
99% confidence
Finding

This is the clearest tool-parameter-abuse path: the main advertised workflow culminates in executing arbitrary user-provided shell text. For an agent skill, this effectively turns a lightweight TDD wrapper into a general remote command execution surface, which can lead to full compromise of the host environment accessible to the process.

Content

Scanner excerpt · tdd.py (reported line 25)May include surrounding context.

python
sys.exit(lint_res.returncode or 1)

print("Tests green. Running target...")
run_res = subprocess.run(args.run, shell=True)
sys.exit(run_res.returncode)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill advertises and relies on shell and environment-driven execution (python tdd.py --run "python your_script.py") but does not declare any explicit tool scope such as permissions or allowed-tools. This creates a policy gap where an agent may invoke broader execution capabilities than reviewers expect, increasing the chance of unintended command execution or misuse in environments that depend on manifest-declared restrictions.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The tool silently allows environment variables to redefine executable commands for tests and linting. This hidden behavior makes the skill more dangerous because command execution can be altered by ambient configuration without obvious indication to users reviewing the CLI arguments alone.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
98% confidence
Finding

The helper executes TEST_CMD with shell=True, and TEST_CMD can come directly from the TEST_CMD environment variable. This allows arbitrary shell execution via environment-controlled input, which is especially risky for an agent skill because callers or surrounding automation may not realize that setting an environment variable changes code execution behavior.

Content

Scanner excerpt · tdd.py (reported line 11)May include surrounding context.

python
TEST_CMD = os.getenv('TEST_CMD') or f"pytest {args.tests}" if os.path.isdir(args.tests) else f"pytest {args.tests}"

print(f"Running tests: {TEST_CMD}")
res = subprocess.run(TEST_CMD, shell=True)
if res.returncode != 0:
    print("Tests failed or missing. Aborting run.")
    sys.exit(res.returncode or 1)

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The overall design of this helper is broader than its stated purpose: instead of only enforcing a TDD loop, it executes arbitrary commands from both user input and environment variables. In an agent skill, this expanded execution surface materially increases abuse potential because the helper can become a general-purpose command runner.

Content

No source excerpt is available for this finding.

Tainted flow: 'TEST_CMD' from os.getenv (line 8, credential/environment) → subprocess.run (code execution)

Medium
Category
Data Flow
Confidence
99% confidence
Finding

This is a real tainted-data-to-code-execution flow: TEST_CMD is read from os.getenv and then executed by the shell. Any attacker who can influence the process environment can run arbitrary commands under the privileges of this tool.

Content

Scanner excerpt · tdd.py (reported line 11)May include surrounding context.

python
TEST_CMD = os.getenv('TEST_CMD') or f"pytest {args.tests}" if os.path.isdir(args.tests) else f"pytest {args.tests}"

print(f"Running tests: {TEST_CMD}")
res = subprocess.run(TEST_CMD, shell=True)
if res.returncode != 0:
    print("Tests failed or missing. Aborting run.")
    sys.exit(res.returncode or 1)

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
97% confidence
Finding

The lint command is executed with shell=True and may be sourced from the LINT_CMD environment variable. This creates another arbitrary command execution path controlled by ambient environment state, which is dangerous in automation and agent contexts where environment variables may be attacker-influenced.

Content

Scanner excerpt · tdd.py (reported line 19)May include surrounding context.

python
if os.getenv('WARN_AS_ERROR') == '1':
    lint = os.getenv('LINT_CMD') or "ruff ."
    print(f"Running lint: {lint}")
    lint_res = subprocess.run(lint, shell=True)
    if lint_res.returncode != 0:
        print("Lint/warnings failed. Aborting run.")
        sys.exit(lint_res.returncode or 1)

Tainted flow: 'lint' from os.getenv (line 17, credential/environment) → subprocess.run (code execution)

Medium
Category
Data Flow
Confidence
99% confidence
Finding

This is a genuine environment-controlled command execution path from LINT_CMD to subprocess.run with shell=True. Because the value is treated as shell syntax rather than data, metacharacters or chained commands can be injected and executed.

Content

Scanner excerpt · tdd.py (reported line 19)May include surrounding context.

python
if os.getenv('WARN_AS_ERROR') == '1':
    lint = os.getenv('LINT_CMD') or "ruff ."
    print(f"Running lint: {lint}")
    lint_res = subprocess.run(lint, shell=True)
    if lint_res.returncode != 0:
        print("Lint/warnings failed. Aborting run.")
        sys.exit(lint_res.returncode or 1)

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
99% confidence
Finding

The script runs args.run with shell=True, and args.run is explicitly user-supplied command text. This is direct arbitrary command execution and goes beyond a narrowly scoped TDD helper, making the skill capable of executing any shell payload provided by the caller.

Content

Scanner excerpt · tdd.py (reported line 25)May include surrounding context.

python
sys.exit(lint_res.returncode or 1)

print("Tests green. Running target...")
run_res = subprocess.run(args.run, shell=True)
sys.exit(run_res.returncode)

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The helper accepts a user-supplied shell command and executes it without any explicit disclosure or warning that arbitrary command execution will occur. In agent ecosystems, lack of clear disclosure increases the chance that integrators or users invoke the tool under the mistaken assumption that it is a narrow TDD utility rather than a shell execution primitive.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.