Back to skill

Security audit

Actual AI CLI

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches its ADR-sync helper purpose, but it needs Review because its diagnostic script may print authentication, configuration, and repository details despite claiming it will not reveal secrets.

Review the diagnostic output before sharing it anywhere, and avoid running the diagnostic script in repositories or environments with sensitive config until its redaction is improved. Use dry-run first, approve any file writes explicitly, prefer environment variables or a secure secret store over command-line API-key examples, and pin or verify external CLI versions where possible.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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 (2)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/diagnose.sh:110
Finding
Incomplete Credential Redaction in Diagnostic Output<![CDATA[ ## Vulnerability Details **File Location**: `scripts/diagnose.sh:110-124` **Vulnerability Type**: Insufficient secret redaction and sensitive configuration disclosure **Risk Level**: Medium ### Vulnerable Code ```bash # Show config (non-sensitive fields only) config_output=$(actual config show 2>&1) || config_output="(could not read config)" while IFS= read -r line; do # Skip lines that look like they contain API key values case "$line" in *api_key*:*sk-*|*api_key*:*key-*) # Redact actual key values but show the field exists field=$(echo "$line" | cut -d: -f1) info "$field: [REDACTED]" ;; *) [ -n "$line" ] && info "$line" ;; esac done <<< "$config_output" ``` ### Technical Analysis The diagnostic script captures the complete output of `actual config show` and prints every line that does not match two narrow shell patterns: ```bash *api_key*:*sk-* *api_key*:*key-* ``` Redaction therefore depends both on a lowercase `api_key` field name and on the value having an anticipated prefix. Credentials with other formats—including Cursor API keys, custom provider keys, bearer tokens, uppercase or differently named fields, and credentials without `sk-` or `key-` prefixes—fall through to the default branch and are printed unchanged. This conflicts with the script's assertion that it “Never prints secrets.” The problem is especially relevant because the Skill explicitly recommends this script for comprehensive diagnostics. Its output may consequently be captured by an AI agent, terminal recording, CI system, support transcript, or shared issue report. The vulnerability does not independently grant system privileges. Exploitation requires a sensitive value to appear in the output of `actual config show` using a format not recognized by the redaction patterns. ### Attack Path 1. A user stores an API key or another credential in the Actual configuration. 2. The credential does not contain an anticipated `sk ...[truncated 1184 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace value-prefix detection with redaction based on normalized sensitive field names. At minimum, redact fields containing terms such as: - `api_key` - `apikey` - `token` - `secret` - `password` - `credential` - `authorization` 2. Prefer an allowlist approach: print only configuration fields explicitly known to be non-sensitive, rather than printing all unmatched output. 3. Add a machine-readable, guaranteed-redacted command to the Actual CLI, such as: ```bash actual config show --redacted --format json ``` The diagnostic script should consume only that output. 4. Treat standard error as potentially sensitive. Do not combine unrestricted standard error with configuration output unless it is also sanitized. 5. Add tests covering: - Cursor keys without recognizable prefixes - Arbitrary bearer tokens - Uppercase and mixed-case field names - Quoted YAML values - Values containing spaces or colons - Multiline YAML values - Unknown future credential fields 6. Until robust redaction is available, report only whether known credential fields are configured, never their values. ]]>

T08 · Insecure Dependencies

Warning
Location
SKILL.md:35
Finding
Unpinned Execution of Third-Party CLI Packages<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:35-45` **Additional Locations**: `README.md:42-43`, `references/error-catalog.md:196`, `references/error-catalog.md:215-216` **Vulnerability Type**: Unpinned third-party dependency installation and execution **Risk Level**: Medium ### Vulnerable Code ```markdown Install options (try in this order): | Method | Command | |--------|---------| | npm/npx (quickest) | `npm install -g @actualai/actual` | | Homebrew (macOS/Linux) | `brew install actual-software/actual/actual` | | GitHub Release (manual) | Download from `actual-software/actual-releases` on GitHub | For one-off use without installing globally: ```bash npx @actualai/actual adr-bot [flags] ``` ``` Related instructions also recommend: ```bash npm install -g @anthropic-ai/claude-code ``` ### Technical Analysis The installation instructions use package names without fixed versions or integrity verification. Both `npm install -g @actualai/actual` and `npx @actualai/actual` resolve a mutable package version at execution time. In particular, `npx` may download and immediately execute package code that was not present when this Skill was audited. The audited repository contains only the Skill documentation and diagnostic script; the principal `actual` CLI implementation is external and was not available for review. That external CLI receives access to repository contents, configuration files, API credentials, and output instruction files as part of its documented operation. No evidence was found that the named packages are currently malicious. The security weakness is that the instructions do not constrain execution to a reviewed release. Successful exploitation therefore depends on compromise of an upstream package, release account, registry, distribution channel, or transitive dependency. ### Attack Path 1. An attacker compromises the npm publisher account, release pipeline, package registry entry, Homebrew tap, or a transitive depen ...[truncated 1529 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin every recommended package to a specific reviewed version: ```bash npm install -g @actualai/actual@X.Y.Z npx --yes @actualai/actual@X.Y.Z adr-bot npm install -g @anthropic-ai/claude-code@X.Y.Z ``` 2. Publish and document SHA-256 checksums or signed attestations for manual release artifacts. 3. Verify release signatures and checksums before executing downloaded binaries. 4. Avoid automatically using the latest Homebrew tap revision. Document a reviewed formula version or commit where practical. 5. Prefer locally installed, verified binaries over one-off `npx` execution. 6. Recommend running package installations without elevated privileges. Do not use `sudo` unless it is strictly required and explicitly approved. 7. Document the package publisher, official registry URL, expected package scope, and verified release source to reduce dependency-confusion and typosquatting risk. 8. Maintain a release-review process covering direct and transitive dependencies, installation scripts, provenance attestations, and lockfile integrity. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (14)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The description presents a broad, feature-complete operational companion for the CLI, including generating files, running adr-bot, configuring runners/models, and covering all runners, model patterns, output formats, and error types. The supplied code is much narrower: it is a single read-only diagnostic script. It checks for installed binaries, reports auth/status/config information, verifies environment variables, inspects config file presence/permissions, looks for output files and markers, and reports git context. Those behaviors support troubleshooting, but they do not implement the larger claimed capabilities such as generation, configuration, or full operational control. Therefore the declared description materially overstates what the code chunk actually does.

External Model or Provider Selection

High
Category
Excessive Agency
Content
actual adr-bot --project services/api --project services/web

# Use a specific runner/model
actual adr-bot --runner anthropic-api --model claude-sonnet-4-6

# Skip AI tailoring (use raw ADRs)
actual adr-bot --no-tailor
Confidence
90% confidence
Finding
Skill selects an external model or provider that may use a different account or billing plan than the operator expects. Undisclosed model switches can cause unexpected cost or quota consumption.

Intent-Code Divergence

High
Confidence
98% confidence
Finding
The script explicitly claims it never prints secrets, but it forwards raw output from `actual auth` line-by-line with no redaction. If `actual auth` includes tokens, account identifiers, session details, or verbose error output containing credentials, this diagnostic script will disclose them to the terminal, logs, CI output, or support transcripts. In the context of a troubleshooting skill, users are especially likely to paste or share this output, increasing exfiltration risk.

Intent-Code Divergence

High
Confidence
97% confidence
Finding
The config display code only redacts lines matching narrow patterns like `sk-` or `key-`, which is insufficient for the wide variety of secret formats used by APIs, bearer tokens, OAuth credentials, session cookies, and custom config values. Because the script claims it never prints secrets, users may trust and widely share the output, but `actual config show` could emit unredacted sensitive values that bypass these simplistic checks.

Rp1

Medium
Category
MCP Rug Pull
Confidence
83% confidence
Finding
The skill recommends executing `npx @actualai/actual` without pinning a specific version, which makes behavior non-deterministic and exposes users to supply-chain risk if a newer or compromised package version is published. Because this skill is explicitly operational and instructs users to run CLI tooling, the unpinned package reference is more dangerous than a passive documentation mention.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
# Preview with full content
actual adr-bot --dry-run --full

# Run sync, skip confirmation prompts
actual adr-bot --force

# Sync specific subdirectories only (monorepo)
Confidence
85% 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.

Session Persistence

Medium
Category
Rogue Agent
Content
### API Keys in Config

API keys set via `config set` are stored in the config YAML file. The file is created with 0600 permissions (owner read/write only) on Unix systems.

```bash
actual config set anthropic_api_key "sk-ant-..."
Confidence
76% confidence
Finding
The documentation explicitly recommends storing long-lived API keys in a persistent local config file. Even with 0600 permissions, persistent storage increases the chance of compromise through backups, local malware, accidental file disclosure, or multi-tool access on the same account; in this skill context, the keys grant access to external AI services and potentially billable usage.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The guide states that if `codex-cli` encounters a model-related error, the tool transparently falls back to `openai-api` and retries. Silent provider switching can change where prompts, repository contents, or other sensitive inputs are sent, defeating user expectations about authentication mode, data handling, auditability, and consent.

Intent-Code Divergence

Medium
Confidence
95% confidence
Finding
The runner overview and probe logic consistently describe the cursor runner as using the `cursor-agent` binary (L027, L234), but the cursor-cli requirements and troubleshooting sections say the required binary is `agent` and recommend `which agent` (L188, L265-L267). This is an active documentation contradiction that could cause users to validate or install the wrong executable.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The document states that repository analysis results, ADR content, and codebase context are sent to external API and AI runners, but it does not pair that behavior with an explicit privacy, data-handling, or consent warning. In a tool that may process proprietary source code, this omission can cause users to transmit sensitive code or metadata off-host without fully informed consent, increasing confidentiality and compliance risk.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
|------|-------|---------|-------|
| `--dry-run` | | Preview without writing | Safe, no side effects |
| `--full` | | Show full content in dry-run | Requires `--dry-run` |
| `--force` | | Skip confirmations, bypass cache | |
| `--project PATH` | | Filter to subdirectory | Repeatable for monorepos |
| `--model MODEL` | | Override model | Auto-infers runner from model name |
| `--runner RUNNER` | | Override runner | One of: claude-cli, anthropic-api, openai-api, codex-cli, cursor-cli |
Confidence
85% 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.

Intent-Code Divergence

Medium
Confidence
91% confidence
Finding
The script prints the full Git origin URL even though its header promises strong secrecy hygiene. Remote URLs can embed usernames, access tokens, internal hostnames, repository names, or other sensitive infrastructure details, and these are often copied into issue trackers or chat during debugging. This is less severe than raw credential leakage but still a real disclosure risk.

Missing User Warnings

Low
Confidence
91% confidence
Finding
The documentation shows users passing API keys directly on the command line, which can expose secrets via shell history, process listings, terminal scrollback, and logging systems. Although the file notes that the config is stored with 0600 permissions, it does not warn that the example invocation method itself may leak the key before it is safely written.

Missing User Warnings

Low
Confidence
85% confidence
Finding
The diagnostic reports repository remote URLs without warning the user that they may reveal private repository names, internal domains, usernames, or embedded credentials. In a support-oriented skill, this increases the chance that users will share sensitive metadata externally without realizing it.

Static analysis

No suspicious patterns detected.