5 Proven CI Gates for API Security: OPA Rules You Can Ship

Engineering leaders don’t need more theory—you need merge-blocking, evidence-producing gates you can roll out this sprint. Below is a practical, code-heavy guide to implement API security CI/CD gates with Open Policy Agent (OPA/Rego) and GitHub Actions, including mappings to SOC 2 & PCI DSS, and automated remediation tickets.

5 Proven CI Gates for API Security: OPA Rules You Can Ship

Looking for help implementing this? Explore Cyber Rely’s API Penetration Testing Services and secure rollout playbooks on our site.


What you’ll build

  • 5 OPA/Rego gates that fail CI when:
    1. endpoints lack authorization,
    2. rate-limits are missing,
    3. code logs PII,
    4. JWTs miss critical claims,
    5. evidence isn’t captured.
  • A single GitHub Actions workflow that runs Conftest, uploads JUnit/SARIF evidence, and auto-opens remediation issues.
  • Evidence mapping your CI output to SOC 2 CC6/CC7 and PCI DSS Req. 6 & 10.

Inputs your gates will read

  • openapi.(yaml|json) – your OpenAPI spec
  • gateway/ – API gateway config (e.g., Kong declarative)
  • scan/semgrep.json – static findings (optional)
  • ci/context.json – build metadata (commit SHA, runner, policy bundle version)

Free Tool screenshot (Website Vulnerability Scanner):

Screenshot of the free tools webpage where you can access security assessment tools for different vulnerability detection.
Screenshot of the free tools webpage where you can access security assessment tools for different vulnerability detection.

Gate #1 — AuthZ required per endpoint (OpenAPI)

Policy intent: Every operation must declare a security requirement that maps to an allowed scheme/role.

policy/authz.rego

package api.authz

# deny if an operation has no security requirement
deny[{"msg": sprintf("Missing authZ on %s %s", [method, path])}] {
  some path, method
  op := input.paths[path][method]
  not op.security
}

# deny if security references an unknown scheme
deny[{"msg": sprintf("Unknown security scheme on %s %s", [method, path])}] {
  some path, method, i
  op := input.paths[path][method]
  scheme := op.security[i]
  not valid_scheme(keys(scheme)[0])
}

valid_scheme(s) {
  s == "oauth2"  # adapt to your org's allowed schemes
} else {
  s == "jwt"
}

Run with Conftest

conftest test openapi.yaml --policy policy --namespace api.authz

Failure effect: CI fails → merge is blocked until missing security is declared.
Evidence: JUnit test report + policy version recorded.


Gate #2 — Rate-limits present (OpenAPI or Gateway config)

Enforce a vendor extension in OpenAPI or a gateway plugin in config.

OpenAPI mode (policy/ratelimit.rego)

package api.ratelimit

deny[{"msg": sprintf("Missing rate-limit on %s %s", [m, p])}] {
  some p, m
  op := input.paths[p][m]
  not op["x-rate-limit"]
}

Kong declarative mode (policy/ratelimit_kong.rego)

package kong.ratelimit

# require global or per-route rate-limiting plugin
deny[msg] {
  not input.plugins[_].name == "rate-limiting"
  not some_route_limit
  msg := "No Kong rate-limiting plugin configured"
}

some_route_limit {
  some i
  input.routes[i].plugins[_].name == "rate-limiting"
}

Gate #3 — No PII in application logs

Feed lightweight static results (e.g., grep/Semgrep) into OPA and fail on risky log patterns.

Example scan/semgrep.json (snippet)

{
  "results": [
    {"check_id":"pii.log.email","path":"svc/user.js","extra":{"message":"logger.info('email=', user.email)"}}
  ]
}

policy/pii_logging.rego

package app.logging

deny[{"msg": sprintf("PII logged in %s: %s", [r.path, r.extra.message])}] {
  r := input.results[_]
  startswith(r.check_id, "pii.log.")
}

Gate #4 — JWT/session claims must be present

Ensure exp, aud, and least-privilege scopes are enforced at the edge.

policy/jwt_claims.rego

package edge.jwt

default required_claims := {"exp", "iat", "sub", "aud"}

deny[{"msg": sprintf("JWT missing required claim: %s", [c])}] {
  some c
  c := required_claims[_]
  not input.jwt[c]
}

deny[{"msg": "scope allows wildcard"}] {
  input.jwt.scope == "*"
}

How to feed input: Have your gateway CI job decode a sample JWT (or fixture) to input.jwt before policy evaluation.


Gate #5 — Evidence & ticket automation

  • Store evidence: upload conftest JUnit + SARIF output, plus ci/context.json (commit, policy bundle hash).
  • Auto-open remediation issues when any gate fails.

scripts/ci_context.sh

jq -n --arg sha "$GITHUB_SHA" --arg run "$GITHUB_RUN_ID" \
  --arg bundle "$(sha256sum policy/*.rego | sha256sum | cut -d' ' -f1)" \
  '{commit:$sha, run_id:$run, policy_bundle:$bundle, timestamp: now|toiso8601}'
  > ci/context.json

GitHub Actions: one-file workflow you can paste

name: api-security-gates

on:
  pull_request:
  push:
    branches: [ main ]

jobs:
  gates:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Set up OPA/Conftest
        uses: instrumenta/conftest-action@v1

      - name: Build CI context
        run: bash scripts/ci_context.sh

      - name: Validate AuthZ
        run: conftest test openapi.yaml --policy policy --namespace api.authz --output junit > junit-authz.xml

      - name: Validate Rate Limits (OpenAPI)
        run: conftest test openapi.yaml --policy policy --namespace api.ratelimit --output junit > junit-rl.xml

      - name: Validate Rate Limits (Kong) # optional
        if: ${{ hashFiles('gateway/kong.yaml') != '' }}
        run: conftest test gateway/kong.yaml --policy policy --namespace kong.ratelimit --output junit > junit-rl-kong.xml

      - name: Scan for PII log patterns (Semgrep)
        run: |
          pipx install semgrep
          semgrep --config p/ci --config r/owasp-top-ten --json -o scan/semgrep.json || true

      - name: Gate on PII logging via OPA
        run: conftest test scan/semgrep.json --policy policy --namespace app.logging --output junit > junit-pii.xml

      - name: Validate JWT claims
        run: conftest test fixtures/jwt.json --policy policy --namespace edge.jwt --output junit > junit-jwt.xml

      - name: Upload Evidence (JUnit)
        uses: actions/upload-artifact@v4
        with:
          name: api-security-evidence
          path: |
            junit-*.xml
            ci/context.json

      - name: Convert to SARIF (optional)
        run: |
          opa eval --format=json -i openapi.yaml -d policy 'data' > sarif.json || true

      - name: Upload SARIF
        uses: github/codeql-action/upload-sarif@v3
        with: { sarif_file: sarif.json }

      - name: Open remediation issue if failed
        if: failure()
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          echo "One or more API Security CI gates failed on $GITHUB_SHA" > body.txt
          echo "Artifacts: api-security-evidence" >> body.txt
          gh issue create --title "Fix: API Security CI gate failures" --body-file body.txt || true

Sample Report screenshot (from the tool) to check Website Vulnerability:

An example of a vulnerability assessment report generated using our free tool provides valuable insights into potential vulnerabilities.
An example of a vulnerability assessment report generated using our free tool provides valuable insights into potential vulnerabilities.

Evidence mapping (SOC 2 & PCI DSS)

  • SOC 2 CC6 (Logical Access), CC7 (Change Mgmt, Monitoring)
    • CI logs + JUnit results prove preventive controls at merge time and detective controls in build telemetry.
  • PCI DSS Requirements 6 & 10 (Secure SDLC & Logging)
    • AuthZ, rate-limit, and JWT gates demonstrably enforce secure coding & config; SARIF/JUnit + pipeline logs show audit evidence captured for assessments.

Need formal mapping & auditor-ready packaging? See our Risk Assessment Services and Remediation Services offerings to turn CI outputs into an assessor-friendly evidence pack.


Rollout plan on CI Gates for API Security (2 sprints)

Sprint 1:

  • Add Gate #1 and #2 on a non-blocking job (warn only), fix noisy endpoints, document allowed schemes/exts.
  • Wire evidence upload.

Sprint 2:

  • Flip to blocking on PRs.
  • Add Gate #3 (PII logging) + Gate #4 (JWT claims).
  • Enable auto-ticket on failure.

Further reading on Cyber Rely


Final Note

And if you need a quick baseline while CI is being wired, run a scan with our free tool at free.pentesttesting.com.


Free Consultation

If you have any questions or need expert assistance, feel free to schedule a Free consultation with one of our security engineers>>

🔐 Frequently Asked Questions (FAQs)

Find answers to commonly asked questions about CI Gates for API Security.

Get a Quote

Leave a Comment

Your email address will not be published. Required fields are marked *

Cyber Rely Logo cyber security
Privacy Overview

This website uses cookies so that we can provide you with the best user experience possible. Cookie information is stored in your browser and performs functions such as recognising you when you return to our website and helping our team to understand which sections of the website you find most interesting and useful.