Back to skill

Security audit

cloudflare-drop

Security checks for vulnerabilities and agentic risk

Overview

This skill is a coherent Cloudflare static-site deployment helper, with expected network upload behavior and sensible user-consent and claim-URL handling.

Install only if you intend to publish the selected static directory to a Cloudflare workers.dev URL. Use it with a trusted, stable directory containing only public files, review Cloudflare terms before accepting, and keep the claim URL file private.

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

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/deploy.mjs:124
Finding
Time-of-check to time-of-use race can upload unintended local files<![CDATA[ ## Vulnerability Details **File Location**: `scripts/deploy.mjs`, lines 124–140 **Vulnerability Type**: Filesystem TOCTOU race and potential local-file disclosure **Risk Level**: Medium ### Vulnerable Code ```js function collectFiles(dirPath, basePath = "") { const files = []; const entries = readdirSync(dirPath); for (const entry of entries) { const fullPath = join(dirPath, entry); const relPath = join(basePath, entry); const stat = lstatSync(fullPath); if (stat.isSymbolicLink()) { throw new Error(`Symlinks are not allowed in the static directory: ${fullPath}`); } if (stat.isDirectory()) { files.push(...collectFiles(fullPath, relPath)); } else if (stat.isFile()) { const content = readFileSync(fullPath); ``` ### Technical Analysis The code validates each path using `lstatSync()` and subsequently accesses the same path using a separate `readFileSync()` operation or recursive directory traversal. These operations resolve the pathname independently. An attacker or concurrent process with write access to the selected static directory can replace a validated regular file or directory with a symbolic link after `lstatSync()` completes but before the subsequent access occurs. The symlink check therefore does not guarantee that the object eventually read is the same object that was validated. If the race succeeds, `readFileSync()` follows the substituted symlink and reads its target. The resulting bytes are Base64-encoded, embedded in the generated Worker, sent to Cloudflare, and potentially made publicly available through the deployed `workers.dev` site. ### Attack Path 1. The victim invokes the deployment script on a static directory that the attacker or another untrusted process can modify. 2. The attacker places an ordinary file in the directory so that `lstatSync()` reports a regular file. 3. Immediately after validation, the attacker replaces that file with a symbolic link targeting a sensi ...[truncated 1254 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Open each candidate file using no-follow semantics, such as `O_NOFOLLOW` where supported, rather than reopening it solely by pathname after validation. 2. Call `fstat` on the opened file descriptor and verify that it refers to a regular file before reading. 3. Read file contents directly from the validated descriptor so that pathname substitution cannot redirect the read. 4. For directory traversal, use descriptor-relative APIs where available and reject symlinks at every path component. 5. Compare device and inode information between validation and access if platform limitations require separate operations, and abort when they differ. 6. Require the deployment directory to be owned by or exclusively writable by the invoking user. Warn or refuse deployment when the tree is writable by untrusted users. 7. Consider copying validated inputs into a newly created private staging directory, then generate and upload the Worker only from that immutable snapshot. 8. Preserve the existing regular-file, symlink, file-count, root `index.html`, and generated-size checks after implementing descriptor-safe traversal. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (2)

Lp3

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding
The skill instructs the agent to perform a networked deployment to Cloudflare Workers but does not declare any explicit tool scope or allowed-tools boundary. That omission weakens policy enforcement and reviewability, because an agent/runtime may permit broader network access than intended or fail closed/open inconsistently when executing the deployment flow.

External Transmission

Medium
Category
Data Exfiltration
Content
} from "node:fs";
import { extname, join } from "node:path";

const API_BASE = "https://api.cloudflare.com/client/v4";
const MAX_FILES = 1_000;
const MAX_WORKER_SCRIPT_BYTES = 2 * 1024 * 1024;
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Static analysis

No suspicious patterns detected.