Back to skill

Security audit

ratgdo32 disco

Security checks for vulnerabilities and agentic risk

Overview

This skill is clearly meant to control a local garage door, but its high-impact physical actions are too broadly scoped and one safety check can fail open when status data is invalid or incomplete.

Install only if you are comfortable giving the agent local control over a physical garage door. Keep the device off the public internet, require explicit user confirmation for door movement and remote lockout, and harden the helper so closing fails closed unless valid status explicitly confirms no obstruction.

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
scripts/garage.sh:43
Finding

Garage Door Safety Check Fails Open on Invalid or Unavailable Status Data

Content
View full analysis

Vulnerability Details

File Location: scripts/garage.sh, lines 43–58
Vulnerability Type: Fail-open safety validation and insufficient HTTP error handling
Risk Level: High

bash
safe_close() {
    local json
    json=$(curl -s --connect-timeout 5 "${BASE}/status.json")
    local obstructed
    obstructed=$(echo "$json" | python3 -c "import json,sys; print(json.load(sys.stdin).get('garageObstructed', False))")
    if [ "$obstructed" = "True" ]; then
        echo "BLOCKED: Obstruction detected — cannot close door"
        exit 1
    fi
    local state
    state=$(echo "$json" | python3 -c "import json,sys; print(json.load(sys.stdin).get('garageDoorState', '?'))")
    if [ "$state" = "closed" ]; then
        echo "Already closed"
        exit 0
    fi
    control "garageDoorState" "0" "Closing door"
}

The affected operation invokes the following helper at lines 32–41:

bash
control() {
    local field="$1" value="$2" label="$3"
    curl -s -X POST -F "${field}=${value}" "${BASE}/setgdo" > /dev/null
    if [ $? -eq 0 ]; then
        echo "OK: ${label}"
    else
        echo "ERROR: Failed to ${label}"
        exit 1
    fi
}

Technical Analysis

safe_close does not validate whether the status request succeeded, returned a successful HTTP status, contained nonempty data, or produced a valid and complete status object. The script also does not enable shell behavior that would terminate execution when either Python parsing command fails.

If the response is valid JSON but omits garageObstructed, the expression .get('garageObstructed', False) explicitly interprets the missing safety field as no obstruction. If the response is empty or malformed, Python exits unsuccessfully, but the failure is ignored and obstructed becomes empty. Because an empty value is not equal to True, execution continues toward the physical close command.

The current door-stat ...[truncated 2374 chars]

Remediation
View remediation

Remediation Suggestions

  1. Make status validation fail closed. Abort unless the status request succeeds and explicitly reports garageObstructed as the boolean value false.
  2. Use strict curl error handling, including --fail, --show-error, a connection timeout, and an overall request timeout.
  3. Parse the status response once and validate its schema. Require both garageObstructed and garageDoorState to exist with expected types and values.
  4. Check every parser exit status. Do not proceed when JSON is empty, malformed, incomplete, or semantically invalid.
  5. Treat unknown door states as fatal rather than issuing a close command.
  6. Validate the control response and, where supported, query status afterward to confirm that the requested state transition actually began.
  7. Prefer authenticated HTTPS if supported by the controller. Otherwise, isolate the device and calling host on a trusted VLAN and use a fixed IP or otherwise protected name resolution to reduce LAN spoofing risk.
  8. Consider strict shell options such as set -euo pipefail, while still implementing explicit error handling for safety-critical requests.

A hardened implementation should follow this pattern:

bash
safe_close() {
    local json parsed obstructed state

    if ! json=$(curl --fail --silent --show-error \
        --connect-timeout 5 --max-time 10 \
        "${BASE}/status.json"); then
        echo "ERROR: Unable to obtain garage safety status" >&2
        exit 1
    fi

    if ! parsed=$(printf '%s' "$json" | python3 -c '
import json
import sys

data = json.load(sys.stdin)
if type(data.get("garageObstructed")) is not bool:
    raise ValueError("Missing or invalid garageObstructed")
if data.get("garageDoorState") not in {
    "open", "closed", "opening", "closing", "stopped"
}:
    raise ValueError("Missing or invalid garageDoorState")

print("true" if data["garageObstructed"] else "false")
print(data["garageDoorSta
...[truncated 767 chars]
Vulnerability Patterns
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (4)

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

Scanner excerpt · scripts/garage.sh (reported line 33)May include surrounding context.

sh
control() {
    local field="$1" value="$2" label="$3"
    curl -s -X POST -F "${field}=${value}" "${BASE}/setgdo" > /dev/null
    if [ $? -eq 0 ]; then
        echo "OK: ${label}"
    else

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

Scanner excerpt · scripts/garage.sh (reported line 62)May include surrounding context.

sh
safe_open() {
    local json
    json=$(curl -s --connect-timeout 5 "${BASE}/status.json")
    local state
    state=$(echo "$json" | python3 -c "import json,sys; print(json.load(sys.stdin).get('garageDoorState', '?'))")
    if [ "$state" = "open" ]; then

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill invokes shell-based device control but does not declare any tool scope or allowed-tools restrictions, creating an authorization gap between what the skill claims and what it can actually do. In this context, shell access can directly open/close a garage door, disable remotes, and change physical security state, so undeclared execution capability materially increases the risk of unsafe or unintended actuation.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The activation text is broad enough to trigger on vague requests like 'anything involving the garage,' which can cause the skill to engage in situations where the user did not clearly intend physical device control. Because this skill affects a real garage door and remote lockout state, over-broad routing increases the chance of accidental invocation, unintended door operation, or an unsafe action being chosen by the agent.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.