Back to skill

Security audit

Keys

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent API-key broker, but its key-management instructions can expose plaintext API keys and its broker grants broad authenticated API access.

Review before installing. Use only with tightly scoped API keys, avoid running the documented verification commands that print secrets, do not place real keys in command-line arguments, and require explicit user approval before using the broker for destructive or financial API actions.

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
manage.md:5
Finding
API Keys Exposed Through Command-Line Arguments and Plaintext Verification Output<![CDATA[ ## Vulnerability Details **File Location**: `manage.md`, lines 5-7, 14-17, and 40-49 **Vulnerability Type**: Plaintext credential exposure **Risk Level**: High ### Vulnerable Code `manage.md:5-7`: ```bash ### macOS ```bash security add-generic-password -s "keys:SERVICE" -a "$USER" -w "THE-API-KEY" ``` `manage.md:14-17`: ```bash ### macOS ```bash security delete-generic-password -s "keys:SERVICE" -a "$USER" security add-generic-password -s "keys:SERVICE" -a "$USER" -w "NEW-API-KEY" ``` `manage.md:40-49`: ```bash ## Verify a Key Exists ```bash # This should return the key (or error if not found) # macOS security find-generic-password -s "keys:SERVICE" -a "$USER" -w # Linux secret-tool lookup service keys:SERVICE ``` ``` ### Technical Analysis The macOS add and update instructions place the API key directly in a command-line argument through `-w "THE-API-KEY"` and `-w "NEW-API-KEY"`. When users replace these placeholders with real credentials, the secret can be retained in shell history and may be exposed through process inspection or terminal-session logging. The verification instructions explicitly retrieve and print the decrypted credential to standard output. On macOS, `security find-generic-password ... -w` prints the password, while on Linux, `secret-tool lookup` prints the stored secret. If these commands are run through an AI Agent terminal or another captured execution environment, the key may enter Agent context, command transcripts, application logs, or tool output. This behavior contradicts the Skill's stated security property that keys are never exposed to Agent context. Although `keys-broker.sh` itself does not return stored keys directly, the documented management workflow provides commands that do. ### Attack Path 1. A user follows the documented macOS key-addition or rotation instructions. 2. The user replaces `THE-API-KEY` or `NEW-API-KEY` with an actual credential. 3. The complete command, including the plaintext creden ...[truncated 1419 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. **Do not pass credentials as command-line arguments.** Replace the macOS examples with an interactive workflow that allows the `security` utility to prompt for the secret rather than embedding it in the command. 2. **Do not print decrypted credentials during verification.** Verification should report only whether a credential exists. Suppress secret output and inspect the command's exit status, for example: ```bash if security find-generic-password -s "keys:SERVICE" -a "$USER" -w >/dev/null 2>&1; then echo "Key exists" else echo "Key not found" fi ``` For Linux: ```bash if secret-tool lookup service keys:SERVICE >/dev/null 2>&1; then echo "Key exists" else echo "Key not found" fi ``` 3. **Keep Linux secret entry interactive.** Continue using `secret-tool store`, which prompts for the secret, and warn users not to pipe credentials from shell command lines or store them in environment variables. 4. **Add explicit Agent-safety guidance.** State that an Agent must never execute commands that return decrypted credentials and must not request that users place keys in command arguments, chat messages, or Agent-controlled terminals. 5. **Address existing exposure.** Users who followed the vulnerable instructions should remove affected commands from shell history and terminal logs, rotate the potentially exposed credentials, revoke old keys, and review provider audit logs for unauthorized use. 6. **Apply least privilege at the provider.** Restrict each API key to the minimum required scopes, projects, repositories, source addresses, spending limits, and expiration period so that accidental disclosure has reduced impact. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (17)

Ae1

High
Category
analysis-evasion
Content
To add services, edit `ALLOWED_URLS` in `keys-broker.sh`.
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
To add services, edit `ALLOWED_URLS` in `keys-broker.sh`.
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Credential Access

High
Category
Privilege Escalation
Content
check_environment() {
    # Detect unsupported environments
    if [[ -f /.dockerenv ]] || grep -q docker /proc/1/cgroup 2>/dev/null; then
        echo '{"ok":false,"error":"Docker containers not supported - no keychain access"}' >&2
        return 1
    fi
    if grep -qi microsoft /proc/version 2>/dev/null; then
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
check_environment() {
    # Detect unsupported environments
    if [[ -f /.dockerenv ]] || grep -q docker /proc/1/cgroup 2>/dev/null; then
        echo '{"ok":false,"error":"Docker containers not supported - no keychain access"}' >&2
        return 1
    fi
    if grep -qi microsoft /proc/version 2>/dev/null; then
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
check_environment() {
    # Detect unsupported environments
    if [[ -f /.dockerenv ]] || grep -q docker /proc/1/cgroup 2>/dev/null; then
        echo '{"ok":false,"error":"Docker containers not supported - no keychain access"}' >&2
        return 1
    fi
    if grep -qi microsoft /proc/version 2>/dev/null; then
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
return 1
    fi
    if [[ "$(uname)" == "Linux" && -z "${DBUS_SESSION_BUS_ADDRESS:-}" ]]; then
        echo '{"ok":false,"error":"No D-Bus session - cannot access keyring (headless?)"}' >&2
        return 1
    fi
}
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Intent-Code Divergence

High
Confidence
99% confidence
Finding
The guide says users should never paste keys in chat, yet the macOS add/update examples require the API key inline on the command line via the -w argument. Supplying secrets directly on the command line can expose them through shell history, process listings, audit logs, screenshots, or copied transcripts, creating a direct credential leakage path.

Description-Behavior Mismatch

High
Confidence
98% confidence
Finding
The document claims keys are never exposed to agent context, but its verification step explicitly retrieves and prints the stored secret value to stdout. In an agent-assisted workflow, terminal output may be captured, echoed back, logged, screen-shared, or otherwise exposed, defeating the stated secrecy boundary and risking credential disclosure.

YARA rule 'backdoor_persistence': Backdoor persistence with malicious payloads (shell commands, SSH key injection, hidden root users) [malware]

High
Category
YARA Match
Content
# Keys Setup

## Requirements

- **macOS** or **Linux with desktop** (GNOME/KDE with keyring)
- curl, jq, bash 4.0+
- NOT supported: Docker, WSL, headless servers

## Install

```bash
# Copy to PATH
cp keys-broker.sh ~/.local/bin/keys-broker
chmod +x ~/.local/bin/keys-broker

# Ensure ~/.local/bin is in PATH
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc
```

## Verify

```bash
# Check dependencies
keys-broker ping
# {"ok":true,"status":"running"}

# List configured services
keys-broker services
# {"ok":true,"services":["openai","anthropic","stripe","github"]}
```

## How It Works

```
Agent                        Keys Broker
  │                              │
  │ {"call": "openai", ...}      │
  ├─────────────────────────────►│
  │                              │ ← validates URL against allowli
Confidence
75% confidence
Finding
YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Lp3

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding
The skill documents shell-based capability (`curl`, `jq`, `bash`, and a `keys-broker` command) but does not declare an explicit tool scope such as permissions or allowed-tools. That omission weakens policy boundaries and makes it harder for the host agent to constrain execution, especially for a skill that can trigger authenticated outbound API requests via a local broker.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
## Rules

1. **Never retrieve keys directly** — always use `keys-broker call`
2. **Never ask user to paste keys in chat** — guide them to keychain commands

## Other Tasks
Confidence
80% confidence
Finding
Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
# Build auth header via file (not visible in ps)
    printf 'Authorization: Bearer %s' "$key" > "$tmp_header"
    chmod 600 "$tmp_header"
    
    # Make request with timeout
    local http_code curl_exit
Confidence
80% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

External Transmission

Medium
Category
Data Exfiltration
Content
# Make request with timeout
    local http_code curl_exit
    if [[ -n "$body" && "$body" != "null" ]]; then
        http_code=$(curl -s \
            --connect-timeout 10 \
            --max-time 120 \
            -X "$method" \
Confidence
70% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
services      List configured services

JSON format for call:
  {"action":"call","service":"openai","url":"https://api.openai.com/v1/...","method":"POST","body":{...}}
EOF
            exit 1
            ;;
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
services      List configured services

JSON format for call:
  {"action":"call","service":"openai","url":"https://api.openai.com/v1/...","method":"POST","body":{...}}
EOF
            exit 1
            ;;
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The verification commands reveal the full stored secret without any warning or masking, which encourages unsafe validation behavior. Even if intended for local confirmation, exposing the plaintext key increases the chance it is captured by logs, terminal integrations, remote support sessions, or the agent itself.

Missing User Warnings

Low
Confidence
93% confidence
Finding
This markdown file includes commands that persistently change the user's shell startup file by appending a PATH export and then reloading the shell configuration. The instructions do not explicitly warn the user that their local environment configuration will be modified, which is a user-impacting system change.

Static analysis

No suspicious patterns detected.