Stop merging vulnerable API code — automate PR security gates with Semgrep + Claude AI
Every team says "we'll fix it after the merge."
They rarely do.
I built vorsken — a GitHub Action that blocks pull requests containing
API vulnerabilities before they reach your main branch.
It combines Semgrep static analysis with Claude AI to post a plain-English
verdict directly in the PR comment: BLOCK / FLAG / PASS.
Here's how to add it to any repo in under 5 minutes.
What it does
When a PR is opened or updated:
- Semgrep scans changed files using OWASP API Security Top 10 rules
- Claude AI analyzes the findings and generates a human-readable report
- A verdict is posted as a PR comment
- A BLOCK verdict fails the required check — the merge is prevented
PR opened
└─▶ Semgrep scans with OWASP API Top10 rules
└─▶ Claude AI explains each finding in plain English
└─▶ BLOCK / FLAG / PASS posted as PR comment
└─▶ BLOCK = merge prevented ✋
text
Why not just use Semgrep alone?
Semgrep gives you rule IDs and line numbers.
vorsken adds the context developers actually need:
| Semgrep alone | vorsken | |
|---|---|---|
| Finding location | ✅ | ✅ |
| OWASP category | ✅ | ✅ |
| What the risk means | ❌ | ✅ (Claude explains) |
| Concrete fix suggestion | ❌ | ✅ (Claude suggests) |
| PR comment | ❌ | ✅ (auto-posted) |
| Merge blocked on BLOCK | ❌ | ✅ |
Setup (5 minutes)
1. Add your Anthropic API key
In your repository: Settings → Secrets → Actions → New repository secret
- Name:
ANTHROPIC_API_KEY - Value:
sk-ant-...
Don't have a key yet? Get one at console.anthropic.com.
2. Create the workflow file
Create .github/workflows/policy-gate.yml:
name: Policy Gate
on:
pull_request:
types: [opened, synchronize, reopened]
jobs:
gate:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: zetide/vorsken@v0.2.6
with:
anthropic-api-key: ${{ secrets.ANTHROPIC_API_KEY }}
That's it. Push this file and open a PR.
What the PR comment looks like
When a vulnerability is detected, vorsken posts a comment like this:
🚨 vorsken Policy Gate — BLOCK
Summary: A hardcoded API key was detected in the changed files.
Rule Severity OWASP Description
hardcoded-api-key CRITICAL API8:2023 Hardcoded credential found in source.
Risk:
An attacker with read access to this repository can use the exposed
credential to authenticate as your service and access protected resources.
Fix:
Remove the hardcoded key. Read it from the environment instead:
api_key = os.environ["API_KEY"]
text
No need to look up the rule documentation — the context is right there in the PR.
OWASP API Security Top 10 coverage
vorsken ships with Semgrep rules covering all 10 OWASP API Security risks (2023 edition):
- API1 — Broken Object Level Authorization
- API2 — Broken Authentication
- API3 — Broken Object Property Level Authorization
- API4 — Unrestricted Resource Consumption
- API5 — Broken Function Level Authorization
- API6 — Unrestricted Access to Sensitive Business Flows
- API7 — Server Side Request Forgery (SSRF)
- API8 — Security Misconfiguration
- API9 — Improper Inventory Management
- API10 — Unsafe Consumption of APIs
Optional: customize the policy
Add a .stacksecai.yml to your repo root to tune the behavior:
policy:
block_on: ["ERROR"]
flag_on: ["WARNING"]
claude:
model: "claude-haiku-4-5"
severity_block: ["CRITICAL", "HIGH"]
severity_flag: ["MEDIUM"]
rules:
overrides:
- rule_id: "hardcoded-password"
action: "BLOCK"
Use your own Semgrep rules
Point semgrep-rules to your own rule directory:
- uses: zetide/vorsken@v0.2.6
with:
anthropic-api-key: ${{ secrets.ANTHROPIC_API_KEY }}
semgrep-rules: ./rules/my-custom-rules
How it's built
- Semgrep — static analysis engine
- Claude API (claude-haiku-4-5) — AI analysis and plain-English output
- tenacity — exponential backoff retry on rate limits
- GitHub Actions — zero-infrastructure deployment
The action is MIT licensed. Source: github.com/zetide/vorsken
Try it now
The easiest way to see it in action:
- Fork or clone any Python API project
- Add the workflow file above
- Open a PR that touches a file with a hardcoded credential or missing auth check
- Watch the BLOCK verdict appear in the PR comment
Available on GitHub Marketplace.
Feedback and contributions welcome — if you try it out, let me know what you think in the comments.
⭐ If this looks useful, a star on GitHub helps others find it:
github.com/zetide/vorsken
This article was originally published by DEV Community and written by vorsken.
Read original article on DEV Community