Skill: in-liberty420/1password-sa (version 1.0.2)

--- name: 1password-sa description: Securely inject secrets from 1Password into agent workflows. Uses service accounts with op run/.env.tpl as the primary pattern, op read as fallback. Includes hardened security rules, input validation, and troubleshooting for auth/permission failures. Use when accessing API keys, credentials, or any 1Password secret. homepage: https://developer.1password.com/docs/cli/get-started/ metadata: { "openclaw": { "emoji": "🔐", "requires": { "bins": ["op"] }, "env": ["OP_SERVICE_ACCOUNT_TOKEN"], "install": [ { "id": "brew", "kind": "brew", "formula": "1password-cli", "bins": ["op"], "label": "Install 1Password CLI (brew)", }, ], }, } --- # 1Password CLI (Hardened) Secure secret access via 1Password CLI (`op`) for OpenClaw agents. Service accounts are the canonical approach. ## References - `references/get-started.md` — install + baseline setup - `references/cli-examples.md` — safe command patterns - `references/troubleshooting.md` — failure/recovery runbook ## Security Rules (must follow) 1. **Prefer `op run` over all alternatives** for secret injection. 2. **Never enable shell tracing** around secret commands (`set -x`, `bash -x`). 3. **Never print secrets to stdout/logs** (`echo`, `cat` on secret values/files). `printf` piped directly to stdin of another command (e.g., `printf ... | curl -H @-`) is acceptable when the output never reaches a log or terminal. 4. **Never dump environment** inside/after secret-bearing runs (`env`, `printenv`, `set`). 5. **Never pass secrets as CLI args** (arguments can appear in process lists). 6. **Never pipe secret output to logs/files** (`tee`, `>`, `>>`) unless explicitly writing a protected temporary file for `op inject`. 7. **Never pipe `op read` output into logging pipelines.** 8. **Use `op inject` only with locked-down temp files:** `umask 077`, `chmod 600`, `trap` cleanup. 9. **Never include secret values in chat, tool output, or agent responses.** If a command outputs a secret, do not echo or reference its value. ### Banned Flags/Patterns - **`--no-masking`** — never use in agent workflows. Masking redacts accidental secret output and must stay on. - **`--reveal`** — never use in routine workflows. Outputs field values in cleartext. - **`op signin --raw`** — outputs raw session token to stdout. - **Bare `op read`** — never run without capturing into a variable. It prints secrets to stdout. - **`set -x`** — never enable around any `op` command. - **`curl -v`** — verbose mode logs auth headers. Use `curl -sSf` instead. - **`script`** / **terminal recorders** — session recording captures all secret output. ### Untrusted Input - Never interpolate user-provided or external text into shell commands without strict quoting. - Always use `--` to separate `op` flags from command arguments. - Vault/item/field names from untrusted sources must be validated (alphanumeric, hyphens, underscores, and spaces only). - Never use `eval`, backtick substitution, or string-built shell commands with secret references. - If an item name looks suspicious (contains `$`, backticks, semicolons, or pipes), stop and verify with the user. **Safe dynamic input template:** ```bash VAULT="my-vault" ITEM="my-item" # Validate: reject names with dangerous characters for NAME in "$VAULT" "$ITEM"; do if ! LC_ALL=C [[ "$NAME" =~ ^[a-zA-Z0-9\ _-]+$ ]]; then echo "ERROR: invalid vault/item name: $NAME" >&2; exit 1 fi done VALUE="$(op read "op://${VAULT}/${ITEM}/password")" # use $VALUE, then: unset VALUE ``` Always double-quote variable expansions. Never build `op://` references from untrusted input without validation. Reject names containing `/`, `$`, backticks, semicolons, pipes, or other shell metacharacters. ### `.env.tpl` Security - Treat as code: verify ownership, review changes, restrict permissions (`chmod 600`). - Do not accept `.env.tpl` files from untrusted sources. - Do not commit to public repos — references reveal vault/item structure. - Add to `.gitignore` if in a repo. - After creating/editing: `chmod 600 .env.tpl` - Only define expected variable names — reject templates containing dangerous env vars (`PATH`, `LD_PRELOAD`, `BASH_ENV`, `NODE_OPTIONS`, etc.). --- ## Service Account Workflow (Primary) Service accounts are the default for agents. No interactive auth needed. ### 1) Load and scope token Load the token from your platform's secure store: ```bash # macOS Keychain: # security find-generic-password -a <account> -s OP_SERVICE_ACCOUNT_TOKEN -w # Linux (GNOME Keyring / libsecret): # secret-tool lookup service OP_SERVICE_ACCOUNT_TOKEN # Last resort (interactive prompt, not automatable): # read -rs OP_SERVICE_ACCOUNT_TOKEN OP_SERVICE_ACCOUNT_TOKEN="$(__REPLACE_WITH_SECURE_STORE_COMMAND__)" [ -z "$OP_SERVICE_ACCOUNT_TOKEN" ] && { echo "ERROR: token retrieval failed" >&2; exit 1; } ``` **Preferred: single-command scope** (token never persists in shell env): ```bash OP_SERVICE_ACCOUNT_TOKEN="$OP_SERVICE_ACCOUNT_TOKEN" \ op run --env-file=.env.tpl -- <command> unset OP_SERVICE_ACCOUNT_TOKEN ``` **If multiple commands needed:** export briefly with trap cleanup: ```bash export OP_SERVICE_ACCOUNT_TOKEN trap 'unset OP_SERVICE_ACCOUNT_TOKEN' EXIT op run --env-file=.env.tpl -- <command-1> op run --env-file=.env.tpl -- <command-2> unset OP_SERVICE_ACCOUNT_TOKEN ``` ### 2) Use `.env.tpl` + `op run` (preferred) Create `.env.tpl` with 1Password references (not raw secrets): ``` [REDACTED_SECRET] DB_PASSWORD=op://my-vault/my-item/password ``` Run: ```bash op run --env-file=.env.tpl -- <command> ``` Masking is on by default and must stay on. Note: masking is defense-in-depth, not primary protection — transformed or partial secrets may evade redaction. The primary defense is never outputting secrets. ### 3) One-off fallback: `op read` Use only when `op run` doesn't fit. Use a subshell for automatic cleanup: ```bash ( trap 'unset VALUE' EXIT VALUE="$(op read 'op://my-vault/my-item/field')" # use $VALUE here — auto-cleaned on exit ) ``` For API calls, prefer `op run` with a wrapper script to avoid `sh -c`: ```bash # api-call.sh (chmod +x) #!/usr/bin/env bash set -euo pipefail printf "Authorization: Bearer %s\n" "$API_TOKEN" | curl -sSf -H @- https://api.example.com/resource ``` ```bash op run --env-file=.env.tpl -- ./api-call.sh ``` ### 4) Diagnostics > **All diagnostic output contains metadata** (account emails, vault names, item IDs, URLs) that should be treated as sensitive in logged/recorded agent sessions. ```bash op whoami op vault list --format json ``` ### 5) Service account lifecycle - **Scope is policy-driven:** read-only vs read-write depends on configuration and vault permissions. - **If access fails:** verify vault grants and item permissions. - **If token expired/revoked:** regenerate in 1Password admin, update secure store, retry. - **Limitation:** service accounts may not support item creation depending on org policy. --- ## `op inject` (restricted use) Use only when a file must be materialized temporarily: ```bash set -euo pipefail set +x umask 077 TMP_FILE="$(mktemp)" cleanup() { rm -f "$TMP_FILE"; } trap cleanup EXIT ERR INT TERM HUP QUIT op inject -i config.tpl -o "$TMP_FILE" chmod 600 "$TMP_FILE" # use "$TMP_FILE" briefly, then auto-cleanup via trap ``` Never persist injected secret files beyond immediate use.

path: references/cli-examples.md
content: # 1Password CLI examples (safe patterns)

All examples use generic placeholders (`my-vault`, `my-item`, `[REDACTED_SECRET]`).

## Identity check

```bash
op whoami
```

## Vault and item discovery

> **Note:** These commands output vault/item names and metadata. In logged/recorded agent sessions, treat this output as sensitive — it reveals infrastructure structure.

```bash
op vault list --format json
op item list --vault "my-vault" --format json
```

## Get item metadata (without secret values)

```bash
op item get "my-item" --vault "my-vault" --format json
```

Returns metadata and field labels but not secret values (unless `--reveal` is used, which is banned). Output may contain usernames, URLs, and item IDs — treat as sensitive in logged contexts.

## Read single secret into variable

Always capture in a subshell for automatic cleanup:

```bash
(
  trap 'unset VALUE' EXIT
  VALUE="$(op read 'op://my-vault/my-item/password')"
  # use $VALUE here — auto-cleaned on exit
)
```

## Safe dynamic input pattern

When vault/item names come from variables, validate and double-quote:

```bash
VAULT="my-vault"
ITEM="my-item"
FIELD="password"

# Validate: reject names with dangerous characters
for NAME in "$VAULT" "$ITEM" "$FIELD"; do
  if ! LC_ALL=C [[ "$NAME" =~ ^[a-zA-Z0-9\ _-]+$ ]]; then
    echo "ERROR: invalid name: $NAME" >&2; exit 1
  fi
done

VALUE="$(op read "op://${VAULT}/${ITEM}/${FIELD}")"
# use $VALUE here
unset VALUE  # or wrap in subshell for auto-cleanup
```

## Run command with `.env.tpl` (preferred)

`.env.tpl` contents:

```
API_TOKEN=op://my-vault/my-item/api-token
```

Single-command scoped token + run:

```bash
# api-call.sh (chmod +x)
#!/usr/bin/env bash
set -euo pipefail
printf "Authorization: Bearer %s\n" "$API_TOKEN" | curl -sSf -H @- https://api.example.com/health
```

```bash
OP_SERVICE_ACCOUNT_TOKEN="$(__REPLACE_WITH_SECURE_STORE_COMMAND__)"
[ -z "$OP_SERVICE_ACCOUNT_TOKEN" ] && { echo "ERROR: token retrieval failed" >&2; exit 1; }
OP_SERVICE_ACCOUNT_TOKEN="$OP_SERVICE_ACCOUNT_TOKEN" \
  op run --env-file=.env.tpl -- ./api-call.sh
unset OP_SERVICE_ACCOUNT_TOKEN
```

## Run with inline env-file (temporary)

```bash
umask 077
TMPFILE=$(mktemp "${TMPDIR:-/tmp}/op-env.XXXXXX")
trap 'rm -f "$TMPFILE"' EXIT ERR INT TERM HUP
cat > "$TMPFILE" <<'EOF'
[REDACTED_SECRET]
EOF
chmod 600 "$TMPFILE"
op run --env-file="$TMPFILE" -- my-command
```

## Banned patterns (never use)

- `op run --no-masking` — disables output redaction
- `op item get --reveal` — outputs secret values in cleartext
- `op signin --raw` — outputs raw session token to stdout
- `op read "op://..."` without variable capture — prints secret to stdout
- `set -x` before any `op` command — logs secrets to trace output
- `curl -v` with secret headers — verbose mode logs auth headers
- `script` / terminal recorders — records all output including secrets


path: references/get-started.md
content: # 1Password CLI get started (safe baseline)

## 1) Install and verify

Install `op` using your platform package manager (see official docs), then verify:

```bash
op --version
```

## 2) Configure service account

Load token from your platform's secure store (see SKILL.md §1 for platform examples):

```bash
OP_SERVICE_ACCOUNT_TOKEN="$(__REPLACE_WITH_SECURE_STORE_COMMAND__)"
[ -z "$OP_SERVICE_ACCOUNT_TOKEN" ] && { echo "ERROR: token retrieval failed" >&2; exit 1; }
```

Single-command scope:

```bash
OP_SERVICE_ACCOUNT_TOKEN="$OP_SERVICE_ACCOUNT_TOKEN" op whoami
unset OP_SERVICE_ACCOUNT_TOKEN
```

Multiple commands — export briefly with trap cleanup:

```bash
export OP_SERVICE_ACCOUNT_TOKEN
trap 'unset OP_SERVICE_ACCOUNT_TOKEN' EXIT
op whoami
# ... do work ...
unset OP_SERVICE_ACCOUNT_TOKEN
```

## 3) Preferred secret injection (`op run`)

Create `.env.tpl` in project/skill directory:

```
SECRET_NAME=op://my-vault/my-item/field
ANOTHER_SECRET=op://my-vault/another-item/password
```

Run command:

```bash
op run --env-file=.env.tpl -- <command>
```

Masking is on by default and must stay on.

## 4) One-off fallback (`op read`)

Always capture in a subshell for automatic cleanup:

```bash
(
  trap 'unset VALUE' EXIT
  VALUE="$(op read 'op://my-vault/my-item/field')"
  # use $VALUE here — auto-cleaned on exit
)
```

## 5) Safety reminders

- Never log or print secrets.
- Never use `set -x` around secret commands.
- Never pass secrets as command-line arguments.
- Never use `--no-masking` or `--reveal`.
- Prefer `op run` for everything; `op read` into variable as last resort.


path: references/troubleshooting.md
content: # 1Password CLI troubleshooting

## "not signed in"

- Ensure `OP_SERVICE_ACCOUNT_TOKEN` is set in the current shell/runtime.

> **Note:** Diagnostic commands below output metadata (account emails, vault names, IDs). Treat output as sensitive in logged/recorded sessions.
- Verify with:

```bash
op whoami --format json
```

## "account not authorized"

- Confirm service account has access to the target vault/item.
- Check vault permissions in 1Password admin.
- Validate reference path (`op://vault/item/field`) is correct.

## "consent required"

- Open the URL shown by `op` and complete consent/approval.
- Re-run the command after consent.

## Token expired / revoked

- Generate a new service-account token in 1Password admin.
- Update secure storage/runtime secret source.
- Retry and verify:

```bash
op whoami --format json
```

## Rate limits / throttling

- Use exponential backoff (e.g., 1s, 2s, 4s, 8s with jitter).
- Reduce concurrent `op` calls.
- Cache non-sensitive metadata where possible.

## Network errors / timeouts

- Retry with bounded attempts and delay.
- Confirm internet/proxy/VPN/DNS are healthy.
- Re-test with a low-impact command:

```bash
op vault list --format json
```


Security scan verdicts — ClawScan: clean | static analysis: clean | VirusTotal: clean | SkillSpector: clean (LOW)