Back to skill

Security audit

Cloudflare API

Security checks for vulnerabilities and agentic risk

Overview

This appears to be a legitimate Cloudflare management skill, but it can change live DNS/tunnel resources and handles sensitive tokens in ways users should review carefully.

Install only if you intend to let the agent manage Cloudflare DNS and tunnels. Use a narrowly scoped Cloudflare API token limited to the needed account and zones, avoid running token-printing commands in CI or transcript-recorded sessions, verify resource names and IDs before mutations, and treat tunnel run tokens as secrets.

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

Warning
Location
scripts/_lib.sh:58
Finding
Unencoded User Input Permits Cloudflare API Query-Parameter Injection<![CDATA[ ## Vulnerability Details **File Location**: `scripts/_lib.sh:58-61`; additional affected call sites include `scripts/dns/delete.sh:54-59`, `scripts/dns/list.sh:52-57`, `scripts/dns/update.sh:59-64`, `scripts/tunnels/configure.sh:49-51`, `scripts/tunnels/delete.sh:46-48`, `scripts/tunnels/list.sh:40-43`, `scripts/tunnels/token.sh:44-47`, and `scripts/zones/get.sh:40` **Vulnerability Type**: API query-parameter injection and unsafe resource selection **Risk Level**: Medium ### Vulnerable Code ```bash # scripts/_lib.sh:58-61 get_zone_id() { local domain="$1" local response=$(cf_get "/zones?name=$domain") echo "$response" | jq -r '.result[0].id // empty' } ``` ```bash # scripts/dns/delete.sh:54-59 # Find the record FULL_NAME="$NAME.$DOMAIN" [ "$NAME" = "@" ] && FULL_NAME="$DOMAIN" RECORDS=$(cf_get "/zones/$ZONE_ID/dns_records?name=$FULL_NAME&type=$TYPE") RECORD_ID=$(echo "$RECORDS" | jq -r '.result[0].id // empty') ``` ```bash # scripts/dns/update.sh:59-64 # Find the record FULL_NAME="$NAME.$DOMAIN" [ "$NAME" = "@" ] && FULL_NAME="$DOMAIN" RECORDS=$(cf_get "/zones/$ZONE_ID/dns_records?name=$FULL_NAME&type=$TYPE") RECORD_ID=$(echo "$RECORDS" | jq -r '.result[0].id // empty') ``` ```bash # scripts/tunnels/delete.sh:46-48 # Get tunnel ID from name TUNNELS=$(cf_get "/accounts/$ACCOUNT_ID/cfd_tunnel?name=$TUNNEL_NAME") TUNNEL_ID=$(echo "$TUNNELS" | jq -r '.result[0].id // empty') ``` ### Technical Analysis User-controlled domains, DNS record names, record types, and tunnel names are interpolated directly into Cloudflare API URLs without URL encoding. Characters such as `&`, `=`, `?`, or encoded delimiters can alter the query string and introduce additional API parameters. The affected mutation operations select `.result[0]` without subsequently verifying that the returned resource exactly matches the requested domain, name, and type. If injected parameters broaden or otherwise change the result set, the first result may not be the intende ...[truncated 1470 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. URL-encode every user-controlled query value before constructing endpoints. For example: ```bash urlencode() { jq -rn --arg value "$1" '$value | @uri' } encoded_domain=$(urlencode "$domain") response=$(cf_get "/zones?name=$encoded_domain") ``` Alternatively, redesign the request helper to use `curl --get --data-urlencode` for query parameters. 2. Apply encoding consistently to: - Zone names. - DNS record names and types. - Tunnel names. - Any future filter, pagination, or search parameters. 3. Validate inputs before making requests: - Require syntactically valid domain and hostname values. - Restrict DNS record types to an explicit allowlist. - Reject control characters and unexpected query delimiters. - Enforce documented tunnel-name constraints. 4. Never rely only on `.result[0]`. Require exactly one result and verify its fields: ```bash MATCH_COUNT=$(echo "$RECORDS" | jq '.result | length') [ "$MATCH_COUNT" -eq 1 ] || { echo "Expected exactly one matching record" >&2 exit 1 } RETURNED_NAME=$(echo "$RECORDS" | jq -r '.result[0].name') RETURNED_TYPE=$(echo "$RECORDS" | jq -r '.result[0].type') [ "$RETURNED_NAME" = "$FULL_NAME" ] && [ "$RETURNED_TYPE" = "$TYPE" ] || { echo "API result does not exactly match the requested record" >&2 exit 1 } ``` 5. Prefer immutable resource IDs for destructive operations when practical, and display all verified identifying fields before requesting confirmation. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/_lib.sh:18
Finding
Cloudflare API and Tunnel Tokens Are Exposed Through Process Arguments and Standard Output<![CDATA[ ## Vulnerability Details **File Location**: `scripts/_lib.sh:18-21`; related secret-output locations include `scripts/tunnels/create.sh:53-63`, `scripts/tunnels/token.sh:44-61`, and `SKILL.md:133-135` **Vulnerability Type**: Sensitive credential exposure **Risk Level**: Medium ### Vulnerable Code ```bash # scripts/_lib.sh:18-21 cf_get() { local endpoint="$1" local token=$(get_token) curl -s -H "Authorization: Bearer $token" "${CF_API}${endpoint}" } ``` The same header construction is used by the POST, PUT, and DELETE helpers: ```bash # scripts/_lib.sh:25-33 cf_post() { local endpoint="$1" local data="$2" local token=$(get_token) curl -s -X POST \ -H "Authorization: Bearer $token" \ -H "Content-Type: application/json" \ -d "$data" \ "${CF_API}${endpoint}" } ``` ```bash # scripts/tunnels/create.sh:53-63 if check_error "$RESPONSE"; then TUNNEL_ID=$(echo "$RESPONSE" | jq -r '.result.id') TUNNEL_TOKEN=$(echo "$RESPONSE" | jq -r '.result.token') echo "✅ Tunnel created!" echo "" echo "Tunnel ID: $TUNNEL_ID" echo "Tunnel Name: $TUNNEL_NAME" echo "" echo "Run token (save this!):" echo "$TUNNEL_TOKEN" ``` ```bash # scripts/tunnels/token.sh:44-61 # Get tunnel ID from name TUNNELS=$(cf_get "/accounts/$ACCOUNT_ID/cfd_tunnel?name=$TUNNEL_NAME") TUNNEL_ID=$(echo "$TUNNELS" | jq -r '.result[0].id // empty') TUNNEL_TOKEN=$(echo "$TUNNELS" | jq -r '.result[0].token // empty') if [ -z "$TUNNEL_ID" ]; then echo "❌ Tunnel '$TUNNEL_NAME' not found" >&2 exit 1 fi if [ -n "$TUNNEL_TOKEN" ]; then echo "$TUNNEL_TOKEN" else # Token might be in credentials_file CREDS=$(echo "$TUNNELS" | jq -r '.result[0].credentials_file // empty') if [ -n "$CREDS" ] && [ "$CREDS" != "null" ]; then # Build token from credentials echo "$TUNNELS" | jq -r '.result[0].token // .result[0].id' ``` ```bash # SKILL.md:133-135 TOKEN=$(./scripts/tunnels/token.sh ...[truncated 2536 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Avoid placing authorization headers directly in process arguments where the execution environment and curl version support a safer mechanism. Use a permission-restricted temporary configuration file or protected file descriptor, and securely remove any temporary material. 2. If a curl configuration file is used: - Create it with `umask 077`. - Ensure it is owned by the current user and has mode `0600`. - Store it outside shared directories. - Remove it immediately after the request. - Install signal traps to clean it up on interruption. 3. Do not print tunnel tokens by default. Require an explicit option such as `--show-token`, clearly label the output as sensitive, and emit non-secret identifiers during normal execution. 4. Provide an option to write tunnel credentials directly to a user-selected file created with mode `0600`, rather than passing them through standard output. 5. Update the documented `cloudflared` workflow to use the safest token-file or protected credential-input mechanism supported by the installed `cloudflared` version. If command-line token input is unavoidable, warn users about process-list and logging exposure. 6. Disable shell tracing around secret operations and document that token-producing commands must not run in verbose CI jobs or transcript-recorded Agent sessions. 7. Redact authorization headers and tunnel tokens in application logs, observability tooling, error reports, and diagnostic bundles. 8. Use narrowly scoped Cloudflare API tokens, limit them to required accounts and zones, rotate them regularly, and revoke both API and tunnel tokens after suspected exposure. ]]>
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
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (15)

Lp3

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding
The skill clearly instructs use of shell scripts that can modify DNS, create tunnels, and delete resources, but it does not declare any explicit tool scope or permissions boundary. That increases the chance an agent can invoke powerful shell capabilities without transparent guardrails, making accidental or unauthorized infrastructure changes more likely.

Session Persistence

Medium
Category
Rogue Agent
Content
---
name: cloudflare
description: Connect to Cloudflare API for DNS management, tunnels, and zone administration. Use when user needs to manage domains, DNS records, or create tunnels.
read_when:
  - User asks about Cloudflare DNS or domains
  - User wants to create or manage DNS records
Confidence
60% confidence
Finding
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
```bash
# Option A: Store in file (recommended)
echo "YOUR_API_TOKEN" > ~/.cloudflare_token
chmod 600 ~/.cloudflare_token

# Option B: Environment variable
export CLOUDFLARE_API_TOKEN="YOUR_API_TOKEN"
Confidence
80% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The documentation includes destructive operations such as deleting DNS records and tunnels, but it does not warn that these actions can break production traffic, disable services, or be difficult to recover quickly. In an agent context, omission of impact warnings increases the risk of unsafe execution from a casual user request.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
"_comment": "Store your Cloudflare API token",
  
  "_option_1": "Save to file (recommended):",
  "_command": "echo 'YOUR_TOKEN' > ~/.cloudflare_token && chmod 600 ~/.cloudflare_token",
  
  "_option_2": "Or set environment variable:",
  "_env": "export CLOUDFLARE_API_TOKEN='YOUR_TOKEN'",
Confidence
80% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
"_comment": "Store your Cloudflare API token",
  
  "_option_1": "Save to file (recommended):",
  "_command": "echo 'YOUR_TOKEN' > ~/.cloudflare_token && chmod 600 ~/.cloudflare_token",
  
  "_option_2": "Or set environment variable:",
  "_env": "export CLOUDFLARE_API_TOKEN='YOUR_TOKEN'",
Confidence
80% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

External Transmission

Medium
Category
Data Exfiltration
Content
#!/bin/bash
# Cloudflare API helper functions

CF_API="https://api.cloudflare.com/client/v4"

# Get API token
get_token() {
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
This shell library reads sensitive credentials from the CLOUDFLARE_API_TOKEN environment variable or a local token file, then uses that token in outbound curl requests to the Cloudflare API. While the file has brief technical comments, it lacks any user-facing warning, confirmation, or disclosure about accessing credentials and sending authenticated network requests.

External Transmission

Medium
Category
Data Exfiltration
Content
cf_get() {
    local endpoint="$1"
    local token=$(get_token)
    curl -s -H "Authorization: Bearer $token" "${CF_API}${endpoint}"
}

# API POST request
Confidence
70% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
This shell script modifies a live DNS record via an API call, which can affect service availability or traffic routing. Although it prints a status message, there is no confirmation prompt or stronger user-facing warning immediately before performing the update.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
echo "Usage: tunnels/delete.sh <tunnel-name> [options]"
            echo ""
            echo "Options:"
            echo "  --force, -f  Skip confirmation"
            exit 0
            ;;
        *)
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.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
echo "Usage: tunnels/delete.sh <tunnel-name> [options]"
            echo ""
            echo "Options:"
            echo "  --force, -f  Skip confirmation"
            exit 0
            ;;
        *)
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.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The script retrieves a Cloudflare tunnel run token and prints it directly to stdout, which can expose a sensitive credential through terminal history, shell logs, CI logs, or calling-agent transcripts. In this skill context, the token grants the ability to run or impersonate a tunnel, so exposing it is materially risky even if the script's operational purpose is legitimate.

Missing User Warnings

Low
Confidence
86% confidence
Finding
The setup section tells users to store a Cloudflare API token locally or export it in the environment, but it does not explicitly identify the token as a highly sensitive credential with account-changing power. That can lead to poor handling, accidental exposure in shell history, logs, screenshots, backups, or multi-user systems.

Missing User Warnings

Low
Confidence
81% confidence
Finding
The script calls `get_token` and `get_account_id` and then uses those values to create a remote Cloudflare tunnel via `cf_post`. While the script prints that it is creating a tunnel, it does not explicitly disclose that it will access stored API credentials and make an authenticated network request to the Cloudflare API.

Static analysis

No suspicious patterns detected.