Back to skill

Security audit

R2 Storage

Security checks for vulnerabilities and agentic risk

Overview

This R2 storage skill is mostly purpose-aligned, but it uses unsafe privileged installation and exposes persistent cloud credentials in ways users should review carefully.

Review before installing. Prefer installing rclone through a trusted package manager or verified release instead of running the provided curl | sudo bash command. Use least-privilege, bucket-scoped R2 tokens, check permissions on ~/.config/r2/config.json and ~/.config/rclone/rclone.conf, avoid using show-creds unless necessary, and preview targets carefully before delete, purge, or sync --delete operations.

Vulnerability Patterns
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (4)

T03 · Remote Payload Retrieval and Execution

Error
Location
scripts/setup.sh:27
Finding
Unverified Remote Installation Script Executed with Root Privileges<![CDATA[ ## Vulnerability Details **File Location**: `scripts/setup.sh:27-31`; also documented in `SKILL.md:4` and `SKILL.md:10-14` **Vulnerability Type**: Remote payload retrieval and privileged execution **Risk Level**: Critical ### Vulnerable Code ```bash # Check rclone if ! command -v rclone &> /dev/null; then echo "Installing rclone..." curl -fsSL https://rclone.org/install.sh | sudo bash fi ``` The same installation command is declared in the Skill metadata and documentation: ```yaml metadata: {"clawdbot":{"emoji":"☁️","requires":{"bins":["rclone"]},"env":["R2_CONFIG"],"install":[{"id":"rclone","kind":"shell","command":"curl -fsSL https://rclone.org/install.sh | sudo bash","label":"Install rclone"}]}} ``` ```bash curl -fsSL https://rclone.org/install.sh | sudo bash ``` ### Technical Analysis The setup process downloads a mutable shell script from an external URL and immediately executes it through `sudo bash`. The downloaded payload is not pinned to a specific release and is not verified using a cryptographic checksum or signature. HTTPS authenticates the connection under normal conditions, but it does not make the mutable upstream script safe against compromise of the hosting infrastructure, upstream project, DNS/TLS trust chain, or release process. Because the response is piped directly into a privileged interpreter, there is no opportunity to inspect the effective payload before execution. The executable behavior can also change after the Skill has been reviewed. ### Attack Path 1. An attacker compromises the upstream installation script, its delivery infrastructure, or another relevant part of the delivery chain. 2. A user or agent runs `scripts/setup.sh` on a system where `rclone` is not installed, or follows the documented installation command. 3. `curl` retrieves the attacker-controlled shell content. 4. The content is passed directly to `sudo bash`. 5. The payload executes with root privileges and can modify any part of the host. ...[truncated 357 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Remove all pipe-to-shell installation commands from the setup script, metadata, and documentation. - Pin installation to a specific, reviewed `rclone` release. - Download the release artifact to a local file before executing or installing anything. - Verify the artifact against a trusted, hardcoded SHA-256 digest and, where supported, an upstream cryptographic signature. - Prefer a trusted operating-system package manager with repository signature verification. - Avoid root installation when a user-scoped installation satisfies the Skill's requirements. - Fail closed if integrity or signature verification does not succeed. - Display the selected version, source URL, and verification result before installation. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/setup.sh:56
Finding
R2 Credentials Stored Without Explicitly Restrictive File Permissions<![CDATA[ ## Vulnerability Details **File Location**: `scripts/setup.sh:56-72` **Vulnerability Type**: Insecure plaintext credential storage **Risk Level**: High ### Vulnerable Code ```bash # Save config JSON mkdir -p ~/.config/r2 echo "$CONFIG_JSON" > "$CONFIG_FILE" echo "✅ Config saved to $CONFIG_FILE" # Write rclone config mkdir -p ~/.config/rclone cat > ~/.config/rclone/rclone.conf << EOF [${REMOTE_NAME}] type = s3 provider = Cloudflare access_key_id = ${ACCESS_KEY} secret_access_key = ${SECRET_KEY} endpoint = ${ENDPOINT} acl = private no_check_bucket = true EOF ``` ### Technical Analysis The script stores the R2 access key and secret key in plaintext in both `~/.config/r2/config.json` and `~/.config/rclone/rclone.conf`. It does not establish a restrictive `umask`, explicitly create the directories with mode `700`, or set the resulting files to mode `600`. The effective permissions therefore depend on the caller's environment and the permissions of any pre-existing files. Under a permissive umask, sensitive files may be readable by other local users. Redirecting over an existing file also preserves that file's existing permissions, which may already be unsafe. ### Attack Path 1. A user runs `scripts/setup.sh` with a permissive umask, or with pre-existing configuration files that have broad permissions. 2. The script writes plaintext R2 credentials without correcting the resulting file permissions. 3. Another local account or process reads either configuration file. 4. The attacker extracts the access key, secret key, and endpoint. 5. The attacker uses those credentials to perform operations permitted by the associated Cloudflare R2 token. ### Impact Assessment The exposed credentials may permit unauthorized object reading, listing, uploading, modification, or deletion, depending on the Cloudflare token's assigned permissions. The impact covers every bucket and object authorized for that token and can include confidentiality loss, data tampering, an ...[truncated 94 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Set `umask 077` before creating or rewriting any credential-bearing files. - Create `~/.config/r2` and `~/.config/rclone` with mode `700`. - Create credential files atomically with mode `600`, and verify their owner and permissions after writing. - Correct unsafe permissions on pre-existing files rather than relying on their current modes. - Avoid unnecessary duplication of credentials across multiple files. - Prefer an operating-system credential store or secret-management service where available. - Use least-privilege R2 tokens limited to the necessary buckets and operations. - Rotate credentials if they may previously have been stored with broad read permissions. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/show-creds.sh:7
Finding
Credential Display Helper Executes the Environment File as Shell Code<![CDATA[ ## Vulnerability Details **File Location**: `scripts/show-creds.sh:7-16` **Vulnerability Type**: Arbitrary shell execution through unsafe configuration loading **Risk Level**: High ### Vulnerable Code ```bash ENV_FILE="$HOME/.config/r2/env" CONFIG_FILE="$HOME/.config/rclone/rclone.conf" # Try env file first, fallback to rclone config if [[ -f "$ENV_FILE" ]]; then source "$ENV_FILE" ACCESS_KEY="${R2_ACCESS_KEY_ID}" SECRET_KEY="${R2_SECRET_ACCESS_KEY}" ENDPOINT="${R2_ENDPOINT}" BUCKET="${R2_BUCKET}" ``` ### Technical Analysis The `source` built-in does not load the file as passive key-value data. It parses and executes the complete file as Bash code in the current shell. Command substitutions, function calls, redirections, and arbitrary commands contained in `~/.config/r2/env` are executed with the privileges and environment of the user running `show-creds.sh`. The setup script does not create this environment file, and the helper performs no ownership, permission, syntax, or provenance checks before executing it. Consequently, any party or compromised process capable of creating or modifying this path can turn a credential-display operation into code execution. ### Attack Path 1. An attacker or compromised local process obtains write access to `~/.config/r2/env` or its parent directory. 2. The attacker inserts shell commands into the file, for example through command substitution or a standalone command. 3. The user or agent invokes `scripts/show-creds.sh`. 4. Bash executes `source "$ENV_FILE"`. 5. The attacker's commands run with the invoking user's privileges. ### Impact Assessment Exploitation provides arbitrary command execution as the user who invokes the helper. The attacker can read or modify files available to that user, steal R2 and other user-accessible credentials, execute network requests, or tamper with the user's environment. It does not inherently provide root privileges unless the invoking context already ha ...[truncated 49 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Do not use `source`, `.`, or `eval` to read credential files. - Prefer parsing the existing JSON configuration with a JSON parser. - If an environment-style format must be supported, parse it as inert data using an allowlist of exact keys. - Reject malformed lines, duplicate keys, unexpected variable names, command substitutions, and shell metacharacters. - Require the file to be owned by the invoking user, not be a symbolic link, and have mode `600`. - Require the containing directory to be owned by the user and not writable by untrusted accounts. - Open and validate the file safely to reduce race conditions between validation and reading. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/show-creds.sh:28
Finding
Complete R2 Secret Key Disclosed Through Standard Output<![CDATA[ ## Vulnerability Details **File Location**: `scripts/show-creds.sh:28-45` **Vulnerability Type**: Sensitive credential exposure **Risk Level**: Medium ### Vulnerable Code ```bash if [[ "$1" == "--raw" ]]; then echo "R2_ACCESS_KEY_ID=$ACCESS_KEY" echo "R2_SECRET_ACCESS_KEY=$SECRET_KEY" echo "R2_ENDPOINT=$ENDPOINT" [[ -n "$BUCKET" ]] && echo "R2_BUCKET=$BUCKET" else echo "☁️ R2 Credentials" echo "=================" echo "" echo "Access Key ID:" echo " $ACCESS_KEY" echo "" echo "Secret Key:" echo " $SECRET_KEY" echo "" echo "Endpoint:" echo " $ENDPOINT" [[ -n "$BUCKET" ]] && echo "" && echo "Bucket:" && echo " $BUCKET" ``` ### Technical Analysis Both the normal display mode and the `--raw` mode print the complete R2 secret access key to standard output. Standard output may be recorded by terminal session logging, CI/CD systems, automation wrappers, agent conversation transcripts, monitoring tools, or redirected files. The normal mode exposes the key without requiring a dedicated disclosure option. The raw mode additionally emits it in a reusable environment-variable format, increasing the likelihood that the credential will be copied into logs or other persistent records. ### Attack Path 1. A user, automation system, or agent invokes `scripts/show-creds.sh`. 2. The helper writes the complete secret key to standard output. 3. A terminal logger, CI system, transcript recorder, wrapper, redirected file, or observer captures the output. 4. An unauthorized party obtains the captured credential. 5. The party authenticates to Cloudflare R2 and exercises the permissions assigned to the token. ### Impact Assessment Disclosure may permit unauthorized access to all R2 resources authorized for the credential. Depending on token permissions, this can include listing and downloading objects, uploading or replacing content, and deleting data. The precise scope is bounded by the Cloudflare token ...[truncated 43 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Mask the secret by default and display only a short, non-sensitive suffix for identification. - Remove complete secret output from the normal display path. - Avoid offering raw secret output unless it is operationally indispensable. - If full disclosure must remain available, require an explicit option, an interactive warning and confirmation, and a terminal check. - Do not print secrets when standard output is redirected or the process is running in a non-interactive logging environment. - Prefer reporting the credential source and configuration status rather than the credential value. - Document that exposed credentials must be rotated and provide a clear rotation procedure. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Rogue AgentSelf-Modification, Session Persistence
Findings (23)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The skill is described as R2 storage management, but it also documents credential-display functionality that reads and outputs access keys in plain text. That behavior materially expands the sensitivity of the skill from file transfer to secret disclosure, making it easier for an agent or user to expose reusable cloud credentials.

External Script Fetching

High
Category
Supply Chain
Content
---
name: r2
description: Cloudflare R2 Storage management — setup, upload, download, sync via rclone
metadata: {"clawdbot":{"emoji":"☁️","requires":{"bins":["rclone"]},"env":["R2_CONFIG"],"install":[{"id":"rclone","kind":"shell","command":"curl -fsSL https://rclone.org/install.sh | sudo bash","label":"Install rclone"}]}}
---

# r2 ☁️
Confidence
99% confidence
Finding
The skill metadata instructs the system to fetch a remote install script and pipe it directly into sudo bash. This combines unverified network content with privileged execution, creating a straightforward path to arbitrary code execution and full host compromise if the script source or delivery is tampered with.

Chaining Abuse

High
Category
Tool Misuse
Content
---
name: r2
description: Cloudflare R2 Storage management — setup, upload, download, sync via rclone
metadata: {"clawdbot":{"emoji":"☁️","requires":{"bins":["rclone"]},"env":["R2_CONFIG"],"install":[{"id":"rclone","kind":"shell","command":"curl -fsSL https://rclone.org/install.sh | sudo bash","label":"Install rclone"}]}}
---

# r2 ☁️
Confidence
98% confidence
Finding
The metadata uses command chaining by piping downloaded content directly into sudo bash, preventing inspection and amplifying the effect of any compromise. This is a classic dangerous pattern because it turns remote text into privileged shell execution in one step.

External Script Fetching

High
Category
Supply Chain
Content
## Install

```bash
curl -fsSL https://rclone.org/install.sh | sudo bash
```

## Credentials Required
Confidence
99% confidence
Finding
The documented install command executes a remote script immediately instead of requiring review or integrity verification. Because it also elevates privileges via sudo, exploitation would likely yield complete control of the local machine.

Chaining Abuse

High
Category
Tool Misuse
Content
## Install

```bash
curl -fsSL https://rclone.org/install.sh | sudo bash
```

## Credentials Required
Confidence
98% confidence
Finding
The install example chains a network fetch into privileged shell execution, which is an unsafe composition of tools rather than merely a convenience shortcut. The skill context makes this more dangerous because installation is likely to be copy-pasted or agent-executed automatically.

Tool Parameter Abuse

High
Category
Tool Misuse
Content
```bash
r2-rm file.txt                           # Delete single file
r2-rm folder/                            # Delete folder contents
r2-purge my-bucket                       # Delete all files in bucket
```
Confidence
85% confidence
Finding
The skill documents direct deletion primitives for objects and bucket contents with no visible safeguards or parameter validation guidance. In an agent setting, malformed paths, misunderstood prefixes, or overbroad targets could lead to unintended destruction of remote data.

Missing User Warnings

High
Confidence
99% confidence
Finding
The script fetches a remote installer over the network and immediately executes it with sudo via a shell pipeline. This is dangerous because any compromise of the download source, TLS interception, DNS hijack, or unexpected upstream change can result in arbitrary root-level code execution on the user's machine.

External Script Fetching

High
Category
Supply Chain
Content
# Check rclone
if ! command -v rclone &> /dev/null; then
    echo "Installing rclone..."
    curl -fsSL https://rclone.org/install.sh | sudo bash
fi

# Get config from arg or interactive
Confidence
99% confidence
Finding
Fetching and executing an external script in one step is a classic supply-chain risk pattern. In a storage-management skill that handles cloud credentials, compromise of the installer can additionally expose or steal those credentials after installation, making the context more dangerous than a generic setup helper.

Chaining Abuse

High
Category
Tool Misuse
Content
# Check rclone
if ! command -v rclone &> /dev/null; then
    echo "Installing rclone..."
    curl -fsSL https://rclone.org/install.sh | sudo bash
fi

# Get config from arg or interactive
Confidence
96% confidence
Finding
The pipeline chaining of curl output directly into sudo bash removes any review boundary and combines two dangerous actions: untrusted network retrieval and privileged execution. This chaining makes exploitation easier and faster because a single upstream compromise immediately becomes local root code execution.

Lp3

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding
The skill exposes shell-based capabilities through install and operational commands but does not declare an explicit tool scope such as permissions or allowed-tools. This increases the chance that an agent can invoke powerful shell actions without clear policy boundaries or user expectations, which is especially risky in a storage-management skill that can modify local files and cloud data.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
---
name: r2
description: Cloudflare R2 Storage management — setup, upload, download, sync via rclone
metadata: {"clawdbot":{"emoji":"☁️","requires":{"bins":["rclone"]},"env":["R2_CONFIG"],"install":[{"id":"rclone","kind":"shell","command":"curl -fsSL https://rclone.org/install.sh | sudo bash","label":"Install rclone"}]}}
---

# r2 ☁️
Confidence
97% confidence
Finding
The metadata includes an install command that runs with sudo, granting root privileges to fetched installer content. In an agent-managed environment, privileged execution substantially raises the blast radius of any mistake or compromise during installation.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
## Install

```bash
curl -fsSL https://rclone.org/install.sh | sudo bash
```

## Credentials Required
Confidence
97% confidence
Finding
The installation instructions tell users to pipe an external script into sudo bash, resulting in immediate root-level code execution. This is dangerous because any compromise of the remote script, network path, or domain would lead to full system compromise.

Session Persistence

Medium
Category
Rogue Agent
Content
**Get credentials from Cloudflare:**
1. Go to https://dash.cloudflare.com → R2
2. Create API token with Object Read/Write/List permissions
3. Copy Account ID (from R2 dashboard URL)
4. Endpoint format: `https://<account_id>.r2.cloudflarestorage.com`
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.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The sync example using --delete can remove destination files, but the documentation does not clearly warn about that destructive behavior. In cloud storage workflows, direction mistakes are common, so an undocumented mirror-delete option can quickly erase valid data.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The documented delete and purge commands are irreversible but are presented without warnings, confirmation steps, or safeguards. In an agent context, terse examples can be executed with little scrutiny, causing accidental large-scale data loss in the target bucket.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
The skill advertises a credential-display script, including a raw output mode, without warning that it may expose active access keys and secrets. Because these are cloud credentials, disclosure can enable unauthorized bucket access, exfiltration, modification, or deletion.

Description-Behavior Mismatch

Medium
Confidence
93% confidence
Finding
The manifest describes the skill as handling setup, upload, download, and sync via rclone, but this script implements deletion and full bucket purging. Destructive removal is a materially different operation from the listed behaviors and is not implied by the manifest wording.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The single-path deletion branch performs `rclone delete` immediately with no confirmation, dry-run, or validation of the supplied target. In an agentic or automated context, a mistaken path, prompt injection, or unsafe upstream input could cause irreversible deletion of remote data with no user checkpoint.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
# Check rclone
if ! command -v rclone &> /dev/null; then
    echo "Installing rclone..."
    curl -fsSL https://rclone.org/install.sh | sudo bash
fi

# Get config from arg or interactive
Confidence
94% confidence
Finding
This line invokes sudo to run an externally fetched script as root. While sudo itself is not always a vulnerability, in this context it materially increases severity because any malicious or tampered installer gains full system privileges instead of user-level access.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
The script writes the provided R2 JSON and the generated rclone configuration, including access_key_id and secret_access_key, to disk in plaintext under the user's home directory without setting restrictive permissions or warning the user. This creates a persistent credential exposure risk if the files are read by other local users, captured by backups, or later exfiltrated by malware.

Session Persistence

Medium
Category
Rogue Agent
Content
fi

# Save config JSON
mkdir -p ~/.config/r2
echo "$CONFIG_JSON" > "$CONFIG_FILE"
echo "✅ Config saved to $CONFIG_FILE"
Confidence
90% confidence
Finding
The script persists sensitive cloud configuration into ~/.config/r2/config.json, creating long-lived local storage of secrets beyond the current session. Session persistence of credentials increases exposure time and makes compromise more likely through local disclosure, backups, or later host compromise.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
This script intentionally prints Cloudflare R2 access credentials, including the secret access key, directly to stdout in both human-readable and raw formats. Secrets written to stdout are easily exposed through terminal history capture, shell logging, CI logs, remote session transcripts, or accidental copy/paste, making credential compromise plausible even if the script is meant for convenience.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The script passes a user-controlled --delete flag directly to `rclone sync`, which can remove files from the destination to mirror the source without any interactive confirmation, dry-run, or scope validation. In a storage-management skill, this is especially risky because source/destination mix-ups, malformed paths, or automation mistakes can cause irreversible bulk deletion of local data or remote R2 objects.

Static analysis

No suspicious patterns detected.