Back to skill

Security audit

Headless Vault CLI

Security checks for vulnerabilities and agentic risk

Overview

The skill has a coherent purpose, but its SSH command construction can turn untrusted configuration into local command execution.

Review before installing. The vault access model is disclosed and mostly purpose-aligned, but the SSH wrapper should validate username, host, and port, avoid unquoted SSH examples, and use safer argv handling before this is trusted with a personal notes vault.

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
vault.sh:25
Finding

SSH Option Injection Through Unvalidated Connection Parameters

Content
View full analysis
&2 exit 1 fi # Run vaultctl command on remote Mac run_vaultctl() { ssh $SSH_OPTS -p "$VAULT_SSH_PORT" "${VAULT_SSH_USER}@${VAULT_SSH_HOST}" vaultctl "$@" } ``` The related instruction in `SKILL.md` directly interpolates the same parameters: ```bash ssh -4 -p ${VAULT_SSH_PORT:-2222} ${VAULT_SSH_USER}@${VAULT_SSH_HOST:-localhost} vaultctl [args] ``` ### Technical Analysis The script accepts the SSH username, host, and port from environment variables, with the username also optionally loaded from a configuration file. These values are not validated before being passed to OpenSSH. Although the combined destination is shell-quoted in `vault.sh`, quoting only prevents shell word splitting and expansion. It does not stop the `ssh` executable from interpreting an argument beginning with `-` as an SSH option. If `VAULT_SSH_USER` begins with an option such as `-oProxyCommand=`, the resulting destination argument can be parsed as an SSH option instead of as `[user@]hostname`. OpenSSH's `ProxyCommand` option invokes a local command through a shell, creating a local command-execution primitive. For example, a maliciou ...[truncated 2384 chars]
Remediation
View remediation
&2 exit 1 fi if [[ ! "$VAULT_SSH_HOST" =~ ^[A-Za-z0-9.-]+$ ]] || [[ "$VAULT_SSH_HOST" == -* ]]; then echo '{"error":"invalid_config","message":"Invalid SSH host"}' >&2 exit 1 fi if [[ ! "$VAULT_SSH_PORT" =~ ^[0-9]+$ ]] || (( VAULT_SSH_PORT < 1 || VAULT_SSH_PORT > 65535 )); then echo '{"error":"invalid_config","message":"Invalid SSH port"}' >&2 exit 1 fi ``` 2. **Use an array for fixed SSH options.** ```bash SSH_OPTS=( -4 -o ConnectTimeout=10 -o BatchMode=yes -o StrictHostKeyChecking=yes ) run_vaultctl() { local destination="${VAULT_SSH_USER}@${VAULT_SSH_HOST}" ssh "${SSH_OPTS[@]}" -p "$VAULT_SSH_PORT" -- \ "$destination" vaultctl "$@" } ``` Use `--` only after verifying that the deployed OpenSSH client supports it. Input validation remains required because compatibility and parsing behavior can vary. 3. **Prefer fixed connection settings.** If the intended architecture always uses a local reverse tunnel, hard-code or enforce `VAULT_SSH_HOST=localhost` rather than accepting an arbitrary host. 4. **Secure the fallback configuration file.** - Require it to be owned by the current user. - Reject group- or world-writable files. - Read only a single validated line. - Avoid following untrusted symlinks where practical. 5. **Update `SKILL.md`.** Remove d ...[truncated 543 chars]
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (5)

Credential Access

High
Category
Privilege Escalation
Confidence
90% confidence
Finding

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

Content

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

md
This is an instruction-only skill. Before using it, the user must complete a one-time setup on their local machine:

1. **Install vaultctl** on the local machine (see [setup instructions](https://github.com/logancyang/headless-vault-cli))
2. **Configure SSH forced-command** on the local machine's `~/.ssh/authorized_keys` to restrict the VPS key to only run `vaultctl` (see Security Model below)
3. **Start a reverse SSH tunnel** from the local machine to the VPS, exposing `localhost:2222`
4. **Set the environment variable** `VAULT_SSH_USER` to the local machine's username

Credential Access

High
Category
Privilege Escalation
Confidence
90% confidence
Finding

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

Content

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

md
This is an instruction-only skill. Before using it, the user must complete a one-time setup on their local machine:

1. **Install vaultctl** on the local machine (see [setup instructions](https://github.com/logancyang/headless-vault-cli))
2. **Configure SSH forced-command** on the local machine's `~/.ssh/authorized_keys` to restrict the VPS key to only run `vaultctl` (see Security Model below)
3. **Start a reverse SSH tunnel** from the local machine to the VPS, exposing `localhost:2222`
4. **Set the environment variable** `VAULT_SSH_USER` to the local machine's username

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The skill activation description is broad enough to trigger on many ordinary note-related requests, which can cause the agent to route sensitive user interactions through this SSH-based skill more often than necessary. In this context, overbroad activation increases exposure of a user's local vault and SSH tunnel to unintended use, even if the underlying commands are constrained.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
83% confidence
Finding

The read command retrieves vault content from a remote Mac via ssh and returns the result, which is a safety-sensitive data access operation. Although the file comments describe remote execution generally, there is no confirmation prompt or explicit user-facing warning near the command path that sensitive vault contents will be accessed and transmitted.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The create and append branches send user-provided content to a remote system and modify vault state, which are write operations affecting user data. The script performs these actions directly with no confirmation prompt, no user-facing disclosure in output, and no inline warning about the remote and potentially irreversible nature of the modification.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.