๐งพ API Definition Conformance Lab โ OpenAPI, Contract Linting, AuthZ Checks, and CI Validation
Intro: The most valuable API security lab is often not a scanner pointed at runtime. It is a disciplined workflow that treats the OpenAPI contract as a security-bearing artifact and continuously asks whether the implementation, authorization model, and release process still conform to it.
What this page includes
- a hands-on learning path for OpenAPI security and conformance;
- CLI examples using Redocly and optional 42Crunch-style audit flows;
- examples for auth, authz, and schema-quality checks;
- CI validation patterns for pull requests and release gates.
Why this lab is worth your time
A broken OpenAPI contract teaches three things at once:
- design mistakes create runtime risk;
- missing schema detail creates test blind spots;
- missing auth or weak authz assumptions survive code review if the contract never made them explicit.
This maps directly to real Product Security review work.
Learning objectives
By the end of this lab you should be able to:
- lint an OpenAPI file for structural and quality issues;
- identify missing or weak security definitions;
- detect likely object-level or scope-level authorization gaps;
- fail a PR or release when the contract meaningfully regresses.
Lab workspace structure
openapi-lab/
openapi/
api.yaml
redocly.yaml
rules/
custom-rules.yaml
scripts/
run-contract-checks.sh
.github/workflows/
openapi-governance.yml
Step 1 โ lint the contract with Redocly CLI
Install and run
npm install -g @redocly/cli
redocly lint openapi/api.yaml --extends recommended-strict --format codeframe
Example redocly.yaml
apis:
core@v1:
root: ./openapi/api.yaml
extends:
- recommended
rules:
operation-operationId: error
operation-2xx-response: error
security-defined: error
no-server-example.com: off
What to look for
- missing
operationIdvalues; - missing success response schemas;
- routes with no security scheme when they should not be public;
- ambiguous request/response definitions;
- fields that should be constrained but are not.
Step 2 โ review the contract as a security artifact
For each sensitive route, ask:
- what caller identity is expected?
- what scope or role is required?
- is object ownership implied or explicit?
- are IDs and filters constrained enough to stop mass enumeration?
- are server-generated fields protected from client override?
Example insecure pattern
paths:
/v1/invoices/{invoiceId}:
get:
summary: Get invoice
security:
- bearerAuth: []
parameters:
- in: path
name: invoiceId
required: true
schema:
type: string
This says a token is needed, but says nothing about:
- tenant ownership;
- allowed roles;
- admin-only exceptions;
- object-level authorization expectations.
Better pattern with explicit reviewer notes
paths:
/v1/invoices/{invoiceId}:
get:
operationId: getInvoice
summary: Get one invoice owned by the authenticated tenant
security:
- bearerAuth: [invoices:read]
parameters:
- in: path
name: invoiceId
required: true
schema:
type: string
pattern: '^[a-f0-9-]{36}$'
responses:
'200':
description: Invoice returned only when the authenticated tenant owns the object
'403':
description: Authenticated caller lacks tenant or role entitlement
'404':
description: Object not found or intentionally hidden outside the tenant boundary
Step 3 โ add contract diff checks
Contract drift matters even when the file still parses.
Example breaking-change check idea
openapi-diff old-api.yaml new-api.yaml || true
Use this to review:
- removed fields;
- weakened constraints;
- changed auth requirements;
- response semantics that would break consumers or monitoring.
Step 4 โ optional 42Crunch audit flow
If you use 42Crunch or a similar platform, the learning goal is to compare:
- what a contract security audit catches;
- what your generic lint rules miss;
- what should become part of your baseline API governance policy.
Example GitHub Actions job using 42Crunch action
name: openapi-security-audit
on:
pull_request:
push:
branches: [main]
jobs:
audit:
runs-on: ubuntu-latest
permissions:
contents: read
security-events: write
steps:
- uses: actions/checkout@v4
- name: 42Crunch API contract audit
uses: 42Crunch/api-security-audit-action@v1
with:
api-token: ${{ secrets.FORTYTWOCRUNCH_TOKEN }}
Step 5 โ CI validation with comments and release gates
Example GitHub Actions workflow
name: openapi-governance
on:
pull_request:
push:
branches: [main]
jobs:
lint-contract:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm install -g @redocly/cli
- run: redocly lint openapi/api.yaml --extends recommended-strict --format github-actions
Example GitLab CI job
openapi_contract_lint:
stage: security
image: node:20-alpine
script:
- npm install -g @redocly/cli
- redocly lint openapi/api.yaml --extends recommended-strict --format codeframe
artifacts:
when: always
paths:
- openapi/
Web UI flow for human review
If you use a platform UI such as 42Crunch:
- import the API contract;
- review score and issue classes;
- sort by auth, authz, and schema gaps first;
- tune policy thresholds for production-bound APIs;
- export the report or create tickets;
- record any exception with expiration and compensating controls.
What to document after the lab
Record:
- the routes that lacked meaningful security semantics;
- weak or missing schemas;
- auth-only versus authz-aware routes;
- the CI signal you would make blocking versus advisory;
- one rule you would enforce everywhere.
Common mistakes
- believing that โhas bearer tokenโ means โauthorization is designedโ;
- using contract lint only for syntax and not for security meaning;
- failing to review drift between versions;
- forgetting to tie audit results to release policy.
Cross-links
---Author attribution: Ivan Piskunov, 2026 - Educational and defensive-engineering use.