---
name: vibe-check-scan
version: 1.0.0
emoji: 🔍
keywords: [security, scanner, headers, tls, cors, api-surface, web-security, cve]
description: Use when the user wants to scan a website for security issues, check HTTP headers, TLS/SSL configuration, CORS policy, or API surface exposure.
---

# Vibe Check Scan

Free passive web security scanner. Returns an A–F grade with per-module findings. No auth required.

## When to use

- User asks to scan a URL for security issues
- User wants to check if a site has proper security headers (CSP, HSTS, etc.)
- User asks about TLS/SSL certificate or protocol version
- User wants to check CORS policy on a site
- User wants to find exposed API endpoints or sensitive files
- User asks whether a site's React Server Components have known advisories (e.g. CVE-2025-55182); the check detects the React version and looks it up in OSV.dev

## When NOT to use

- User asks general security questions answerable from your knowledge
- User wants active penetration testing, fuzzing, or credential testing (this tool is passive only)
- User wants to scan a private/internal IP or localhost
- You already have the scan result in context — answer from context, do not re-scan

## Scanning workflow

Scanning is asynchronous. Prefer this 2-step flow:

| Step | Action | Wait? |
|------|--------|-------|
| 1 | POST /api/scan/start with { "url": "..." } | No — returns scanId immediately |
| 2 | GET /api/scan/status?id={scanId}&format=agent | Poll every 2–3s until top-level status becomes "completed" or "error" |

When the scan finishes, the final status response includes a `result` payload so agents do not need a separate result fetch.

Optional result formats:

- GET https://vibecheckscan.com/api/scan/result?id={scanId} — Complete scan report with all findings. The default.
- GET https://vibecheckscan.com/api/scan/result?id={scanId}&format=summary — Condensed JSON with scores and counts only.
- GET https://vibecheckscan.com/api/scan/result?id={scanId}&format=agent — JSON containing text, markdown, remediationBrief and summary.
- GET https://vibecheckscan.com/api/scan/result?id={scanId}&format=text — Plain text for chat delivery.
- GET https://vibecheckscan.com/api/scan/result?id={scanId}&format=markdown — Markdown for chat delivery.
- GET https://vibecheckscan.com/api/scan/result?id={scanId}&format=telegram — Alias of markdown. (alias of markdown)
- GET https://vibecheckscan.com/api/scan/result?id={scanId}&format=whatsapp — Alias of markdown. (alias of markdown)
- GET https://vibecheckscan.com/api/scan/result?id={scanId}&format=fix — Markdown task list for a coding agent to investigate and fix the findings. Evidence is redacted.
- GET https://vibecheckscan.com/api/scan/result?id={scanId}&format=remediation — Alias of fix. (alias of fix)

The `fix` brief is also available inside `format=agent` as `remediationBrief`.

A share link's report is also fetchable as Markdown at `https://vibecheckscan.com/scan/{scanId}/report.md`.

## Terminology

| API term | Meaning |
|----------|---------|
| `scanId` | 32-char hex identifier for a scan session |
| `overallGrade` | A–F letter grade for the passive configuration checks (A = 90–100, F = <60). A weighted configuration score, not a vulnerability rating — a low grade is not by itself proof of a confirmed vulnerability. |
| `overallScore` | 0–100 weighted score across five weighted modules |
| `modules` | headers (26.25%), tls (22.5%), cors (15%), apiSurface (11.25%), cve (25%, confirmed matches only) |
| `probes` | Individual CORS test requests sent to the target |
| `APISurfaceFinding` | Structured finding with `kind`, `category`, `path`, `status`, and `reason` |
| `confirmedExposure` | Path returned readable content that should be restricted — counts against score |
| `needsReview` | Credential-shaped or context-dependent observation — no score penalty; review before action |
| `protectedSurface` | Path exists but access is correctly blocked (401/403) — no score penalty |
| `expectedPublicEndpoint` | Health, discovery, or metadata path — intentionally public, no score penalty |
| `hardeningOpportunity` | Not exposed but could be hardened further — informational only |

## Interpreting results

When a user asks about their results, explain from the data already in context — do not re-scan.

- **Grade is a weighted average.** headers (26.25%), cve (25%), tls (22.5%) dominate. Confirmed RSC CVEs affect the grade. Server-secret material in shipped JavaScript is scored like an exposed `.env` file; public client config is not.
- **Only `confirmedExposure` findings cost points.** `needsReview`, `protectedSurface`, `expectedPublicEndpoint`, and `hardeningOpportunity` findings are informational. Reassure the user if their protected routes and blocked file probes show up — that means their access controls are working.
- **Priority order:** sensitive file exposures → missing HSTS → weak or missing CSP → weak TLS → CORS wildcards → unprotected API data → remaining lower-priority headers. Missing framing controls or Permissions-Policy alone is usually a hardening opportunity, not a serious incident.
- **Header findings carry an `assessment`** (`effective` / `weak` / `missing` / `invalid` / `unknown` / `not_applicable`). `missing` is absent hardening, not a confirmed vulnerability; `unknown` and `not_applicable` are excluded from the header score. A header module that is all `missing` with nothing `weak`/`invalid` is "needs hardening", not a failure.
- **For in-depth remediation guidance**, fetch `https://vibecheckscan.com/api/agent/interpret` once. It contains per-finding fix instructions, the full category reference, and answers to common user questions.

## Error recovery

| Code | Meaning | What to do |
|------|---------|-----------|
| `missing_url` | No URL in request body | Add "url" field |
| `invalid_url` | URL failed validation | Check format (must be http/https), ensure host is public |
| `rate_limit_exceeded` | Too many requests | Wait for Retry-After seconds, then retry |
| `scan_not_found` | Scan expired, invalid ID, or the poll reached an instance that does not hold this scan | If the response has `"retryable": true`, retry the poll a few times before giving up — the scan may still be running elsewhere. Otherwise start a new scan |
| `invalid_scan_id` | Bad scanId format | Use exact scanId from start_scan response |

## Rate limits

- 5 requests per IP per minute (POST /api/scan/start, POST /api/cve-2025-55182/check)
- 100 requests per IP per minute (HTML page routes; API routes under /api/ are not subject to this limit)
- Status polling is not rate limited. Poll every 2-3 seconds; do not poll faster.
- 429 with Retry-After header (seconds) and code: "rate_limit_exceeded"

## Machine contracts

| Resource | URL |
|----------|-----|
| Capability registry | https://vibecheckscan.com/api/agent/capabilities |
| OpenAPI 3.1 spec | https://vibecheckscan.com/api/openapi.json |
| Agent card | https://vibecheckscan.com/api/agent/card |
| Interpret guide | https://vibecheckscan.com/api/agent/interpret |
| Overview | https://vibecheckscan.com/llms.txt |

## Protocol support

There is no MCP server for this service and none is planned. Use the REST endpoints above.
