Skip to content

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:

ResourceEndpointoperationIdBOLA Risk
API keysGET /api/keysuserListApiKeysUser A lists user B’s keys
API keysDELETE /api/keys/{keyId}userRevokeApiKeyUser A revokes user B’s key
API keysPATCH /api/keys/{keyId}userUpdateApiKeyUser A modifies user B’s key
Queue resultsGET /queue/results/{requestId}getQueueResultsUser A reads user B’s compilation result
Queue cancellationDELETE /queue/cancel/{requestId}cancelQueueJobUser A cancels user B’s job
Workflow statusGET /workflow/status/{workflowType}/{instanceId}getWorkflowStatusUser A reads user B’s workflow state
Workflow eventsGET /workflow/events/{workflowId}getWorkflowEventsUser A reads user B’s workflow events
Rule setsGET/PUT/DELETE /rules/{id}getRuleSet/updateRuleSet/deleteRuleSetUser 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() → Handler

The 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 by deno task schema:cloudflare)

Step 1 — Upload the Schema

Terminal window
# Regenerate the Cloudflare-compatible schema (strips localhost, x-* extensions)
deno task schema:cloudflare
# Verify the schema validates cleanly
deno task openapi:validate

Upload 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 typeValue sourceWhere to configure
Clerk JWT (Free tier)Test user’s Clerk sessionVault → cf/vuln-scanner/clerk-jwt-free
Clerk JWT (Pro tier)Test user’s Clerk sessionVault → cf/vuln-scanner/clerk-jwt-pro
API keyabc_... key from test accountVault → cf/vuln-scanner/api-key
Admin keyX-Admin-Key valueVault → 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:

PriorityEndpointsReason
High/api/user/api-keys, /api/queue/*, /api/workflow/*User-owned resources with IDs
Medium/api/configuration/*, /api/admin/deploymentsConfiguration and history
Low/compile, /compile/stream, /compile/batchStateless — 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

CheckWhy it matters
All operations have operationIdRequired 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 dateStale schema → scanner tests wrong surface
OpenAPI spec validates cleanlyMalformed 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 user
const 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 access
const 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 via WHERE user_id = ?
  • DELETE /api/keys/{keyId} (userRevokeApiKey) — scoped via WHERE user_id = ? AND id = ?
  • PATCH /api/keys/{keyId} (userUpdateApiKey) — scoped via WHERE 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 ScoreSeverityTarget fix time
9.0–10.0Critical24 hours
7.0–8.9High72 hours
4.0–6.9Medium1 week
0.1–3.9LowNext sprint

Reporting via GitHub Security Advisories

Repository → Security tab → Advisories → New draft advisory

Include:

  • 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:cloudflare before deployment. They exist solely for the scanner’s static analysis phase.