Back to skill

Security audit

EdgeOne Pages Dev

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent EdgeOne Pages development guide, but some copy-ready examples can lead agents to create insecure authentication and public persistent-data APIs without enough safeguards.

Review this skill carefully before installing. It appears to be documentation rather than malware, but agents using it may generate insecure application code unless you explicitly require verified authentication, object-level authorization, input validation, safe JSON serialization, privacy limits for IP/geolocation, and cautious handling of KV deletion and environment 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 (3)

T09 · Insecure Skill Coding Practices

Error
Location
references/middleware.md:110
Finding

Bearer Token Presence Check Allows Authentication Bypass

Content
View full analysis

Vulnerability Details

File Location: references/middleware.md, lines 110–122
Vulnerability Type: Broken authentication caused by missing token verification
Risk Level: High

Vulnerable Code

javascript
export const config = {
  matcher: ['/api/:path*', '/admin/:path*'],
};

export function middleware(context) {
  const token = context.request.headers.get('Authorization');
  if (!token || !token.startsWith('Bearer ')) {
    return new Response(JSON.stringify({ error: 'Unauthorized' }), {
      status: 401,
      headers: { 'Content-Type': 'application/json' },
    });
  }
  return context.next();
}

Technical Analysis

This copy-ready example is presented as an authentication guard, but it only verifies that the Authorization header starts with Bearer . It does not validate the token's signature, value, expiration, issuer, audience, algorithm, session state, or authorization claims.

Consequently, any attacker can satisfy the guard with an arbitrary header such as:

http
Authorization: Bearer attacker-controlled-value

The middleware then invokes context.next() and treats the request as authenticated. Because the matcher covers both /api/* and /admin/*, applications copying this pattern may unintentionally expose all routes under those prefixes.

Attack Path

  1. An application adopts the documented middleware as an authentication guard.
  2. A protected API or administrative endpoint is placed under /api/* or /admin/*.
  3. An unauthenticated attacker sends a request with an arbitrary nonempty bearer value.
  4. The prefix check succeeds even though the token has no valid signature or identity.
  5. The middleware forwards the request to the protected route.
  6. The attacker receives the same endpoint access that the application intended to grant only to authenticated users.

Impact Assessment

An attacker can bypass the documented authenticat ...[truncated 377 chars]

Remediation
View remediation

Remediation Suggestions

  • Parse the bearer credential strictly and reject missing, empty, malformed, or duplicated authorization headers.
  • Verify the token cryptographically using a trusted JWT or session library.
  • Restrict acceptable signing algorithms and validate the signature using a trusted key.
  • Enforce expiration, not-before time, issuer, audience, and token-purpose claims.
  • Check required roles or scopes separately for administrative and data-changing routes.
  • Support revocation or server-side session validation where immediate invalidation is required.
  • Return 401 Unauthorized for invalid authentication and 403 Forbidden for valid identities lacking permission.
  • Do not present a header-presence or prefix check as a complete authentication implementation.
  • Add tests proving that arbitrary, expired, incorrectly signed, wrong-audience, and insufficient-scope tokens are rejected.

T09 · Insecure Skill Coding Practices

Error
Location
references/kv-storage.md:162
Finding

Unauthenticated KV CRUD and Enumeration Expose Persistent User Data

Content
View full analysis

Vulnerability Details

File Location: references/kv-storage.md, lines 162–218
Vulnerability Type: Missing authentication, authorization, and input validation on persistent storage operations
Risk Level: High

Vulnerable Code

javascript
// edge-functions/api/users/[id].js

export async function onRequestGet({ params }) {
  const user = await my_kv.get(`user:${params.id}`, 'json');
  if (!user) {
    return new Response(JSON.stringify({ error: 'Not found' }), {
      status: 404,
      headers: { 'Content-Type': 'application/json' },
    });
  }
  return new Response(JSON.stringify(user), {
    headers: { 'Content-Type': 'application/json' },
  });
}

export async function onRequestPost({ params, request }) {
  const data = await request.json();
  await my_kv.put(`user:${params.id}`, JSON.stringify(data));
  return new Response(JSON.stringify({ success: true }), {
    status: 201,
    headers: { 'Content-Type': 'application/json' },
  });
}

export async function onRequestDelete({ params }) {
  await my_kv.delete(`user:${params.id}`);
  return new Response(JSON.stringify({ success: true }), {
    headers: { 'Content-Type': 'application/json' },
  });
}
javascript
// edge-functions/api/users.js

export async function onRequestGet() {
  const users = [];
  let result;
  let cursor;

  do {
    result = await my_kv.list({ prefix: 'user:', limit: 256, cursor });
    const fetched = await Promise.all(
      result.keys.map(k => my_kv.get(k.name, 'json'))
    );
    users.push(...fetched.filter(Boolean));
    cursor = result.cursor;
  } while (!result.complete);

  return new Response(JSON.stringify({ users }), {
    headers: { 'Content-Type': 'application/json' },
  });
}

Technical Analysis

The examples directly expose persistent KV operations through public HTTP handlers. They contain no authentication, record-level auth ...[truncated 1820 chars]

Remediation
View remediation

Remediation Suggestions

  • Require cryptographically verified authentication before every persistent-data operation.
  • Enforce object-level authorization so callers can access only records they own or are explicitly permitted to manage.
  • Restrict enumeration endpoints to authorized administrative roles, or replace bulk enumeration with filtered, paginated responses.
  • Derive storage keys from the verified identity where possible instead of trusting a caller-selected identifier.
  • Validate identifiers against a strict allowlist and length limit before constructing KV keys.
  • Validate request bodies against an explicit schema, reject unknown fields, and enforce type and length limits.
  • Use separate handlers for creation and updates with appropriate HTTP methods and conflict checks.
  • Return only necessary fields and remove secrets or sensitive attributes from response objects.
  • Add rate limits, quotas, abuse monitoring, and audit logging for reads, writes, deletes, and enumeration.
  • Consider soft deletion, versioning, or backups where record recovery is required.
  • Document KV eventual-consistency behavior when implementing authorization-sensitive updates.

T09 · Insecure Skill Coding Practices

Warning
Location
references/python-functions.md:77
Finding

Unescaped Request Values Are Interpolated into JSON Responses

Content
View full analysis

Vulnerability Details

File Location: references/python-functions.md, lines 77–86 and 177–185
Vulnerability Type: Improper output encoding and JSON injection
Risk Level: Medium

Vulnerable Code

python
# cloud-functions/api/search.py
from http.server import BaseHTTPRequestHandler
from urllib.parse import urlparse, parse_qs

class handler(BaseHTTPRequestHandler):

    def do_GET(self):
        parsed = urlparse(self.path)
        query_params = parse_qs(parsed.query)
        name = query_params.get('name', ['Guest'])[0]

        self.send_response(200)
        self.send_header('Content-Type', 'application/json')
        self.end_headers()
        self.wfile.write(f'{{"hello": "{name}"}}'.encode('utf-8'))
python
# cloud-functions/api/users/[id].py
from http.server import BaseHTTPRequestHandler

class handler(BaseHTTPRequestHandler):

    def do_GET(self):
        user_id = self.path.strip('/')
        self.send_response(200)
        self.send_header('Content-Type', 'application/json')
        self.end_headers()
        self.wfile.write(f'{{"user_id": "{user_id}"}}'.encode('utf-8'))

Technical Analysis

Both examples construct JSON using Python f-strings and insert request-controlled values directly between quotation marks. JSON requires quotation marks, backslashes, and control characters inside strings to be escaped. The examples perform no such encoding.

A value containing characters such as ", \, a newline, or JSON delimiters can make the response invalid or alter its apparent structure. For example, an attacker-controlled value conceptually equivalent to:

text
attacker", "admin": true, "ignored": "

can introduce additional properties into the generated response text. Whether this becomes a further client-side vulnerability depends on how downstream consumers parse and use the response, but the server itself no longer guarantees valid, st ...[truncated 1299 chars]

Remediation
View remediation

Remediation Suggestions

  • Build a Python object and serialize it with the standard JSON encoder:

    python
    payload = json.dumps({"hello": name}).encode("utf-8")
    self.wfile.write(payload)
    
  • Apply the same pattern to route values:

    python
    payload = json.dumps({"user_id": user_id}).encode("utf-8")
    self.wfile.write(payload)
    
  • Parse route parameters explicitly instead of reflecting the entire stripped request path.

  • Validate input types, formats, and maximum lengths before including values in responses.

  • Reject control characters where they are not valid for the business use case.

  • Continue setting Content-Type: application/json, but do not treat the header as a substitute for correct serialization.

  • Add tests using quotation marks, backslashes, Unicode, newlines, and JSON delimiter characters to confirm responses remain valid JSON.

Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (6)

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · SKILL.md (reported line 156)May include surrounding context.

Manage environment variables:

bash
edgeone pages env pull       # Pull from console to local .env

Access env vars in functions via context.env.KEY (Node.js), os.Getenv("KEY") (Go), or os.environ.get("KEY") (Python).

Tool Parameter Abuse

High
Category
Tool Misuse
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).

Content

Scanner excerpt · references/recipes.md (reported line 15)May include surrounding context.

├── cloud-functions/ │ └── api/ │ ├── users.js # GET/POST /api/users │ └── users/[id].js # GET/PUT/DELETE /api/users/:id └── package.json

text

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

This markdown file includes example handlers that create, update, and delete stored user records via my_kv.put(...) and my_kv.delete(...), but the surrounding documentation does not warn that these operations modify persistent data or that deletion is irreversible. Under the markdown-file criteria, user-facing documentation should disclose behaviors that may affect user data or system integrity.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The example explicitly propagates context.clientIp and geolocation-derived data into upstream request headers, increasing exposure of personal and quasi-personal data across internal services without any warning, minimization guidance, or consent considerations. In a middleware skill, this pattern is especially risky because it encourages broad, automatic collection on every matched request and can normalize privacy-invasive defaults in downstream application code and logs.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The geo-routing example rewrites users from China to a Chinese-language path solely based on inferred location, with no user choice, persistence controls, or fallback behavior. This can lead to discriminatory or misleading experiences, incorrect locale assignment for VPN/travel users, and may create compliance and consent issues when location inference is used to alter content automatically.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

This markdown file includes sample code that reads DB_HOST, DB_USER, DB_PASSWORD, and DB_NAME from context.env, which is sensitive credential access. The surrounding documentation explains functionality but does not warn readers about secret handling, storage, or exposure risks for these credentials.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.exposed_secret_literal

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
references/node-functions.md:71