cloudflare-workers — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited cloudflare-workers (Agent Skill) and scored it 91/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 1 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 1 flagged
The text {match} is the classic direct prompt-injection phrasing. Placed in a skill body that the agent reads as trusted instructions, it tries to make the agent abandon its prior rules and follow whatever comes next — a full system-prompt override.
ignore/disregard/forget … previous instructions sentence.Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Consolidated skill for building on the Cloudflare platform. Biases toward retrieval from live Cloudflare docs over pre-trained knowledge - API signatures, limits, and pricing change frequently.
| Need | Product |
|---|---|
| Serverless functions at the edge | Workers |
| Full-stack web app with Git deploys | Pages |
| Stateful coordination / real-time | Durable Objects |
| Long-running multi-step jobs | Workflows |
| Scheduled tasks | Cron Triggers |
| Lightweight request transformation | Snippets |
| Need | Product |
|---|---|
| Key-value (config, sessions, cache) | KV |
| Relational SQL | D1 (SQLite) |
| Object/file storage (S3-compatible) | R2 |
| Message queue | Queues |
| Vector embeddings (RAG/search) | Vectorize |
| Strongly-consistent per-entity state | Durable Objects |
| Need | Product |
|---|---|
| Run LLM inference | Workers AI |
| Vector database for RAG | Vectorize |
| Stateful AI agents | Agents SDK |
| AI provider gateway | AI Gateway |
| Need | Product |
|---|---|
| Expose local service to internet | Tunnel |
| Web Application Firewall | WAF |
| CAPTCHA alternative | Turnstile |
| DDoS protection | DDoS Shield |
export default {
async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
const url = new URL(request.url)
if (url.pathname === '/health') {
return Response.json({ status: 'ok' })
}
return new Response('Hello, World!', { status: 200 })
},
} satisfies ExportedHandler<Env>
interface Env {
MY_KV: KVNamespace
MY_DB: D1Database
MY_BUCKET: R2Bucket
SECRET_KEY: string
}wrangler.toml Configurationname = "my-worker"
main = "src/index.ts"
compatibility_date = "2025-04-10"
compatibility_flags = ["nodejs_compat"]
[[kv_namespaces]]
binding = "MY_KV"
id = "xxxxxxxxxxxxxxxx"
[[d1_databases]]
binding = "MY_DB"
database_name = "my-database"
database_id = "xxxxxxxxxxxxxxxx"
[[r2_buckets]]
binding = "MY_BUCKET"
bucket_name = "my-bucket"
[ai]
binding = "AI"npm create cloudflare@latest # scaffold a new project
wrangler dev # local dev server (http://localhost:8787)
wrangler deploy # deploy to production
wrangler tail # stream real-time logs
wrangler secret put SECRET_KEY # add encrypted secret
wrangler kv key put --binding MY_KV "key" "value"// Write
await env.MY_KV.put('user:123', JSON.stringify({ name: 'Alice' }), {
expirationTtl: 3600 // seconds
})
// Read
const raw = await env.MY_KV.get('user:123')
const user = raw ? JSON.parse(raw) : null
// Delete
await env.MY_KV.delete('user:123')
// List keys
const { keys } = await env.MY_KV.list({ prefix: 'user:' })KV Characteristics:
// Query
const { results } = await env.MY_DB.prepare(
'SELECT * FROM users WHERE email = ?'
).bind('[email protected]').all()
// Insert
await env.MY_DB.prepare(
'INSERT INTO users (name, email) VALUES (?, ?)'
).bind('Alice', '[email protected]').run()
// Batch operations
await env.MY_DB.batch([
env.MY_DB.prepare('UPDATE users SET active = 1 WHERE id = ?').bind(1),
env.MY_DB.prepare('INSERT INTO logs (action) VALUES (?)').bind('activated'),
])Schema migrations - use wrangler d1 migrations:
wrangler d1 migrations create my-database add-users-table
wrangler d1 migrations apply my-database --local # local
wrangler d1 migrations apply my-database # production// Upload
await env.MY_BUCKET.put('files/photo.jpg', request.body, {
httpMetadata: { contentType: 'image/jpeg' },
})
// Download
const object = await env.MY_BUCKET.get('files/photo.jpg')
if (!object) return new Response('Not Found', { status: 404 })
return new Response(object.body, {
headers: { 'Content-Type': object.httpMetadata?.contentType ?? 'application/octet-stream' },
})
// Delete
await env.MY_BUCKET.delete('files/photo.jpg')
// List objects
const listed = await env.MY_BUCKET.list({ prefix: 'files/', limit: 100 })// Text generation
const response = await env.AI.run('@cf/meta/llama-3.1-8b-instruct', {
messages: [
{ role: 'system', content: 'You are a helpful assistant.' },
{ role: 'user', content: 'Explain DNS in one paragraph.' },
],
})
return Response.json({ text: response.response })
// Embeddings
const embeds = await env.AI.run('@cf/baai/bge-small-en-v1.5', {
text: ['Hello world', 'Goodbye world'],
})
// embeds.data is an array of float arrays
// Image classification
const result = await env.AI.run('@cf/microsoft/resnet-50', {
image: [...new Uint8Array(await request.arrayBuffer())],
})Available models: check https://developers.cloudflare.com/workers-ai/models/
// src/counter.ts - the Durable Object class
export class Counter implements DurableObject {
state: DurableObjectState
value: number = 0
constructor(state: DurableObjectState, env: Env) {
this.state = state
this.state.blockConcurrencyWhile(async () => {
this.value = (await this.state.storage.get<number>('value')) ?? 0
})
}
async fetch(request: Request): Promise<Response> {
const url = new URL(request.url)
if (url.pathname === '/increment') {
this.value++
await this.state.storage.put('value', this.value)
}
return Response.json({ value: this.value })
}
}
// src/index.ts - Worker that uses it
export default {
async fetch(request: Request, env: Env) {
const id = env.COUNTER.idFromName('global')
const stub = env.COUNTER.get(id)
return stub.fetch(request)
},
}
interface Env {
COUNTER: DurableObjectNamespace
}wrangler.toml:
[[durable_objects.bindings]]
name = "COUNTER"
class_name = "Counter"
[[migrations]]
tag = "v1"
new_classes = ["Counter"]// Producer - enqueue from a Worker
await env.MY_QUEUE.send({ userId: 123, action: 'send-welcome-email' })
// Consumer - process messages
export default {
async queue(batch: MessageBatch<{ userId: number; action: string }>, env: Env) {
for (const msg of batch.messages) {
await processMessage(msg.body)
msg.ack() // acknowledge on success
}
},
} satisfies ExportedHandler<Env>Deploy full-stack apps with Git integration:
npm create cloudflare@latest my-app -- --framework=next
cd my-app
wrangler pages deploy .next # or use the dashboard for Git integrationPages Functions (serverless backend):
// functions/api/user.ts
export async function onRequest(ctx: EventContext<Env, '/api/user', {}>) {
return Response.json({ user: 'Alice' })
}https://developers.cloudflare.com/wrangler secret put for sensitive valuescompatibility_flags = ["nodejs_compat"] in wrangler.toml~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.