OpenAPI Scanning in CI/CD: Make Every Run Explainable
Design an authorized API assessment pipeline with validated contracts, clear run states, protected artifacts, and reviewed release gates.
Read the field noteDesign API scanning integrations around explicit scope, run status, evidence references, and review decisions with a downloadable illustrative JSON report.
An assessment integration should preserve what was authorized, what ran, and what the evidence supports. Do not reduce these distinctions to one pass/fail field. A cancelled job can contain useful observations; a completed job can leave approved questions outside its coverage.
The JSON example below is a downloadable report contract, not a live ApiScanner.com endpoint. It contains fictional staging data and performs no scanning. Adapt the fields to your chosen tool and verify each mapping against its actual output.
Separate run_status, scope, coverage, and findings. Give findings stable identifiers, expected and observed behavior, a test role, an evidence reference, and a review state. Use null or an explicit unknown state when information is unavailable; do not manufacture a confidence score or severity.
The public sample contains no credentials or real response bodies. Your own report may expose internal routes or business data. Store it in an appropriate restricted artifact system, not beside your public website files. Give a sanitized summary to the broader development audience.
{
"schema_version": "1.0",
"illustrative": true,
"notice": "Fictional teaching data. No scan was performed. Not a security assessment of any real system.",
"run_id": "example-staging-inventory-001",
"run_status": "incomplete",
"scope": {
"host": "inventory.example.test",
"environment": "staging",
"roles": [
"Viewer",
"Editor"
],
"excluded": [
"Production",
"Vendor infrastructure",
"Payment providers",
"Destructive operations"
]
},
"coverage": {
"inventory_routes": 8,
"completed_checks": 2,
"incomplete_checks": 2,
"not_assessed": 4,
"observations": 3
},
"routes": [
{
"method": "GET",
"path": "/v1/items",
"test_role": "Viewer",
"check_state": "complete"
},
{
"method": "GET",
"path": "/v1/items/{item_id}",
"test_role": "Viewer",
"check_state": "incomplete"
},
{
"method": "GET",
"path": "/v1/warehouses",
"test_role": "Editor",
"check_state": "complete"
},
{
"method": "GET",
"path": "/v1/warehouses/{warehouse_id}",
"test_role": "Editor",
"check_state": "incomplete"
},
{
"method": "POST",
"path": "/v1/items",
"test_role": "Editor",
"check_state": "not_assessed"
},
{
"method": "PATCH",
"path": "/v1/items/{item_id}",
"test_role": "Editor",
"check_state": "not_assessed"
},
{
"method": "GET",
"path": "/v1/admin/audit",
"test_role": "Outside test roles",
"check_state": "not_assessed"
},
{
"method": "GET",
"path": "/v0/items",
"test_role": "Unknown",
"check_state": "not_assessed"
}
],
"findings": [
{
"id": "EXAMPLE-001",
"title": "Authorization evidence is incomplete",
"route": "/v1/items/{item_id}",
"method": "GET",
"test_role": "Viewer",
"expected_behavior": "Deny access to a synthetic record belonging to another warehouse.",
"observed_behavior": "The illustrative record does not include the cross-warehouse response.",
"evidence_reference": "SYNTHETIC-A01",
"evidence": "Invented worksheet notes record an intended ownership test but no observed response.",
"next_action": "An authorized reviewer should confirm the synthetic identity and capture the approved permitted and denied cases.",
"review_state": "review_required",
"severity": null,
"confidence": "not_assessed"
},
{
"id": "EXAMPLE-002",
"title": "A legacy route needs an owner",
"route": "/v0/items",
"method": "GET",
"test_role": null,
"expected_behavior": "Every inventoried route has a documented owner and lifecycle decision.",
"observed_behavior": "The illustrative inventory contains a legacy route without an owner.",
"evidence_reference": "SYNTHETIC-I02",
"evidence": "The fictional inventory row has no assigned maintenance owner; no runtime behavior is asserted.",
"next_action": "Assign an inventory owner to confirm whether the route remains supported, is retired, or needs documentation.",
"review_state": "review_required",
"severity": null,
"confidence": "not_assessed"
},
{
"id": "EXAMPLE-003",
"title": "Error-response review needs context",
"route": "/v1/warehouses/{warehouse_id}",
"method": "GET",
"test_role": "Editor",
"expected_behavior": "An error response should disclose only information needed by the intended caller.",
"observed_behavior": "The example worksheet notes a field named debug_context but supplies no complete response or interpretation.",
"evidence_reference": "SYNTHETIC-R03",
"evidence": "An invented field label alone is insufficient to establish exposure or business impact.",
"next_action": "Review a sanitized response in the approved environment and confirm whether the field contains unnecessary information.",
"review_state": "review_required",
"severity": null,
"confidence": "not_assessed"
}
]
}Download the illustrative JSON report. The human-readable sample report describes the same fictional observations and counts.
Validate the API specification, approved destinations, staging identity, and test data before execution. ZAP's API scan documentation describes behavior that can include active testing, so review the selected mode rather than assuming an import is merely a static file inspection.
A schema change, expired credential, or scanner update can affect results without a change to the application's permissions. Record those revisions alongside the application release. Make required coverage failures visible instead of permitting a quiet report to imply success.
Choose explicit conditions that stop a release and a documented exception process. Tie exceptions to a narrow requirement, owner, reason, and expiration. For a repaired issue, preserve both the original evidence and the permitted/denied retest results.
Read the OpenAPI and CI/CD field guide before putting an assessment on a release path. Use AI prompts only for bounded interpretation of sanitized evidence, not as the source of execution authority.
Read the documentation that matches your tool, framework, and deployment. These sources provide context; they do not establish coverage of your environment.