Cloudflare API Shield Vulnerability Scanner
Cloudflare API Shield Vulnerability Scanner
This document describes how Cloudflare’s Web and API Vulnerability Scanner integrates with the bloqr-backend project and how its stateful, AI-driven approach strengthens the existing Zero Trust Architecture.
Overview
Cloudflare’s vulnerability scanner is a stateful, AI-powered security tool built into API Shield. Unlike traditional scanners that fire static test vectors at individual endpoints, it:
- Builds an API call graph from the uploaded OpenAPI spec (
docs/api/cloudflare-schema.yaml) - Sequences requests to simulate realistic attacker workflows (e.g., create a resource as user A → attempt to read/modify it as user B)
- Detects logic flaws that static analysis misses, especially Broken Object Level Authorization (BOLA) — the #1 OWASP API risk
- Uses HashiCorp Vault to protect test credentials during simulated attack flows
The scanner launches in beta targeting BOLA first, with OWASP Top 10 coverage (SQLi, XSS, etc.) planned for later releases.
Why This Matters for bloqr-backend
The bloqr-backend API exposes user-scoped resources that are prime BOLA candidates:
| Resource | Endpoint | operationId | BOLA Risk |
|---|---|---|---|
| API keys | GET /api/keys | userListApiKeys | User A lists user B’s keys |
| API keys | DELETE /api/keys/{keyId} | userRevokeApiKey | User A revokes user B’s key |
| API keys | PATCH /api/keys/{keyId} | userUpdateApiKey | User A modifies user B’s key |
| Queue results | GET /queue/results/{requestId} | getQueueResults | User A reads user B’s compilation result |
| Queue cancellation | DELETE /queue/cancel/{requestId} | cancelQueueJob | User A cancels user B’s job |
| Workflow status | GET /workflow/status/{workflowType}/{instanceId} | getWorkflowStatus | User A reads user B’s workflow state |
| Workflow events | GET /workflow/events/{workflowId} | getWorkflowEvents | User A reads user B’s workflow events |
| Rule sets | GET/PUT/DELETE /rules/{id} | getRuleSet/updateRuleSet/deleteRuleSet | User A reads/modifies user B’s rule set |
Each of these endpoints accepts an ID parameter. The scanner will attempt to access one user’s resource ID using another user’s credentials — exactly the class of bug the existing ZTA auth tier enforces against, but now testable automatically.
Relationship to Existing ZTA
The bloqr-backend already defends against BOLA through its Zero Trust Architecture:
Request → Auth (Clerk JWT / API Key) → requireAuth() → checkRateLimitTiered() → HandlerThe handler is responsible for scoping the query to the authenticated user’s resources. The vulnerability scanner verifies that this scoping is correctly implemented — it doesn’t replace ZTA, it validates it.
flowchart TD
A[API Shield\nVulnerability Scanner] -->|builds call graph from| B[cloudflare-schema.yaml]
A -->|sequences requests using| C[Test credentials\nHashiCorp Vault]
A -->|detects authorization bypass in| D[Worker Handler]
D -->|should enforce| E[Resource ownership check\nuserID === authenticatedUserID]
E -->|reports to| F[Security Dashboard\n+ AnalyticsService.trackSecurityEvent]
Setup Guide
Prerequisites
- API Shield enabled on the Cloudflare zone
- Cloudflare API Shield Vulnerability Scanner in beta access
- An up-to-date
docs/api/cloudflare-schema.yaml(generated bydeno task schema:cloudflare)
Step 1 — Upload the Schema
# Regenerate the Cloudflare-compatible schema (strips localhost, x-* extensions)deno task schema:cloudflare
# Verify the schema validates cleanlydeno task openapi:validateUpload docs/api/cloudflare-schema.yaml to:
Cloudflare Dashboard → Security → API Shield → Schema Validation → Add Schema
Ensure the Mitigation action is set to Block for schema violations.
Step 2 — Enable the Vulnerability Scanner
Cloudflare Dashboard → Security → API Shield → Vulnerability Scanner
Configure scanner credentials for the scanner to use when authenticating requests:
| Credential type | Value source | Where to configure |
|---|---|---|
| Clerk JWT (Free tier) | Test user’s Clerk session | Vault → cf/vuln-scanner/clerk-jwt-free |
| Clerk JWT (Pro tier) | Test user’s Clerk session | Vault → cf/vuln-scanner/clerk-jwt-pro |
| API key | abc_... key from test account | Vault → cf/vuln-scanner/api-key |
| Admin key | X-Admin-Key value | Vault → cf/vuln-scanner/admin-key |
⚠️ Never use production credentials for scanning. Create dedicated test accounts for each tier.
Step 3 — Configure Scan Scope
Limit the scanner to endpoints that handle user-scoped resources to maximise BOLA signal:
| Priority | Endpoints | Reason |
|---|---|---|
| High | /api/user/api-keys, /api/queue/*, /api/workflow/* | User-owned resources with IDs |
| Medium | /api/configuration/*, /api/admin/deployments | Configuration and history |
| Low | /compile, /compile/stream, /compile/batch | Stateless — less BOLA risk |
Step 4 — Review Findings
Scan results appear in:
- Cloudflare Dashboard → Security → API Shield → Vulnerabilities
- Cloudflare Analytics Engine (if scanner emits events — check dashboard)
For each finding, open a GitHub Security Advisory via the process described in SECURITY.md.
CI/CD Integration
The .github/workflows/api-shield-scan.yml workflow runs on every PR and push to main to ensure the OpenAPI spec remains API Shield-compatible:
sequenceDiagram
participant PR as Pull Request
participant CI as api-shield-scan workflow
participant Spec as openapi.yaml
participant Schema as cloudflare-schema.yaml
PR->>CI: trigger on push/pull_request
CI->>Spec: validate openapi.yaml (deno task openapi:validate)
CI->>Schema: regenerate cloudflare-schema.yaml
CI->>Schema: check for drift (git diff)
CI->>Spec: check all operations have operationId
CI->>Spec: check resource endpoints have security annotations
CI-->>PR: ✅ pass / ❌ fail with details
What the workflow checks
| Check | Why it matters |
|---|---|
All operations have operationId | Required for scanner to reference operations in call graphs |
Resource endpoints annotated with security: | Scanner needs to know which auth scheme to use |
cloudflare-schema.yaml is up to date | Stale schema → scanner tests wrong surface |
| OpenAPI spec validates cleanly | Malformed spec → scanner cannot parse call graph |
BOLA Prevention Patterns
Every resource-scoped endpoint in the Worker must scope its database query to the authenticated user. Pattern to follow:
// ✅ Correct — query scoped to authenticated userconst row = await env.DB .prepare('SELECT * FROM api_keys WHERE user_id = ? AND id = ?') .bind(authContext.userId, keyId) .first();
if (!row) { // Return 404 (not 403) — avoid leaking resource existence return JsonResponse.notFound('Not found');}
// ❌ Wrong — unscoped lookup leaks cross-user accessconst row = await env.DB .prepare('SELECT * FROM api_keys WHERE id = ?') .bind(keyId) .first();Return 404, not 403, for missing/unauthorized resources. Returning 403 when a resource exists (but belongs to another user) leaks resource existence — a pattern the scanner will flag.
Verified BOLA-safe endpoints
The following OpenAPI operations have been reviewed and confirmed to scope queries to authContext.userId:
GET /api/keys(userListApiKeys) — scoped viaWHERE user_id = ?DELETE /api/keys/{keyId}(userRevokeApiKey) — scoped viaWHERE user_id = ? AND id = ?PATCH /api/keys/{keyId}(userUpdateApiKey) — scoped viaWHERE user_id = ? AND id = ?
When the scanner is activated, any endpoint or operation not listed here should be reviewed before the first scan run.
Vulnerability Reporting Workflow
When the scanner (or any researcher) discovers a vulnerability:
flowchart LR
A[Scanner finds\nvulnerability] --> B[Cloudflare Dashboard\nVulnerability entry]
B --> C{Severity}
C -->|Critical / High| D[Open GitHub\nSecurity Advisory]
C -->|Medium / Low| E[Open private\nGitHub Issue]
D --> F[Assign fix owner\n+ set SLA]
E --> F
F --> G[Fix implemented\nin feature branch]
G --> H[ZTA PR checklist\ncompleted]
H --> I[Merge + deploy]
I --> J[Re-scan to verify\nfix is effective]
SLA by severity
| CVSS Score | Severity | Target fix time |
|---|---|---|
| 9.0–10.0 | Critical | 24 hours |
| 7.0–8.9 | High | 72 hours |
| 4.0–6.9 | Medium | 1 week |
| 0.1–3.9 | Low | Next sprint |
Reporting via GitHub Security Advisories
Repository → Security tab → Advisories → New draft advisoryInclude:
- CVSS score estimate
- Affected endpoints (operationId list)
- Steps to reproduce (curl commands or Postman collection)
- Suggested fix
OpenAPI Extensions for Scanner Hints
The Cloudflare scanner can use OpenAPI extension fields to improve call graph quality. Add these to resource endpoints when available:
# Example: Queue job endpoint with scanner hints/api/queue/{jobId}: get: operationId: getQueueResults x-cf-resource-type: queue_job # Resource type for BOLA grouping x-cf-owner-field: userId # Field in response that identifies owner security: - ClerkJWT: [] - UserApiKey: []These extensions are stripped by
deno task schema:cloudflarebefore deployment. They exist solely for the scanner’s static analysis phase.
Related Documentation
- Zero Trust Architecture — existing ZTA implementation
- ZTA Developer Guide — patterns for new endpoints
- Security Policy — vulnerability reporting process
- API Shield Setup — schema upload and validation
- OpenAPI Tooling — spec validation and generation
- Cloudflare Blog: Vulnerability Scanner — feature announcement