Back to skill

Security audit

pilot-sandbox

Security checks for vulnerabilities and agentic risk

Overview

This skill is purpose-built for Pilot connectivity in a locked-down sandbox, but it asks users to run privileged background network routing and includes an unsafe certificate-pinning fallback.

Install only if you understand and need this exact restricted-sandbox Pilot workaround. Run it in a disposable VM or tightly scoped environment, confirm HTTPS_PROXY is trusted, prefer system TLS trust over pinned trust, avoid the fingerprint refresh snippet unless you can verify the fingerprint through an independent trusted channel, and be prepared to manually find and stop the background router and daemon processes.

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
references/troubleshooting.md:85
Finding

Unauthenticated TLS Certificate Pin Bootstrap

Content
View full analysis

Vulnerability Details

File Location: references/troubleshooting.md, lines 85–92
Vulnerability Type: Trust-on-first-use from an unauthenticated TLS connection
Risk Level: Medium

Vulnerable code:

python
assert b" 200" in s.recv(4096).split(b"\r\n")[0]
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
ctx.check_hostname = False; ctx.verify_mode = ssl.CERT_NONE
t = ctx.wrap_socket(s, server_hostname="registry.pilotprotocol.network")
print(hashlib.sha256(t.getpeercert(binary_form=True)).hexdigest())
t.close()

Technical Analysis

The documented fallback procedure obtains a new registry certificate fingerprint while explicitly disabling both certificate-chain validation and hostname verification. The resulting fingerprint is printed for use as PILOT_REGISTRY_FINGERPRINT, making the certificate from this unauthenticated connection a future trust anchor.

This path is reachable when the sandbox lacks a usable CA bundle or the existing pin no longer matches and the operator follows the documented fingerprint refresh procedure. The attacker-controlled point is the certificate presented over the network. A malicious or compromised egress proxy, or another attacker capable of intercepting the proxy tunnel, can terminate TLS using an arbitrary certificate because ssl.CERT_NONE accepts it.

Although sending Proxy-Authorization to the user-configured proxy is normal proxy authentication and is not credential exfiltration, relying on that same unauthenticated network path to establish a certificate pin does not independently authenticate the registry.

Attack Path

  1. The daemon reports an unknown-authority or fingerprint-mismatch error.
  2. The operator follows the documented fallback and runs the fingerprint-fetching snippet.
  3. An attacker controlling or intercepting the egress proxy path returns a successful CONNECT response and presents an attacker-controlled TLS certificate.
  4. Because hostn ...[truncated 893 chars]
Remediation
View remediation

Remediation Suggestions

  • Do not derive a production trust anchor from a TLS connection configured with CERT_NONE.
  • Prefer the system trust store with normal certificate-chain and hostname validation:
    python
    ctx = ssl.create_default_context()
    t = ctx.wrap_socket(s, server_hostname="registry.pilotprotocol.network")
    
  • If the sandbox lacks a CA bundle, install or provide a narrowly scoped trusted CA bundle rather than disabling verification.
  • Alternatively, distribute the expected fingerprint through an independently authenticated channel, such as a signed release artifact or authenticated configuration.
  • If manual pin verification is unavoidable, require comparison against a fingerprint obtained through a separate trusted channel before updating PILOT_REGISTRY_FINGERPRINT.
  • Document that a fingerprint observed through the same unverified proxy connection must not be trusted automatically.
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Rogue AgentSelf-Modification, Session Persistence
  • 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 (10)

Lp1

High
Category
MCP Least Privilege
Confidence
75% confidence
Finding

The skill uses 'env' capability that is not listed in its permissions. This may indicate deceptive intent or missing permission declarations.

Content

No source excerpt is available for this finding.

Lp1

High
Category
MCP Least Privilege
Confidence
75% confidence
Finding

The skill uses 'network' capability that is not listed in its permissions. This may indicate deceptive intent or missing permission declarations.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill instructs the user to run root-level networking and mount-namespace changes (unshare -m, bind-mounting /etc/hosts, and starting a local transparent router on port 443) but does not present a clear upfront warning about security and operational impact. Even if intended for legitimate sandbox connectivity, these actions alter name resolution for a privileged process and create long-lived proxying behavior that could be misused or cause unintended traffic routing.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
88% confidence
Finding

Using nohup ... & intentionally detaches the SNI router so it survives shell termination, creating persistence within the VM session. In a security-sensitive sandbox, a background network relay that continues operating after the initiating shell exits increases the chance of unnoticed traffic forwarding or later abuse.

Content

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

md
cd ~/workspace/skills/pilot-sandbox

# 1. SNI router (reads HTTPS_PROXY from the environment)
nohup python3 scripts/sni_router.py > sni_router.log 2>&1 &

# 2. Daemon in a private mount namespace. setsid keeps it alive after the
#    shell exits; plain `nohup ... &` may not.

Session Persistence

Medium
Category
Rogue Agent
Confidence
93% confidence
Finding

setsid unshare -m ./scripts/run-daemon.sh ... & creates a detached, session-independent daemon process with mount-namespace modifications, making it persist beyond the shell and harder to monitor. Because it runs with elevated privileges and changes name resolution for the daemon, this persistence expands the blast radius if the daemon or wrapper is misconfigured or replaced.

Content

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

md
# 1. SNI router (reads HTTPS_PROXY from the environment)
nohup python3 scripts/sni_router.py > sni_router.log 2>&1 &

# 2. Daemon in a private mount namespace. setsid keeps it alive after the
#    shell exits; plain `nohup ... &` may not.
setsid unshare -m ./scripts/run-daemon.sh >> daemon.log 2>&1 < /dev/null &

Session Persistence

Medium
Category
Rogue Agent
Confidence
65% 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 99)May include surrounding context.

md
nohup python3 scripts/sni_router.py > sni_router.log 2>&1 &

# 2. Daemon in a private mount namespace. setsid keeps it alive after the
#    shell exits; plain `nohup ... &` may not.
setsid unshare -m ./scripts/run-daemon.sh >> daemon.log 2>&1 < /dev/null &

# 3. Wait for registration

Session Persistence

Medium
Category
Rogue Agent
Confidence
87% confidence
Finding

This workflow example repeats the detached nohup launch pattern, encouraging users to leave a local network-routing process running in the background. Repetition in an example makes accidental adoption more likely and normalizes persistence without emphasizing cleanup or monitoring.

Content

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

bash
export PATH="$PATH:$HOME/.pilot/bin"
cd ~/workspace/skills/pilot-sandbox
nohup python3 scripts/sni_router.py > sni_router.log 2>&1 &
setsid unshare -m ./scripts/run-daemon.sh >> daemon.log 2>&1 < /dev/null &
sleep 30 && grep -q "daemon registered" daemon.log && echo "node online"

Session Persistence

Medium
Category
Rogue Agent
Confidence
91% confidence
Finding

This example also repeats detached setsid execution of the privileged namespace-wrapping daemon, reinforcing persistent operation after logout. In context, the process modifies resolution behavior for the daemon and maintains ongoing external connectivity, which is sensitive behavior in a restricted sandbox.

Content

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

md
export PATH="$PATH:$HOME/.pilot/bin"
cd ~/workspace/skills/pilot-sandbox
nohup python3 scripts/sni_router.py > sni_router.log 2>&1 &
setsid unshare -m ./scripts/run-daemon.sh >> daemon.log 2>&1 < /dev/null &
sleep 30 && grep -q "daemon registered" daemon.log && echo "node online"

# Now use Pilot normally: ask pilot-mom for a plan, then query the specialist.

Session Persistence

Medium
Category
Rogue Agent
Confidence
65% 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 100)May include surrounding context.

md
#
# Launch it ONLY like this (root or CAP_SYS_ADMIN required for unshare -m):
#
#   setsid unshare -m ./scripts/run-daemon.sh >> daemon.log 2>&1 < /dev/null &
#
# Environment (all optional):
#   PILOT_REGISTRY_TRUST        system (default) | pinned

Session Persistence

Medium
Category
Rogue Agent
Confidence
65% 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 · scripts/run-daemon.sh (reported line 8)May include surrounding context.

sh
#
# Launch it ONLY like this (root or CAP_SYS_ADMIN required for unshare -m):
#
#   setsid unshare -m ./scripts/run-daemon.sh >> daemon.log 2>&1 < /dev/null &
#
# Environment (all optional):
#   PILOT_REGISTRY_TRUST        system (default) | pinned

Static analysis

No suspicious patterns detected.