Back to skill

Security audit

service-registry

Security checks for vulnerabilities and agentic risk

Overview

This skill is coherent for managing external service execution, but its examples give broad command-execution patterns with weak scoping and incomplete warnings about sending prompts and files to third-party services.

Review this skill carefully before installing. It is not malicious, but only use it for deliberate multi-service registry work, with trusted service definitions, allowlisted commands, explicit user approval before sending sensitive prompts or files, and safer argument-array construction instead of free-form command templates.

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

Warning
Location
modules/execution-patterns.md:14
Finding

Argument Injection Through Unsafe Command-Template Expansion

Content
View full analysis

Vulnerability Details

File Location: modules/execution-patterns.md:14-49; related unsafe template configuration at modules/service-config.md:17-19 and modules/service-config.md:50
Vulnerability Type: CLI argument injection caused by interpolating untrusted values into a command string
Risk Level: Medium

Vulnerable Code

python
def build_command(
    config: ServiceConfig,
    prompt: str,
    files: list[str],
    model: str = None
) -> str:
    """Build command from template."""
    file_args = " ".join(f"@{f}" for f in files)
    model = model or config.default_model

    return config.command_template.format(
        command=config.command,
        prompt=prompt,
        files=file_args,
        model=model
    )

The resulting interpolated string is subsequently parsed into arguments:

python
import subprocess
import shlex

def execute_safely(command: str, timeout: int = 60) -> ExecutionResult:
    """Execute command with safety measures."""
    start = time.time()

    try:
        result = subprocess.run(
            shlex.split(command),
            capture_output=True,
            text=True,
            timeout=timeout
        )

The documented configuration places the untrusted prompt inside manually constructed quoting:

python
command: str  # CLI command or endpoint
command_template: str = "{command} -p {prompt}"
python
command_template="gemini -p '{prompt}' {files}",

Technical Analysis

The command builder substitutes prompt, file names, the model, and configuration values into one command string. It then uses shlex.split() to reconstruct an argument vector. This does not preserve the intended boundary between trusted command options and untrusted data.

Although subprocess.run() is invoked without shell=True, which prevents ordinary shell metacharacters from directly launching a shell comma ...[truncated 2654 chars]

Remediation
View remediation

Remediation Suggestions

  1. Construct an argument array directly. Do not interpolate user-controlled values into a command string and then parse it:

    python
    def build_argv(
        config: ServiceConfig,
        prompt: str,
        files: list[str],
        model: str | None = None
    ) -> list[str]:
        argv = [config.command, "-p", prompt]
    
        selected_model = model or config.default_model
        if selected_model:
            argv.extend(["--model", selected_model])
    
        argv.extend(f"@{path}" for path in files)
        return argv
    

    Execute the array without shlex.split():

    python
    result = subprocess.run(
        argv,
        shell=False,
        capture_output=True,
        text=True,
        timeout=timeout,
        check=False
    )
    
  2. Replace free-form command templates with structured configuration. Store the executable and each fixed option as separate fields. Do not allow templates to determine quoting or argument boundaries.

  3. Allowlist executables and options. Resolve the executable to an approved absolute path and reject unsupported flags, models, or service names.

  4. Validate file inputs. Resolve paths canonically, restrict them to approved project directories, reject control characters, and verify that each path refers to an allowed file type.

  5. Use explicit end-of-options delimiters where supported. Insert -- before positional arguments to prevent values beginning with - from being interpreted as options. This is supplementary and does not replace direct argument-array construction.

  6. Add adversarial tests. Test prompts and file names containing spaces, single and double quotes, leading hyphens, backslashes, newlines, and option-like strings. Verify that each untrusted value remains exactly one intended argument.

  7. Apply least privilege. Run external service CLIs with minimal filesystem permissions, restrict ...[truncated 128 chars]

Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (5)

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The trigger list includes generic terms like "services", "registry", "execution", and "integration", which are broad enough to cause unintended activation in many unrelated contexts. Because this skill coordinates external service execution, accidental invocation could route prompts or file contents to integrated third-party services unexpectedly, increasing data exposure and operational risk.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The skill demonstrates executing prompts and passing file paths through external services, but it does not warn users that prompts, code, and possibly file contents may be transmitted to third-party systems. In a service-registry context that centralizes multiple integrations and failover logic, this omission is more dangerous because users may not realize their data could be sent to one of several external providers.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The documented pattern builds a command string from templated fields including prompt, files, and model, then executes it as an external process. Even though shlex.split() avoids direct shell interpretation, this still enables untrusted input to influence executable arguments and broadens the skill from registry coordination into arbitrary command invocation, which can lead to unintended tool execution, data exposure, or unsafe side effects depending on the configured template.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

Calling this routine 'Safe Execution' is misleading because the code still executes externally configured commands influenced by runtime inputs. That label can cause downstream developers or operators to trust the pattern without adding the necessary restrictions, increasing the likelihood of insecure deployment and abuse.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The markdown presents subprocess execution as a reusable pattern without prominently warning users that it runs external commands. In a service-registry skill that coordinates multiple integrations, this omission is more dangerous because adopters may enable external execution across many services, expanding the blast radius of any misconfiguration or malicious service definition.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.