Back to skill

Security audit

Pilot Keychain

Security checks for vulnerabilities and agentic risk

Overview

This skill is meant for credential sharing, but its documented workflow stores and handles secrets in ways that can leave plaintext credentials exposed after use.

Review carefully before installing. This skill handles highly sensitive API keys and tokens, but its examples write them to plaintext files in /tmp and persist sent secrets under ~/.pilot/keychain/sent. Use only with credentials that can be quickly revoked or rotated, and prefer a version that uses secure temporary files or in-memory transfer, strict file permissions, verified received paths, and real expiry enforcement.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
Findings (3)

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:42
Finding

Plaintext credentials are written to unsafe temporary files

Content
View full analysis
/tmp/cred.json < /tmp/cred-$cred_id.json <
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:75
Finding

Plaintext sent credentials persist beyond their declared expiry

Content
View full analysis
/tmp/cred-$cred_id.json <
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
SKILL.md:55
Finding

Untrusted received metadata can direct credential processing to unintended files

Content
View full analysis
(now | todate)) | .value' ``` ### Technical Analysis The command validates `.filename` against a credential-like pattern but uses the separate `.filepath` property as the actual operand to `cat`. It does not establish that `.filepath` corresponds to the validated filename, resolves beneath `~/.pilot/keychain/received/`, is owned by the current user, or identifies a regular non-symbolic-link file. If an attacker can influence the metadata returned by `pilotctl received`, the attacker may supply an acceptable `.filename` while setting `.filepath` to another locally readable JSON file. The command then reads that path and prints its `.value` field if its `.expires_at` value passes the filter. The pipeline also uses newline-delimited output and `xargs` for filenames. This is fragile for paths containing newlines or other unusual characters and can cause incorrect file selection. Although `xargs -I` does not invoke a shell for `{}`, it does not resolve the underlying path-trust problem. ### Attack Path 1. An attacker sends or otherwise introduces a received-file record whose `.filename` matches `cred-.*\.json`. 2. The attacker causes the corresponding `.filepath` metadata to reference another file readable by the Skill's user. This step depends on whether the external `pilotctl` implementation permits sender or metadata influence over `.filepath`. 3. The user executes the documented receive command. 4. `jq` approves the benign-looking `.filename` but outputs the separate attacker-influenced `.filepath`. 5. `xargs` invokes `cat` on the unintended local file. 6. If that file is valid JSON with qualifying `expires_a ...[truncated 661 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (9)

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
85% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

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

EOF

pilotctl --json send-file "$RECIPIENT" /tmp/cred.json rm /tmp/cred.json

text

### Receive Credential

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

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

Cleanup Expired

bash
for CRED_FILE in ~/.pilot/keychain/received/cred-*.json; do
  EXPIRES_AT=$(jq -r '.expires_at' "$CRED_FILE")
  [ $(date +%s) -gt $(date -d "$EXPIRES_AT" +%s) ] && rm "$CRED_FILE"
done

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

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

Cleanup Expired

bash
for CRED_FILE in ~/.pilot/keychain/received/cred-*.json; do
  EXPIRES_AT=$(jq -r '.expires_at' "$CRED_FILE")
  [ $(date +%s) -gt $(date -d "$EXPIRES_AT" +%s) ] && rm "$CRED_FILE"
done

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

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

Cleanup Expired

bash
for CRED_FILE in ~/.pilot/keychain/received/cred-*.json; do
  EXPIRES_AT=$(jq -r '.expires_at' "$CRED_FILE")
  [ $(date +%s) -gt $(date -d "$EXPIRES_AT" +%s) ] && rm "$CRED_FILE"
done

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The skill advertises automatic expiration, but the examples only embed an expires_at field and later filter or manually delete files; no automatic enforcement mechanism is shown. Users may assume expired secrets are unusable or removed when they actually remain accessible on disk, causing overtrust in the skill's security properties.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The example writes plaintext credentials to /tmp/cred.json before sending them, exposing secrets to local disclosure risks through predictable paths, weak temp-file handling, race conditions, permissive permissions, swap, backups, or recovery of deleted files. In a credential-sharing skill, plaintext staging materially increases exposure because the content is highly sensitive by design.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
90% confidence
Finding

The workflow intentionally creates persistent sent/received directories and stores credential material in them, extending the lifetime of secrets beyond their immediate exchange. In the context of a credential-transfer skill, session persistence is more dangerous because compromise of the local account, filesystem, or backups can reveal previously shared secrets long after use.

Content

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

md
#!/bin/bash
# Credential lifecycle

mkdir -p ~/.pilot/keychain/{sent,received}

send_credential() {
  local recipient="$1"

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The workflow example stores sent credential files under ~/.pilot/keychain/sent/, which directly contradicts the stated guidance not to use the skill for persistent credential storage. Because the files contain plaintext secret values, this creates unnecessary local secret retention and expands the window for credential theft by other local users, malware, backups, or forensic recovery.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

The 'Cleanup Expired' section documents a loop that removes matching credential files from ~/.pilot/keychain/received, but the markdown provides no warning that files will be permanently deleted. For markdown files, SQP-2 requires warning users about behaviors that could affect data or system integrity, and irreversible deletion qualifies.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.