Back to skill

Security audit

Npjames 1password

Security checks for vulnerabilities and agentic risk

Overview

This 1Password CLI skill is mostly coherent, but some examples can expose real secrets in terminal output, captured logs, or plaintext files.

Review before installing. Use this skill only if you will control the exact op commands run, avoid printenv, echo, --no-masking, and pane capture after secret-producing commands, and avoid writing injected secrets or private keys to disk unless permissions and cleanup are handled explicitly.

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
SKILL.md:40
Finding
Plaintext Secret Exposure Through Terminal Output, Tmux Capture, and Files## Vulnerability Details **File Location**: `SKILL.md:40-45`; `references/cli-examples.md:10-13,17-19,23-24` **Vulnerability Type**: Plaintext credential disclosure caused by unsafe secret-handling examples **Risk Level**: High ### Vulnerable Code `SKILL.md:40-45`: ```bash tmux -S "$SOCKET" new -d -s "$SESSION" -n shell tmux -S "$SOCKET" send-keys -t "$SESSION":0.0 -- "op signin --account my.1password.com" Enter tmux -S "$SOCKET" send-keys -t "$SESSION":0.0 -- "op whoami" Enter tmux -S "$SOCKET" send-keys -t "$SESSION":0.0 -- "op vault list" Enter tmux -S "$SOCKET" capture-pane -p -J -t "$SESSION":0.0 -S -200 tmux -S "$SOCKET" kill-session -t "$SESSION" ``` `references/cli-examples.md:10-13`: ```bash - `op read op://app-prod/db/password` - `op read "op://app-prod/db/one-time password?attribute=otp"` - `op read "op://app-prod/ssh key/private key?ssh-format=openssh"` - `op read --out-file ./key.pem op://app-prod/server/ssh/key.pem` ``` `references/cli-examples.md:17-19`: ```bash - `export DB_PASSWORD="op://app-prod/db/password"` - `op run --no-masking -- printenv DB_PASSWORD` - `op run --env-file="./.env" -- printenv DB_PASSWORD` ``` `references/cli-examples.md:23-24`: ```bash - `echo "db_password: {{ op://app-prod/db/password }}" | op inject` - `op inject -i config.yml.tpl -o config.yml` ``` ### Technical Analysis Several documented examples resolve sensitive 1Password references directly to standard output or plaintext files. In particular, `op run --no-masking -- printenv DB_PASSWORD` explicitly disables 1Password's output masking and prints the resolved database password. The `op read` and piped `op inject` examples can likewise place passwords, one-time passwords, or private keys in terminal output. The required workflow subsequently demonstrates `tmux capture-pane`, which copies terminal scrollback to the caller's output. If a secret-producing command is run in the same pane, its ...[truncated 2150 chars]
Remediation
## Remediation Suggestions 1. Remove `--no-masking` and all examples that pass resolved secrets to `printenv`, `echo`, or other standard-output commands. 2. Demonstrate `op run` only by launching the intended application directly, without displaying its secret-bearing environment: ```bash op run --env-file="./.env" -- ./application ``` 3. Do not run `tmux capture-pane` after any command that may display a secret. Use a separate pane for authentication and status checks, clear scrollback before capture, or avoid pane capture entirely. 4. Replace direct `op read` examples with examples that consume the secret without printing it. Where output is inherently required, add an explicit warning that the command must not be executed through captured or logged terminals. 5. Avoid writing private keys or injected configurations to disk. Prefer process substitution, standard input, or an application interface that consumes the secret in memory. 6. When a file is unavoidable, create it in a protected directory with restrictive permissions, for example by setting `umask 077`, and securely delete it immediately after use. 7. Add automated redaction or output filtering as defense in depth, while making clear that redaction is not a substitute for avoiding plaintext output. 8. Update the workflow so its examples are consistent with the existing prohibition against placing secrets in logs, chat, or code.
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
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (5)

Env Variable Harvesting

High
Category
Data Exfiltration
Content
## Run

- `export DB_PASSWORD="op://app-prod/db/password"`
- `op run --no-masking -- printenv DB_PASSWORD`
- `op run --env-file="./.env" -- printenv DB_PASSWORD`

## Inject
Confidence
98% confidence
Finding
`op run --no-masking -- printenv DB_PASSWORD` explicitly causes a resolved secret to be printed in cleartext to the terminal, and `--no-masking` disables a key safety feature meant to reduce accidental exposure. This can leak credentials to shell history captures, terminal scrollback, CI logs, session recordings, or any observer with access to the execution environment.

Env Variable Harvesting

High
Category
Data Exfiltration
Content
- `export DB_PASSWORD="op://app-prod/db/password"`
- `op run --no-masking -- printenv DB_PASSWORD`
- `op run --env-file="./.env" -- printenv DB_PASSWORD`

## Inject
Confidence
94% confidence
Finding
`op run --env-file="./.env" -- printenv DB_PASSWORD` also prints the resolved secret value to stdout, creating the same exposure channel even without the explicit `--no-masking` flag. In the context of a 1Password CLI skill, this is especially sensitive because the command teaches users to retrieve and display live secrets rather than consume them safely within an application process.

Credential Access

High
Category
Privilege Escalation
Content
- `export DB_PASSWORD="op://app-prod/db/password"`
- `op run --no-masking -- printenv DB_PASSWORD`
- `op run --env-file="./.env" -- printenv DB_PASSWORD`

## Inject
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The examples demonstrate writing secret material to local files (`--out-file ./key.pem` and `op inject ... -o config.yml`) without any warning about file permissions, persistence, or cleanup. In a secrets-management skill, this can lead users to store plaintext secrets or private keys on disk insecurely, increasing the chance of later disclosure through backups, logs, repo commits, or permissive file modes.

Unrestricted Tool Access

Medium
Category
Excessive Agency
Content
- macOS: Settings > Developer > Integrate with 1Password CLI (Touch ID optional).
  - Windows: turn on Windows Hello, then Settings > Developer > Integrate.
  - Linux: Settings > Security > Unlock using system authentication, then Settings > Developer > Integrate.
- After integration, run any command to sign in (example in docs: `op vault list`).
- If multiple accounts: use `op signin` to pick one, or `--account` / `OP_ACCOUNT`.
- For non-integration auth, use `op account add`.
Confidence
80% confidence
Finding
Skill grants unrestricted tool access without appropriate constraints. An agent with unfettered tool access can perform arbitrary actions including file modification, network requests, and code execution.

Static analysis

No suspicious patterns detected.