Back to skill

Security audit

Pilot Quarantine

Security checks for vulnerabilities and agentic risk

Overview

The skill is a plausible Pilot Protocol quarantine helper, but its examples grant high-impact trust and disconnect authority with inconsistent scope and unsafe shell/JQ handling that could affect unintended agents.

Install only after the publisher tightens the scope and hardens the examples. In particular, disconnect behavior should be clearly opt-in, targets should be validated and previewed before untrust/disconnect, jq should use --arg, quarantine IDs should be constrained to generated hex IDs, and JSON records should be written with a serializer and restrictive file permissions.

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 (4)

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:46
Finding

JQ Expression Injection Can Disconnect Unrelated Agents

Content
View full analysis

Vulnerability Details

File Location: SKILL.md, lines 46–47 and 73–74
Vulnerability Type: JQ expression injection caused by unsafe string interpolation
Risk Level: High

Vulnerable Code

bash
pilotctl --json connections | jq -r '.connections[] | select(.remote_hostname == "'"$AGENT"'") | .id' | \
  xargs -I {} pilotctl --json disconnect {}

The same vulnerable command also appears in the quarantine enforcement workflow at lines 73–74.

Technical Analysis

The AGENT variable is inserted directly into the jq program rather than being supplied as a jq data argument. Consequently, quotes and jq operators in an agent name are interpreted as executable jq syntax.

For example, an agent value resembling:

text
" or true or .remote_hostname == "

can change the selection condition so that it evaluates as true for every connection. All matching connection IDs are then passed directly to the state-changing pilotctl disconnect command.

Shell quoting does not protect the jq expression because the shell deliberately terminates the single-quoted jq program to interpolate AGENT.

Attack Path

  1. An attacker registers, advertises, or provides a crafted agent hostname containing jq syntax.
  2. An operator copies that value into the documented AGENT variable or stores it in a quarantine record.
  3. The quarantine or enforcement workflow inserts the value into the jq program.
  4. The injected predicate selects connections other than the intended agent.
  5. xargs invokes pilotctl --json disconnect for each selected connection.
  6. Legitimate agents are disconnected from the Pilot Protocol network.

Impact Assessment

Exploitation grants no additional operating-system privileges, but it allows an attacker to misuse all connection-management authority available to the invoking pilotctl user. The scope can include every connection returned by pilotctl --json connections, resul ...[truncated 78 chars]

Remediation
View remediation

Remediation Suggestions

Pass the agent name as data through jq's --arg option instead of constructing jq source code:

bash
pilotctl --json connections |
  jq -r --arg agent "$AGENT" \
    '.connections[] | select(.remote_hostname == $agent) | .id' |
  xargs -r -I {} pilotctl --json disconnect -- {}

Apply the same correction to lines 73–74. In addition:

  1. Validate agent hostnames against the Pilot Protocol's documented hostname syntax.
  2. Reject control characters, quotes, and unexpected whitespace where they are not valid hostname characters.
  3. Verify that pilotctl find returns exactly one valid node before changing trust.
  4. Preview or count selected connection IDs before disconnecting them.
  5. Use xargs -r so no command is executed when the input is empty.

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:59
Finding

Unvalidated Quarantine ID Permits Path Traversal

Content
View full analysis

Vulnerability Details

File Location: SKILL.md, lines 59–64
Vulnerability Type: Path traversal through an unvalidated file identifier
Risk Level: Medium

Vulnerable Code

bash
QUARANTINE_ID="abc123"
QFILE=~/.pilot/quarantine/active/$QUARANTINE_ID.json
AGENT=$(jq -r '.agent' "$QFILE")

mv "$QFILE" ~/.pilot/quarantine/resolved/
pilotctl --json handshake "$AGENT" "Quarantine released"

Technical Analysis

QUARANTINE_ID is concatenated directly into a filesystem path without format validation or canonical-path verification. A value containing directory traversal components such as ../ can make QFILE resolve outside ~/.pilot/quarantine/active/.

The .json suffix limits the target to a path ending in that suffix, but it does not prevent access to other JSON files reachable by the current user. The selected file is parsed with jq, moved into the resolved quarantine directory, and its agent field is supplied to pilotctl handshake.

The workflow also does not reject symbolic links. A maliciously placed symlink in the active directory could therefore redirect processing to an unintended file.

Attack Path

  1. An attacker influences the quarantine identifier supplied to an operator or automation.
  2. The identifier contains traversal components, for example a relative path leading to another JSON file.
  3. QFILE resolves outside the intended active quarantine directory.
  4. The workflow reads the target file's agent property.
  5. mv relocates that unintended file into the resolved directory.
  6. pilotctl handshake contacts the agent named in the selected file.

Impact Assessment

The attacker can cause files ending in .json and accessible to the invoking user to be moved, potentially corrupting application state or causing denial of service. If the selected JSON document contains an agent property, the workflow may also initiate an unintended network handshake.

Ex ...[truncated 176 chars]

Remediation
View remediation

Remediation Suggestions

Enforce the identifier format generated by the quarantine workflow before constructing a path:

bash
case "$QUARANTINE_ID" in
  (*[!0-9a-f]*|'')
    echo "Invalid quarantine ID" >&2
    exit 1
    ;;
esac

[ "${#QUARANTINE_ID}" -eq 12 ] || {
  echo "Invalid quarantine ID length" >&2
  exit 1
}

Additional hardening should include:

  1. Define absolute active and resolved directory paths.
  2. Canonicalize the selected path and verify that it remains beneath the active directory.
  3. Require the target to be a regular file and reject symbolic links.
  4. Use mv -- "$QFILE" "$resolved_dir/".
  5. Verify that the record has the expected schema and status before moving it.
  6. Validate the extracted agent name before passing it to pilotctl.

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:92
Finding

Unsafe JSON Construction Allows Record Corruption and Field Injection

Content
View full analysis

Vulnerability Details

File Location: SKILL.md, lines 92–100
Vulnerability Type: Improper escaping during JSON generation
Risk Level: Medium

Vulnerable Code

bash
cat > ~/.pilot/quarantine/active/$QUARANTINE_ID.json <<EOF
{
  "quarantine_id": "$QUARANTINE_ID",
  "agent": "$AGENT",
  "reason": "Port scanning detected",
  "quarantined_at": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
  "status": "active"
}
EOF

Technical Analysis

Shell variables are interpolated directly into JSON string literals. JSON requires quotation marks, backslashes, control characters, and line breaks to be escaped. The shell does not perform JSON escaping.

An attacker-controlled agent value containing quotation marks or newline characters can therefore make the record invalid or alter its structure. Depending on the supplied value, subsequent properties can be injected or existing properties can be duplicated. Later list, enforcement, and release workflows trust fields read from these records with jq.

The record is also written directly to its final path. If the process is interrupted, another workflow may observe a partially written JSON document.

Attack Path

  1. An attacker supplies or advertises an agent name containing JSON metacharacters.
  2. The operator assigns that value to AGENT.
  3. The heredoc inserts the value without JSON escaping.
  4. The resulting quarantine record is malformed or contains attacker-influenced fields.
  5. Listing may fail, enforcement may read a manipulated agent or node identifier, and release may initiate a handshake using manipulated record data.
  6. Operational quarantine state becomes unreliable or attacker-directed.

Impact Assessment

Exploitation can corrupt quarantine records, disrupt quarantine enforcement, mislead incident responders, or influence the agent value used during release. The affected scope is the quarantine state and Pilot Protocol operations availab ...[truncated 179 chars]

Remediation
View remediation

Remediation Suggestions

Generate JSON with a serializer such as jq so every value is escaped correctly:

bash
timestamp=$(date -u +%Y-%m-%dT%H:%M:%SZ)

jq -n \
  --arg quarantine_id "$QUARANTINE_ID" \
  --arg agent "$AGENT" \
  --arg reason "Port scanning detected" \
  --arg quarantined_at "$timestamp" \
  '{
    quarantine_id: $quarantine_id,
    agent: $agent,
    reason: $reason,
    quarantined_at: $quarantined_at,
    status: "active"
  }' > "$temporary_record"

Then:

  1. Validate the agent and quarantine ID before serialization.
  2. Create the quarantine directories with restrictive permissions, such as mode 0700.
  3. Create the temporary record securely in the destination directory.
  4. Set record permissions to 0600.
  5. Validate the completed document and atomically rename it into its final path.
  6. Reject duplicate or unexpected fields when records are later consumed.

T09 · Insecure Skill Coding Practices

Note
Location
SKILL.md:41
Finding

Primary Quarantine Command Does Not Persist Quarantine State

Content
View full analysis

Vulnerability Details

File Location: SKILL.md, lines 41–47
Vulnerability Type: Incomplete security-state management
Risk Level: Low

Vulnerable Code

bash
AGENT="suspicious.pilot"
QUARANTINE_ID=$(openssl rand -hex 6)
NODE_ID=$(pilotctl --json find "$AGENT" | jq -r '.node_id')

pilotctl --json untrust "$NODE_ID"
pilotctl --json connections | jq -r '.connections[] | select(.remote_hostname == "'"$AGENT"'") | .id' | \
  xargs -I {} pilotctl --json disconnect {}

Technical Analysis

The command generates a quarantine identifier and performs a one-time trust removal and disconnection, but it never creates a corresponding record under ~/.pilot/quarantine/active/.

The documented listing, release, and enforcement workflows all depend on active JSON records. Therefore, a quarantine initiated with the primary command cannot be listed, periodically enforced, or released through those workflows. The unused QUARANTINE_ID may also give operators the misleading impression that durable quarantine state was created.

Attack Path

  1. An operator follows the primary “Quarantine Agent” command.
  2. The suspicious agent is untrusted and its current connections are disconnected.
  3. No active quarantine record is stored.
  4. The enforcement workflow has no record identifying that agent.
  5. If the agent reconnects or otherwise establishes a new permitted connection, the documented enforcement process does not target it.
  6. Incident responders may incorrectly assume the agent remains under managed quarantine.

Impact Assessment

The issue weakens the availability and integrity of the quarantine control rather than granting attacker privileges. A suspicious agent may escape continued enforcement after the initial disconnect, and operators may lose the ability to track or consistently resolve the incident.

The scope is limited to quarantines created through the incomplete primary command.

Remediation
View remediation

Remediation Suggestions

Make durable record creation part of the primary quarantine transaction:

  1. Create the active and resolved directories with restrictive permissions.
  2. Validate that agent discovery returns exactly one valid node ID.
  3. Generate and securely write a complete active quarantine record.
  4. Confirm that the record has been atomically committed.
  5. Perform the untrust and disconnect operations.
  6. Record operation results and report partial failures explicitly.
  7. If a required step fails, either roll back safely or retain a record marked with a clear failure state for responder review.
  8. Do not report quarantine success until both persistent state creation and isolation actions have succeeded.
Vulnerability Patterns
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (6)

Intent-Code Divergence

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The skill explicitly tells users not to use it for immediate disconnect, but later command examples do exactly that. This contradiction is especially dangerous in an incident-response skill because operators rely on documentation boundaries to choose proportionate containment actions, and violating those boundaries can lead to unintended service disruption or abusive isolation workflows.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The destructive workflow revokes trust and terminates connections without an explicit user-facing warning or confirmation. In a security operations context, these are sensitive actions that can cut off legitimate agents, disrupt investigations, or be triggered too casually if copied verbatim from the skill documentation.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The quarantine command performs both trust revocation and active disconnection, even though the skill description explicitly says it should not be used for immediate disconnects. This mismatch can cause operators or downstream agents to invoke the skill expecting a limited quarantine action but instead terminate live sessions, creating an unsafe capability expansion and increasing the chance of misuse during incident response.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The enforcement workflow repeatedly disconnects matching agents, effectively implementing the immediate disconnect behavior that the manifest says should be handled by another tool. This creates policy drift between documentation and actual behavior, which is dangerous in security automation because users may unknowingly deploy stronger disruption than intended.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · SKILL.md (reported line 86)May include surrounding context.

md
#!/bin/bash
# Quarantine management

mkdir -p ~/.pilot/quarantine/{active,resolved}

AGENT="malicious.pilot"
QUARANTINE_ID=$(openssl rand -hex 6)

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

The release workflow resumes trust-related communication with a previously quarantined agent via a handshake, but does not warn the operator that this may restore interaction with a still-suspicious system. While less severe than forced disconnect, it can prematurely re-enable communication during an incomplete investigation.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.