Back to skill

Security audit

Durable Objects

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent Cloudflare Durable Objects reference, but some best-practice examples could lead an agent to generate insecure public APIs if copied directly.

Review generated Worker code carefully before deployment. Require authentication and object-level authorization for every Durable Object route, derive identity from verified sessions or tokens, restrict CORS to trusted origins, explicitly reject unsupported methods, and pin development dependencies when following the testing setup.

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

T08 · Insecure Dependencies

Warning
Location
references/testing.md:10
Finding

Unpinned Development Dependency Creates Supply-Chain Risk

Content
View full analysis
Remediation
View remediation
npm ci ``` ]]>

T09 · Insecure Skill Coding Practices

Error
Location
references/workers.md:136
Finding

Durable Object API Example Omits Authentication and Authorization

Content
View full analysis
(); const result = await stub.sendMessage(body.userId, body.message); return Response.json(result); } const messages = await stub.getMessages(); return Response.json(messages); ``` ### Technical Analysis The example selects a Durable Object using a caller-controlled room identifier and exposes both message creation and message retrieval without authenticating the requester. For message creation, it also trusts a caller-supplied `userId`, allowing identity impersonation. Input validation elsewhere in the document only validates shape and length; it does not establish identity or verify room membership. Predictable values passed to `getByName()` make object identifiers suitable for deterministic routing, but they must not be treated as authorization secrets. The final fallback also returns messages for any method other than `POST`, rather than explicitly allowing only an intended read method. ### Attack Path 1. An attacker discovers or guesses a room identifier. 2. The attacker sends a request containing that identifier. 3. For a read, the handler calls `getMessages()` without verifying room membership and returns the stored messages. 4. For a write, the attacker submits an arbitrary `userId` and message. 5. The handler forwards the forged identity and content to the Durable Object without authentication or authorization. ### Impact Assessment If copied into a deployed Worker, this pattern could allow unauthenticated users to read messages from predictable rooms, inject content, impersonate other users, and modify application state. The scope includes every Durable Object instance whos ...[truncated 207 chars]
Remediation
View remediation
(); const result = await stub.sendMessage(identity.userId, body.message); return Response.json(result); } if (request.method === "GET") { return Response.json(await stub.getMessages()); } return new Response("Method Not Allowed", { status: 405 }); ``` ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
references/workers.md:279
Finding

Wildcard CORS Policy Unnecessarily Exposes API Operations to All Origins

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
Findings (6)

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · references/rules.md (reported line 163)May include surrounding context.

md
async processItem(id: string) {
  const item = await this.ctx.storage.get<Item>(`item:${id}`);
  if (item?.status === "pending") {
    await fetch("https://api.example.com/process"); // Other requests can run here!
    await this.ctx.storage.put(`item:${id}`, { status: "completed" });
  }
}

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · references/testing.md (reported line 87)May include surrounding context.

md
describe("Worker HTTP", () => {
  it("should increment via POST", async () => {
    const res = await SELF.fetch("http://example.com?id=test", {
      method: "POST",
    });

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · references/testing.md (reported line 97)May include surrounding context.

md
});

  it("should get count via GET", async () => {
    await SELF.fetch("http://example.com?id=get-test", { method: "POST" });
    await SELF.fetch("http://example.com?id=get-test", { method: "POST" });
    
    const res = await SELF.fetch("http://example.com?id=get-test");

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · references/testing.md (reported line 98)May include surrounding context.

md
});

  it("should get count via GET", async () => {
    await SELF.fetch("http://example.com?id=get-test", { method: "POST" });
    await SELF.fetch("http://example.com?id=get-test", { method: "POST" });
    
    const res = await SELF.fetch("http://example.com?id=get-test");

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding

npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding

npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.