API Documentation
Integrate VulnRap directly into your workflow. All endpoints are free, anonymous, and require no authentication. Use them with your own tools, CI/CD pipelines, or triage systems.
OpenAPI Specification
Machine-readable description of the API. Import it into your client generator or API tool.
No Auth Required
All endpoints are open and anonymous. No API keys, no accounts, only per-IP rate limits per minute: 10 submissions, 20 checks, 6 batches; see the agent guide for details.
Quick Start
Submit a report and get results in two requests:
# 1. Submit a report for analysis
curl -X POST https://vulnrap.com/api/reports \
-F "file=@vulnerability-report.txt" \
-F "contentMode=full"
# Response: { "id": 42, "slopScore": 12, ... }
# 2. Retrieve the full results
curl https://vulnrap.com/api/reports/42
# Or check a report without storing it (read-only)
curl -X POST https://vulnrap.com/api/reports/check \
-F "rawText=Your report content here..."Endpoints
/api/reports# Upload a file
curl -X POST https://vulnrap.com/api/reports \
-F "file=@my-report.txt" \
-F "contentMode=full"
# Or submit via URL (GitHub, Gist, GitLab, Pastebin, etc.)
curl -X POST https://vulnrap.com/api/reports \
-F "reportUrl=https://github.com/user/repo/blob/main/report.md" \
-F "contentMode=full"Returns report ID, delete token, vulnrap composite (score + label + per-engine breakdown for AI Authorship / Technical Substance / CWE Coherence), legacy slopScore (mapped from composite), llmFeedback, heuristic feedback, similarity matches, redaction summary, and a correlation id for diagnostics lookup
/api/reports/:idcurl -X DELETE https://vulnrap.com/api/reports/42 \
-H "Content-Type: application/json" \
-d '{"deleteToken": "your-token-here"}'Returns confirmation message. Deletion is permanent and irreversible.
/api/reports/check# Paste text directly
curl -X POST https://vulnrap.com/api/reports/check \
-F "rawText=Your report text here..."
# Or check via URL
curl -X POST https://vulnrap.com/api/reports/check \
-F "reportUrl=https://gist.github.com/user/abc123"Returns vulnrap composite (score + label + per-engine breakdown), legacy slopScore (mapped from composite), llmFeedback, similarity matches, section hashes — nothing saved
/api/reports/:idcurl https://vulnrap.com/api/reports/42Returns full analysis: redacted text, slop score, matches, sections
/api/reports/:id/diagnosticscurl https://vulnrap.com/api/reports/42/diagnosticsReturns composite, engines[], perplexity, overridesApplied, warnings, trace { correlationId, stages[], signalsSummary }, legacyMapping { slopScore, displayMode, note }, featureFlags
/api/reports/:id/verifycurl https://vulnrap.com/api/reports/42/verifyReturns slop score, match counts, content hash, verify URL
/api/reports/lookup/:hashcurl https://vulnrap.com/api/reports/lookup/abc123...Returns the report if found, 404 otherwise
/api/statscurl https://vulnrap.com/api/statsReturns totalReports, duplicatesDetected, avgSlopScore, reportsByMode
/api/feedbackcurl -X POST https://vulnrap.com/api/feedback \
-H "Content-Type: application/json" \
-d '{"rating": 5, "helpful": true, "comment": "Great tool!"}'Returns confirmation of feedback submission
Official SDKs
Hand-written, idiomatic clients that wrap the four most common endpoints. No code generation, no extra dependencies.
pip install vulnrapscore_report, lookup_report, query_stats, test_yourself. Fully type-hinted (py.typed), one runtime dep (httpx), typed errors via vulnrap.APIError.pip install vulnrap
from vulnrap import Client
with Client() as c:
res = c.test_yourself(raw_text="Found a path traversal in /api/files...")
print(f"slop={res.slop_score}/{res.slop_tier} confidence={res.confidence:.2f}")github.com/REMEDiSSecurity/VulnRap.Com/sdks/go/vulnrapScoreReport, LookupReport, QueryStats, TestYourself. Idiomatic context.Context-first API, typed errors via *vulnrap.APIError, no panics.go get github.com/REMEDiSSecurity/VulnRap.Com/sdks/go/vulnrap
import (
"context"
"log"
"github.com/REMEDiSSecurity/VulnRap.Com/sdks/go/vulnrap"
)
func main() {
c := vulnrap.NewClient()
res, err := c.TestYourself(context.Background(), &vulnrap.TestYourselfInput{
RawText: "Found a path traversal in /api/files...",
})
if err != nil { log.Fatal(err) }
log.Printf("slop=%d/%s confidence=%.2f", res.SlopScore, res.SlopTier, res.Confidence)
}Postman Collection
Prefer clicking through endpoints to writing curl? Import the auto-generated Postman v2.1 collection. Insomnia, Bruno, and Hoppscotch accept the same file.
vulnrap.postman_collection.json{{baseUrl}} variable defaulting to https://vulnrap.com/api. Regenerated from the OpenAPI spec — never hand-edited.Repo path: sdks/postman/vulnrap.postman_collection.json — regenerate with pnpm --filter @workspace/scripts run generate:postman.
Browser Bookmarklet
Drag the button below onto your bookmarks bar. Click it on any page (a HackerOne report, a Bugcrowd submission, an email, …) to open /check with the currently selected text pre-filled. No extension to install, no permissions to grant.
javascript:(...)window.getSelection() and opens vulnrap.com/check?text=<encoded> in a new tab. Selections longer than 50,000 chars are truncated to stay under URL length limits. Does not auto-submit — you always click Check yourself.Manual install
If your browser blocks dragging, create a new bookmark and paste the contents of sdks/bookmarklet/vulnrap.bookmarklet.url as the URL.
Repo path: sdks/bookmarklet/ — regenerate with pnpm --filter @workspace/scripts run generate:bookmarklet.
GitHub Action
Drop-in composite action that scores incoming security advisory PRs (or VDP issue bodies) against VulnRap and exposes the slop score, tier, and triage verdict as step outputs you can gate merges on or post back as PR comments. Pure bash + curl + jq, no node_modules.
REMEDiSSecurity/VulnRap.Com/sdks/github-actionreport-text or report-file, optional fail-threshold (default 70). Outputs: slop-score, slop-tier, verdict, quality-score, confidence, similarity-match-count.name: VulnRap triage
on:
pull_request:
paths:
- "advisories/**.md"
jobs:
score:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # needed so the diff against the base branch works
- name: Pick the changed advisory
id: pick
run: |
file=$(git diff --name-only origin/${{ github.base_ref }}... \
| grep -E '^advisories/.*\.md$' | head -n1)
echo "file=${file}" >> "$GITHUB_OUTPUT"
- name: Score with VulnRap
id: vulnrap
if: steps.pick.outputs.file != ''
uses: REMEDiSSecurity/VulnRap.Com/sdks/github-action@main
with:
report-file: ${{ steps.pick.outputs.file }}
fail-threshold: 80 # block the PR if it scores 80+
- name: Comment on the PR
if: steps.pick.outputs.file != ''
uses: actions/github-script@v7
with:
script: |
const score = `${{ steps.vulnrap.outputs.slop-score }}`;
const tier = `${{ steps.vulnrap.outputs.slop-tier }}`;
const verdict = `${{ steps.vulnrap.outputs.verdict }}`;
const dupes = `${{ steps.vulnrap.outputs.similarity-match-count }}`;
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: `### VulnRap analysis\n\n- **Slop score:** ${score}/100 (${tier})\n- **Verdict:** \`${verdict}\`\n- **Similar reports:** ${dupes}`,
});Repo path: sdks/github-action/ — not published to the Marketplace; reference by repo path or vendor it.
GitLab CI/CD Component
Reusable GitLab CI/CD component that scores incoming security advisory MRs against VulnRap and exposes the slop score, tier, and triage verdict as dotenv artifact variables downstream jobs can consume. Same engine, same inputs — just include: it and go.
sdks/gitlab-component/template.ymlreport-text or report-file, optional fail-threshold (default 70). Outputs via dotenv artifact: VULNRAP_SLOP_SCORE, VULNRAP_SLOP_TIER, VULNRAP_VERDICT, VULNRAP_QUALITY_SCORE, VULNRAP_CONFIDENCE, VULNRAP_SIMILARITY_MATCH_COUNT.include:
- remote: "https://raw.githubusercontent.com/REMEDiSSecurity/VulnRap.Com/main/sdks/gitlab-component/template.yml"
stages:
- test
- report
vulnrap-score:
variables:
INPUT_REPORT_FILE: advisories/CVE-2026-0001.md
INPUT_FAIL_THRESHOLD: "80" # block the MR if it scores 80+
report-results:
stage: report
needs: [vulnrap-score]
script:
- echo "Slop score $VULNRAP_SLOP_SCORE ($VULNRAP_SLOP_TIER)"
- echo "Verdict $VULNRAP_VERDICT"
- |
if [ "$VULNRAP_VERDICT" = "AUTO_CLOSE" ]; then
echo "This report was flagged as AI slop"
fiRepo path: sdks/gitlab-component/ — include via remote URL or vendor into your repo.
Integration Recipes
End-to-end walkthroughs for wiring VulnRap into specific triage platforms. Pure docs — copy the scripts, adapt to your environment.
report-created webhook into /api/reports/check, post the composite score as an internal comment, and (opt-in) close the AUTO_CLOSE tier with a templated reply. Reference shell, Python, and Go scripts inline.submission.created outbound webhook into /api/reports/check, post the composite score as a team-only note, and (opt-in) transition the AUTO_CLOSE tier to not_applicable with a templated reply. Reference shell + Python scripts inline.submission.created outbound webhook into /api/reports/check, post the composite score as an internal message, and (opt-in) close the AUTO_CLOSE tier with closeReason=NotApplicable and a templated reply. Reference shell + Python scripts inline.Incoming Webhook, an on-demand /vulnrap slash command, and threaded replies on tracker-feed messages via the Events API. Slack app setup (scopes, signing secret, bot token), Slack-style request signature verification, and a shared Block Kit renderer that all three postures reuse.Self-Hosting
Run VulnRap on your own infrastructure. Two reference deployment paths — pick the one that matches your stack.
docker-compose.ymldeploy/helm/vulnraphelm lint. Bring your own PostgreSQL.git clone https://github.com/REMEDiSSecurity/VulnRap.Com.git
cd vulnrap
helm install vulnrap ./deploy/helm/vulnrap \
--namespace vulnrap --create-namespace \
--set-string secrets.data.DATABASE_URL="postgresql://vulnrap:vulnrap@my-pg:5432/vulnrap" \
--set-string secrets.data.OPENAI_API_KEY="sk-..."Repo path: deploy/helm/vulnrap/ — verify with helm lint ./deploy/helm/vulnrap.
Integration Ideas
Example Scripts
Copy-paste scripts you can drop into your workflow:
import requests, pathlib, json
reports_dir = pathlib.Path("./reports")
for f in reports_dir.glob("*.txt"):
r = requests.post("https://vulnrap.com/api/reports/check",
files={"file": open(f, "rb")})
data = r.json()
score = data.get("slopScore", "?")
dupes = len(data.get("similarityMatches", []))
print(f"{f.name}: slop={score}, duplicates={dupes}")#!/bin/bash
# Add to your CI pipeline to reject AI-generated reports
REPORT_FILE="$1"
THRESHOLD=50
RESULT=$(curl -s -X POST https://vulnrap.com/api/reports/check \
-F "file=@$REPORT_FILE")
SCORE=$(echo "$RESULT" | jq '.slopScore')
echo "Slop score: $SCORE / 100"
if [ "$SCORE" -gt "$THRESHOLD" ]; then
echo "FAILED: Report exceeds slop threshold ($THRESHOLD)"
exit 1
fi
echo "PASSED: Report looks human-written"const FormData = require("form-data");
const axios = require("axios");
const fs = require("fs");
async function analyzeAndPost(filePath, slackWebhook) {
const form = new FormData();
form.append("file", fs.createReadStream(filePath));
const { data } = await axios.post(
"https://vulnrap.com/api/reports/check",
form, { headers: form.getHeaders() }
);
const emoji = data.slopScore < 30 ? ":white_check_mark:"
: data.slopScore < 70 ? ":warning:" : ":x:";
const dupes = data.similarityMatches?.length || 0;
await axios.post(slackWebhook, {
text: `${emoji} *VulnRap Analysis*\n`
+ `Slop Score: ${data.slopScore}/100 (${data.slopTier})\n`
+ `Similar Reports: ${dupes}\n`
+ `Redacted Items: ${data.redactionSummary?.total || 0}`
});
}MCP Server (for Claude, Cursor, & agents)
A hosted Model Context Protocol server at https://vulnrap.com/mcp (streamable HTTP, JSON-RPC 2.0, no key). Each of its nine tools calls the same public endpoint the website uses, so the same per-IP rate limits apply and nothing is exposed that the REST API does not already offer.
check_report → POST /api/reports/checksubmit_report → POST /api/reportslookup_report → GET /api/reports/{id}find_by_hash → GET /api/reports/lookup/{hash}list_recent_reports → GET /api/reports/feedrecord_outcome → POST /api/reports/{id}/outcomeget_outcomes_summary → GET /api/outcomes/summaryget_stats → GET /api/statsget_status → GET /api/public/statusmcp-remote bridge or their own HTTP setting. See Connect your agent.claude mcp add --transport http vulnrap https://vulnrap.com/mcp{
"mcpServers": {
"vulnrap": {
"command": "npx",
"args": ["-y", "mcp-remote", "https://vulnrap.com/mcp"]
}
}
}Limits per IP per minute: 30 MCP calls, and the underlying endpoint limits (10 submissions, 20 checks).
