Back to skill

Security audit

Cursor Cloud Agents

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly does what it advertises, but it handles Cursor credentials in ways that could expose them if the environment is misconfigured or controlled by someone else.

Review this before installing if you use Cursor on private repositories. Prefer setting CURSOR_API_KEY only in a dedicated file or environment variable, do not set CURSOR_API_BASE unless testing with throwaway credentials, and clear or protect ~/.cache/cursor-api on shared machines.

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 (2)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/cursor-api.sh:47
Finding
Cursor API Key Disclosure Through an Unrestricted API Base Override<![CDATA[ ## Vulnerability Details **File Location**: `scripts/cursor-api.sh:47`, `scripts/cursor-api.sh:579-589`, and `scripts/cursor-api.sh:618-647` **Vulnerability Type**: Credential disclosure through an attacker-controlled network destination **Risk Level**: High ### Vulnerable Code ```bash # Configuration readonly API_BASE="${CURSOR_API_BASE:-https://api.cursor.com/v0}" ``` ```bash # Get authorization header # Uses Basic auth with base64 encoding per Cursor API spec # The API key is read from CURSOR_API_KEY env var or config files # This is standard HTTP Basic authentication, not obfuscation get_auth_header() { local api_key credentials api_key=$(get_api_key) || return 1 credentials="${api_key}:" # Base64 encode for HTTP Basic Authentication (RFC 7617) # Format: base64(username:password) where username is API key, password is empty echo "Authorization: Basic $(printf '%s' "$credentials" | base64)" } ``` ```bash local curl_opts=( -s -w "\n%{http_code}" --connect-timeout "$CURL_CONNECT_TIMEOUT" --max-time "$CURL_MAX_TIME" ) local headers=(-H "Content-Type: application/json" -H "$(get_auth_header)") local url="${API_BASE}${endpoint}" verbose "API Request: $method $url" local response http_code curl_stderr local attempt=1 local retry_delay=2 while [[ $attempt -le $CURL_RETRY_COUNT ]]; do curl_stderr=$(mktemp) if [[ "$method" == "GET" ]]; then response=$(curl "${curl_opts[@]}" "${headers[@]}" "$url" 2>"$curl_stderr") || { error "curl failed: $(cat "$curl_stderr")" "$E_API_ERROR" } else if [[ -n "$body" ]]; then response=$(curl "${curl_opts[@]}" "${headers[@]}" -X "$method" -d "$body" "$url" 2>"$curl_stderr") || { error "curl failed: $(cat "$curl_stderr")" "$E_API_ERROR" } else response=$(curl "${curl_opts[@]}" "${headers[@]}" -X "$method" "$url" 2>"$curl_stderr") || { error "curl failed: $(ca ...[truncated 2437 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove `CURSOR_API_BASE` from production use and hardcode the trusted endpoint: ```bash readonly API_BASE="https://api.cursor.com/v0" ``` 2. If an override is required for testing, require an explicit test mode and validate the complete origin: ```bash if [[ "${CURSOR_TEST_MODE:-false}" != "true" ]]; then API_BASE="https://api.cursor.com/v0" fi ``` 3. Allowlist trusted HTTPS origins rather than relying on a prefix or substring check. Parse and verify the scheme, hostname, port, and path independently. 4. Never send production credentials to a test endpoint. Require a separate test credential variable when an override is enabled. 5. Reject plaintext HTTP endpoints and malformed URLs. 6. Document the trust implications of endpoint overrides in `SECURITY.md`, `README.md`, `SKILL.md`, and `skill.json`. 7. Add automated tests proving that arbitrary domains, plaintext HTTP URLs, embedded user information, and unexpected ports are rejected before the Authorization header is created or transmitted. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/cursor-api.sh:233
Finding
Sensitive Agent Responses and Prompts Are Cached Without Enforced Access Permissions<![CDATA[ ## Vulnerability Details **File Location**: `scripts/cursor-api.sh:233-236` and `scripts/cursor-api.sh:278-301` **Vulnerability Type**: Plaintext storage of sensitive data with permissions dependent on the caller's umask **Risk Level**: Medium ### Vulnerable Code ```bash # Write to cache write_cache() { local cache_file="$1" local data="$2" mkdir -p "$CACHE_DIR" echo "$data" > "$cache_file" } ``` ```bash # Save background task info save_bg_task() { local task_id="$1" local agent_id="$2" local repo="$3" local prompt="$4" local status="$5" local pid="$6" local max_runtime="${7:-86400}" init_bg_tasks_dir local task_file="${BG_TASKS_DIR}/${task_id}.json" jq -n \ --arg task_id "$task_id" \ --arg agent_id "$agent_id" \ --arg repo "$repo" \ --arg prompt "$prompt" \ --arg status "$status" \ --arg pid "$pid" \ --arg created_at "$(date -Iseconds)" \ --arg max_runtime "$max_runtime" \ '{ task_id: $task_id, agent_id: $agent_id, repo: $repo, prompt: $prompt, status: $status, pid: $pid, created_at: $created_at, max_runtime: $max_runtime }' > "$task_file" } ``` ### Technical Analysis The Skill stores successful GET responses in `~/.cache/cursor-api/` and stores complete background-task prompts and repository metadata under `~/.cache/cursor-api/background-tasks/`. Neither path is created with an explicit restrictive mode. The files are also written without applying mode `0600` or first establishing `umask 077`. Their effective permissions therefore depend on the environment in which the Skill runs. Under a permissive umask, other local users may be able to read the files. Cached API responses may include: - Full agent conversations. - User prompts and generated responses. - Agent and pull-request metadata. - Cursor account identi ...[truncated 1877 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Establish a restrictive umask before creating any cache or background-task artifacts: ```bash umask 077 ``` 2. Explicitly create directories with owner-only permissions: ```bash mkdir -p -m 700 "$CACHE_DIR" mkdir -p -m 700 "$BG_TASKS_DIR" ``` 3. Create files atomically with owner-only permissions. Use `mktemp` inside the protected directory, write the content, apply `chmod 600`, and atomically rename the file. 4. Apply `chmod 600` to existing cache, task, and log files after validating that they are regular files owned by the current user. 5. Do not cache sensitive endpoints such as `/me` and `/agents/<id>/conversation` by default. Require explicit opt-in if conversation caching is needed. 6. Minimize persisted background-task data. Store a prompt hash or redacted summary instead of the complete prompt unless retaining the full prompt is essential. 7. Implement an automatic expiration and cleanup policy for completed tasks, logs, and cached conversations. 8. Verify that the cache directory and files are owned by the current user and reject symlinks or unexpected file types before reading or writing. 9. Add tests that run the script under a permissive umask and verify directory mode `0700` and file mode `0600`. ]]>
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (57)

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

High
Category
YARA Match
Content
```bash
git clone https://github.com/Parcosta/cursor-cloud-agents.git ~/.openclaw/skills/cursor-cloud-agents
```

### Standalone Usage

After installation, use the skill directly:

```bash
cursor-cloud-agents --help
```

### Short Commands (Optional)

For faster daily usage, enable short-form `cca` aliases by sourcing the aliases file:

```bash
# One-time setup: Add to your ~/.bashrc or ~/.zshrc
echo 'source ~/.openclaw/workspace/projects/cursor-cloud-agents/scripts/cca-aliases.sh' >> ~/.bashrc

# Or source manually for current session
source ~/.openclaw/workspace/projects/cursor-cloud-agents/scripts/cca-aliases.sh
```

Then use short commands:

```bash
cca list              # List all agents
cca ls                # Short for 'list'
cca launch --repo owner/repo --prompt "Add tests"
cca status <agent-id>
cca conv <agent-id>   # Short for 'conversation'
cca fu <agent-id> --prompt "..." # Short for 'followup'
cca rm <agent-id>     # Short for 'delete'
```

All standard commands work with
Confidence
75% confidence
Finding
YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Credential Access

High
Category
Privilege Escalation
Content
1. Store `CURSOR_API_KEY` in `~/.openclaw/.env` with restricted permissions:
   ```bash
   chmod 600 ~/.openclaw/.env
   ```

2. Never commit API keys to version control
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
1. Store `CURSOR_API_KEY` in `~/.openclaw/.env` with restricted permissions:
   ```bash
   chmod 600 ~/.openclaw/.env
   ```

2. Never commit API keys to version control
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
1. Store `CURSOR_API_KEY` in `~/.openclaw/.env` with restricted permissions:
   ```bash
   chmod 600 ~/.openclaw/.env
   ```

2. Never commit API keys to version control
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The declared description presents this skill as a deployment automation tool for Cursor AI agents operating on GitHub repositories to write code and open PRs. However, the supplied code chunk is only a shell convenience script that, when sourced, defines a `cca` wrapper around another script (`cursor-api.sh`). Its primary behavior is local CLI aliasing and command forwarding, plus help/version output and a path sanity check. While some forwarded commands like `launch` may be related to agent deployment, this chunk itself does not implement the described repo automation behavior. It also exposes additional account and background-task management capabilities not mentioned in the description. Therefore the description does not accurately represent what this specific code chunk actually does.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding
The code is related to the declared domain of managing Cursor agents for GitHub repos, and it does support launching agents that could write code and create PRs. However, the description is narrower than the implementation. The script is not specifically a 'deploy agents to GitHub repos' tool only; it is a broader Cursor API management wrapper with lifecycle management, conversation retrieval, follow-up messaging, model listing, account inspection, usage reporting, repo verification, deletion, caching, and local background monitoring/logging. These are materially undeclared capabilities, especially account/usage access and local credential/config discovery. No unrelated trigger behavior is present, but the declared description does not accurately capture the broader management and data-access behavior of the code.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The declared description describes an automation skill for deploying Cursor AI agents to GitHub repositories and performing repository actions like code writing, test generation, documentation generation, and PR creation. The actual code chunk is instead a local test harness for validating another shell script. Its primary purpose is QA/test execution, not GitHub repo automation or agent deployment. This is a material purpose mismatch. While the code references a Cursor API key for integration tests, it still does not implement the declared repo/PR functionality in this chunk.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
There is a clear mismatch between the declared purpose and the observed code. The description promises automation around deploying Cursor AI agents to GitHub repos and performing development tasks like code writing, test generation, documentation generation, and opening PRs. The supplied code does none of that. Instead, it acts as a validation utility for a skill/repository structure, likely to ensure publishability to a hub ('clawdhub'). It performs only local filesystem inspection and lint-like checks, with no GitHub access, no Cursor subscription usage, no agent deployment, and no code/test/doc/PR generation. This is a materially different primary purpose, so it should be flagged as a mismatch.

Credential Access

High
Category
Privilege Escalation
Content
- base64
  files:
    read:
      - ~/.openclaw/.env
      - ~/.openclaw/.env.local
      - .env
      - ~/.cursor/config.json
Confidence
95% confidence
Finding
The skill is designed to read credentials from local env/config files, including project-level .env files that often contain many unrelated secrets beyond the Cursor API key. Granting broad read access to such files increases the blast radius of compromise and can expose secrets unnecessarily to the skill runtime or any dependent tooling.

Credential Access

High
Category
Privilege Escalation
Content
files:
    read:
      - ~/.openclaw/.env
      - ~/.openclaw/.env.local
      - .env
      - ~/.cursor/config.json
    write:
Confidence
95% confidence
Finding
Reading ~/.openclaw/.env.local similarly grants access to potentially sensitive local secrets unrelated to this skill. Because the file may contain per-user overrides and tokens, this behavior materially expands credential exposure beyond what is required for operation.

Credential Access

High
Category
Privilege Escalation
Content
read:
      - ~/.openclaw/.env
      - ~/.openclaw/.env.local
      - .env
      - ~/.cursor/config.json
    write:
      - ~/.cache/cursor-api/
Confidence
96% confidence
Finding
Reading ~/.cursor/config.json can expose broader application configuration and tokens, and combined with project/global .env access creates multiple credential-harvesting surfaces. Even if intended for convenience, this is dangerous because it normalizes access to sensitive local files without strict minimization.

Ae1

High
Category
analysis-evasion
Content
Then use `cca` instead of `cursor-api.sh`:
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

External Model or Provider Selection

High
Category
Excessive Agency
Content
cursor-api.sh launch --repo owner/repo --prompt "Add comprehensive tests for auth module"

# Launch with specific model
cursor-api.sh launch --repo owner/repo --prompt "Add tests" --model claude-4-opus

# Response: {"id": "agent_123", "status": "CREATING", ...}
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.

Tool Parameter Abuse

High
Category
Tool Misuse
Content
Permanently deletes an agent and its conversation history.

```http
DELETE /agents/:id
```

**Response:**
Confidence
80% confidence
Finding
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Credential Access

High
Category
Privilege Escalation
Content
echo "$str"
}

# Get API key from various sources
get_api_key() {
    local key
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 0
    fi

    # Check ~/.openclaw/.env
    if [[ -f "$HOME/.openclaw/.env" ]]; then
        key=$(grep -E '^CURSOR_API_KEY=' "$HOME/.openclaw/.env" | cut -d= -f2-)
        key=$(strip_quotes "$key")
Confidence
95% confidence
Finding
Reading credentials from ~/.openclaw/.env is credential access behavior beyond explicit user input and can silently consume secrets stored for other workflows. In a skill context, that increases the chance of unauthorized secret use and accidental exposure through subsequent API requests.

Credential Access

High
Category
Privilege Escalation
Content
fi

    # Check ~/.openclaw/.env
    if [[ -f "$HOME/.openclaw/.env" ]]; then
        key=$(grep -E '^CURSOR_API_KEY=' "$HOME/.openclaw/.env" | cut -d= -f2-)
        key=$(strip_quotes "$key")
        if [[ -n "$key" ]]; then
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
fi

    # Check ~/.openclaw/.env
    if [[ -f "$HOME/.openclaw/.env" ]]; then
        key=$(grep -E '^CURSOR_API_KEY=' "$HOME/.openclaw/.env" | cut -d= -f2-)
        key=$(strip_quotes "$key")
        if [[ -n "$key" ]]; then
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
fi

    # Check ~/.openclaw/.env
    if [[ -f "$HOME/.openclaw/.env" ]]; then
        key=$(grep -E '^CURSOR_API_KEY=' "$HOME/.openclaw/.env" | cut -d= -f2-)
        key=$(strip_quotes "$key")
        if [[ -n "$key" ]]; then
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
fi

    # Check ~/.openclaw/.env
    if [[ -f "$HOME/.openclaw/.env" ]]; then
        key=$(grep -E '^CURSOR_API_KEY=' "$HOME/.openclaw/.env" | cut -d= -f2-)
        key=$(strip_quotes "$key")
        if [[ -n "$key" ]]; then
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
fi

    # Check ~/.openclaw/.env
    if [[ -f "$HOME/.openclaw/.env" ]]; then
        key=$(grep -E '^CURSOR_API_KEY=' "$HOME/.openclaw/.env" | cut -d= -f2-)
        key=$(strip_quotes "$key")
        if [[ -n "$key" ]]; then
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
fi

    # Check ~/.openclaw/.env
    if [[ -f "$HOME/.openclaw/.env" ]]; then
        key=$(grep -E '^CURSOR_API_KEY=' "$HOME/.openclaw/.env" | cut -d= -f2-)
        key=$(strip_quotes "$key")
        if [[ -n "$key" ]]; then
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
fi
    fi

    # Check ~/.openclaw/.env.local
    if [[ -f "$HOME/.openclaw/.env.local" ]]; then
        key=$(grep -E '^CURSOR_API_KEY=' "$HOME/.openclaw/.env.local" | cut -d= -f2-)
        key=$(strip_quotes "$key")
Confidence
95% confidence
Finding
The script also reads credentials from ~/.openclaw/.env.local, broadening the set of local secret stores it will consume without explicit user confirmation. This materially increases credential exposure risk because local override files often contain sensitive development secrets not intended for this skill.

Credential Access

High
Category
Privilege Escalation
Content
fi

    # Check ~/.openclaw/.env.local
    if [[ -f "$HOME/.openclaw/.env.local" ]]; then
        key=$(grep -E '^CURSOR_API_KEY=' "$HOME/.openclaw/.env.local" | cut -d= -f2-)
        key=$(strip_quotes "$key")
        if [[ -n "$key" ]]; then
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
fi

    # Check ~/.openclaw/.env.local
    if [[ -f "$HOME/.openclaw/.env.local" ]]; then
        key=$(grep -E '^CURSOR_API_KEY=' "$HOME/.openclaw/.env.local" | cut -d= -f2-)
        key=$(strip_quotes "$key")
        if [[ -n "$key" ]]; then
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Static analysis

No suspicious patterns detected.