Positive security for the edge
Allow only what your code accepts.
Positive Edge reads your Next.js app with Claude Opus 5.5, writes a contract for every route — each header, cookie, param and body field — and enforces it on Cloudflare Workers. Everything else is denied.
- GET/api/users/42200api.users.byId
- POST/api/legacy403body key __proto__
- DELETE/api/users/42405method not in contract
- GET/api/users/42200x-forwarded-host dropped
- POST/api/upload200file image/png 182KB
- GET/api/users/1%2f..%2fadmin403path traversal
- GET/?q=shoes&utm_source=x200query utm_source stripped
- PATCH/api/users/42403body.isAdmin not allowed
Default
deny
Signatures
0
Generated by
Claude Opus 5.5
WAF · negative model
- Blocks patterns someone already wrote a rule for.
- Every new CVE is a race against signature updates.
- Forwards every header, cookie and field not recognised as bad.
Positive Edge · positive model
- Allows only inputs your code demonstrably reads.
- Unknown attacks fail closed. There is no list to get ahead of.
- The origin never sees headers, cookies or fields it doesn't use.
How it works
Your codebase is the specification.
01
Read the code
A GitHub Action discovers every App Router, Pages Router, server action and middleware path, and gathers the exact source each one runs.
02
Derive the contract
Claude Opus 5.5 reads each handler and writes the narrowest rule the code justifies, with file and line evidence.
03
Review as a PR
edge-contract.json lands as a pull request with a diff and per-route confidence. Security is reviewed like code.
04
Enforce at the edge
A Cloudflare Worker validates every request before your origin sees it. Start in report mode, then enforce.
The contract
Every rule traces back to a line of code.
A real route and the contract Claude Opus 5.5 generated for it. The auth regex, the integer id and the strict PATCH body are lifted from the handler.
// app/api/users/[id]/route.ts
const patchSchema = z.object({
name: z.string().min(1).max(100),
email: z.string().email().max(254),
}).strict();
function isAuthorized(value: string | null) {
return value !== null && /^Bearer [A-Za-z0-9._-]{1,64}$/u.test(value);
}
export async function PATCH(request: Request, { params }) {
const { id } = await params;
if (!isAuthorized((await headers()).get("authorization"))) return unauthorized();
const userId = Number(id);
if (!Number.isSafeInteger(userId) || userId < 1) return badRequest();
const parsed = patchSchema.safeParse(await request.json());
…
}{
"id": "api-api-users-by-id",
"path": "/api/users/:id",
"methods": ["GET", "PATCH"],
"params": {
"id": { "type": "integer", "minimum": 1, "pattern": "^[1-9][0-9]{0,15}$" }
},
"headers": {
"authorization": { "required": true, "pattern": "^Bearer [A-Za-z0-9._-]{1,64}$" }
},
"unknown": { "query": "deny", "headers": "strip", "cookies": "strip" },
"methodRules": {
"PATCH": { "body": {
"contentTypes": ["application/json"], "maxBytes": 2048,
"json": { "type": "object", "required": ["name", "email"],
"properties": {
"name": { "type": "string", "minLength": 1, "maxLength": 100 },
"email": { "type": "string", "format": "email", "maxLength": 254 }
}, "additionalProperties": false }
} }
},
"confidence": "high"
}Bodies
JSON Schema 2020-12 with additionalProperties: false forced on. Duplicate keys, prototype keys and deep nesting rejected.
Headers
Only headers the code reads are forwarded. Spoofed x-forwarded-* and framework-internal headers never reach the origin.
Cookies
Each cookie has its own type, pattern and length. Unknown cookies are stripped.
Paths
Typed :params and catch-alls with deterministic precedence. Traversal and ambiguous encodings rejected before routing.
Uploads
Per-field rules for multipart and urlencoded forms: file counts, byte limits and MIME types.
Report mode
Ship observe-only first. Violations stream to the dashboard without touching traffic.
CVE-2025-29927 · critical
Blocked without knowing it existed.
On Next.js 14.2.24 one x-middleware-subrequest header skips middleware — including auth. The generated contract never allowed that header and required the session cookie middleware checks. Two independent layers, no signature.
FAQ