{
  "markdown": "<div align=\"center\">\n\n<img src=\".github/readme/hero.svg\" alt=\"security-recipes.ai — Search CVEs. Remediate vulnerabilities with AI agents. Sourced NVD + CISA KEV intelligence, evidence-gated canonical records, and bounded remediation plans.\" width=\"100%\" />\n\n[![Live site](https://img.shields.io/badge/Live-security--recipes.ai-2dd4bf.svg?style=flat-square&labelColor=020506)](https://security-recipes.ai/)\n[![CVE Database](https://img.shields.io/badge/CVE_Database-260k%2B_records-2dd4bf.svg?style=flat-square&labelColor=020506)](https://security-recipes.ai/cve-database/)\n[![MCP server](https://img.shields.io/badge/MCP-%2Fmcp-5eead4.svg?style=flat-square&labelColor=020506)](https://security-recipes.ai/mcp-servers/)\n[![Security health action](https://img.shields.io/badge/CI-Security_Health_Action-5eead4.svg?style=flat-square&labelColor=020506)](https://security-recipes.ai/docs/security-health-action/)\n[![llms.txt](https://img.shields.io/badge/agents-llms.txt-67e8f9.svg?style=flat-square&labelColor=020506)](https://security-recipes.ai/llms.txt)\n[![Listed on mcpservers.org](https://mcpservers.org/badge.svg)](https://mcpservers.org/servers/security-recipes-ai-mcp-servers)\n</div>\n\n# security-recipes.ai\n\n**Search CVEs. Remediate vulnerabilities with AI agents.** Sourced facts stay\nsourced, remediation stays bounded, and every plan carries verification,\nrollback, and stop conditions — the live site's contract, and this repo's.\n\n[security-recipes.ai](https://security-recipes.ai/) is an Eleventy site for\nsourced CVE intelligence and evidence-gated vulnerability remediation that AI\nagents can consume without inheriting deployment or production authority.\n\nThe project is intentionally narrow:\n\n- a complete rolling Medium/High/Critical CVE database,\n- evidence-qualified canonical CVE remediation records,\n- practical security remediation recipes,\n- prompt and rules-file examples,\n- agent setup guides,\n- MCP integration patterns,\n- an optional read-only MCP server for recipe search and approved upstream MCP\n  context,\n- a [reusable GitHub Action](https://security-recipes.ai/docs/security-health-action/)\n  that turns this guidance into toggleable CI health checks.\n\nIt is not a scanner, ticketing system, SOAR platform, deployment tool, or custom\nsecurity toolkit. Existing security tools should produce the findings; this\nsite helps agents use the right remediation context and stop at the right time.\n\nStart with the live [CVE Database](https://security-recipes.ai/cve-database/)\nfor an exact vulnerability or the\n[AI Vulnerability Remediation Playbooks](https://security-recipes.ai/security-remediation/)\nfor the evidence-to-patch workflow. Agent-specific guides cover\n[Codex](https://security-recipes.ai/codex/),\n[Claude Code](https://security-recipes.ai/claude/),\n[Cursor](https://security-recipes.ai/cursor/),\n[GitHub Copilot](https://security-recipes.ai/github_copilot/),\n[Devin](https://security-recipes.ai/devin/),\n[Shiba Studio](https://security-recipes.ai/agents/#shiba-studio),\n[Hermes Desktop](https://security-recipes.ai/agents/#hermes-desktop), and\n[OpenClaw](https://security-recipes.ai/agents/#openclaw).\nThe [Visual Guide](https://security-recipes.ai/how-to-use/) shows the complete\npath from source qualification and search discovery to a bounded plan, proof,\nrollback, and human review.\nFor the distinct problem of securing an agent system's identities, tools,\nconnectors, context, memory, runtime, and recovery controls, use\n[AI Agent Security](https://security-recipes.ai/agentic-security/).\n\n## Current product and workflow\n\n![Security Recipes CVE database and AI vulnerability remediation interface](static/images/og-card.png)\n\n### Qualified search discovery\n\n![A source catalog passes an evidence gate before a canonical CVE page reaches search discovery and a reviewed remediation workflow](static/images/how-to-use/canonical-cve-search-discovery.webp)\n\nThe complete catalog remains searchable, while public canonical CVE pages stay\nlimited to reviewed or evidence-qualified records. Those pages ship unique\nsearch metadata, server-rendered core facts and affected-version evidence, one\nremediation authority (stable reviewed guidance first, otherwise complete\nsource-linked AI enrichment), a short approval-gated AI implementation prompt,\ncanonical URLs, breadcrumbs, and `Article`/`TechArticle` structured data. The CVE database\ndescribes the catalog as a `Dataset`; the remediation pillar exposes its visible\nseven-step workflow as a `HowTo`. Year-partitioned CVE sitemaps contain only\nindexable canonical routes, and the build fails when sitemap parity, canonical\nownership, crawl reachability, metadata limits, or same-origin links drift.\n\nIndexability is also withheld from mass-templated recipe children. The 72\ndevelopment code-hygiene recipes and 39 generated compliance-framework recipes\nremain browsable from their canonical hubs with `noindex,follow` while they\nshare a common method. A bounded rendered-body similarity gate prevents a child\nfrom re-entering sitemaps until its evidence, examples, and tests are materially\ndistinct. The hubs remain indexable and carry the shared discovery context.\n\nAfter an SEO-bearing release, the public revision must match the merge commit\nbefore sitemap submission or URL inspection. The\n[Caddy deployment guide](README.caddy-deploy.md#search-discovery-after-an-seo-release)\ndocuments the DNS-verified Search Console handoff, priority live-URL checks,\nsitemap submission, indexing requests, and query monitoring. Submission is a\ndiscovery hint; it does not guarantee indexing or a particular ranking.\n\nThe remediation pillar also records a public repository example for\n[CVE-2026-13149 in `brace-expansion`](https://security-recipes.ai/security-remediation/#real-repository-case-study-cve-2026-13149-in-brace-expansion).\nIt ties the dependency-only change to the\n[reviewed pull request](https://github.com/stevologic/security-recipes.ai/pull/89),\ntests, advisory evidence, and recovery path while explicitly separating the\nsame PR's unrelated Fail2Ban work.\n\n| CVE search to canonical record | CVE evidence to bounded agent plan |\n| --- | --- |\n| ![CVE search, affected surface, evidence, and canonical remediation record](static/images/how-to-use/cve-search-to-record.webp) | ![Seven-phase CVE remediation plan inside a review gate](static/images/how-to-use/cve-to-agent-plan.webp) |\n| Proof and human review | Read-only MCP context |\n| ![Scope, change, tests, evidence, rollback, and human review](static/images/how-to-use/proof-and-review.webp) | ![Read-only MCP context with write access behind explicit approval](static/images/how-to-use/read-only-mcp-context.webp) |\n\n## What this project is for\n\nAI coding agents can help close security findings when their work is bounded:\none finding, one recipe, one reviewed output.\n\nsecurity-recipes.ai helps teams answer:\n\n- Which recipe matches this finding?\n- Which prompt should the agent use?\n- Where do I put the instructions for Copilot, Claude, Cursor, Codex, or Devin?\n- Which MCP servers should the agent read for advisory, scanner, repository, or\n  runbook context?\n- What should the PR or triage note include before a reviewer trusts it?\n\n## What ships\n\n- Eleventy documentation site (fast static builds, no Go toolchain).\n- CVE-first observatory home page and data-first CVE database.\n- Recipe hubs for dependency, SAST, sensitive-data, base-image, CVE, and\n  default-hardening remediation.\n- CVE intelligence intake policy, prompt, fixtures, and evaluator for routing\n  advisory signals before an agent patches.\n- A complete rolling ten-year Medium/High/Critical CVE catalog composed from\n  integrity-verified NVD JSON 2.0 feeds, CISA KEV metadata, and every applicable\n  vetted remediation archetype. Only reviewed `stable` Markdown pages override\n  that conservative baseline.\n- An integrity-hashed search allowlist that publishes canonical CVE pages only\n  for reviewed stable Markdown or AI enrichment that passes the deterministic\n  recipe-ready evidence contract. The full database remains searchable even\n  when a record is not eligible for search indexing.\n- A versioned seven-phase agentic change contract for every catalog CVE:\n  discover, assess, mitigate, remediate, verify, rollback, and triage. Each\n  action declares likely file targets, mutation and approval boundaries,\n  required evidence, outputs, and failure behavior without guessing a patch or\n  fixed version.\n- A structured compliance library spanning 39 security, privacy, assurance,\n  resilience, and software-supply-chain frameworks without reproducing\n  licensed control text. Its framework hub is the search surface; templated\n  child assessments remain `noindex,follow` until differentiated.\n- A 72-recipe code-hygiene library covering cross-language and ecosystem-\n  specific audit, remediation, verification, and stop-condition workflows.\n  Its development children remain `noindex,follow` while their bodies share a\n  generated template.\n- Recipes with existing prompt collections preserved.\n- Agent setup guides for GitHub Copilot, Claude, Cursor, Codex, and Devin.\n- MCP integration guidance for public and organization-approved security data\n  sources.\n- Optional read-only FastMCP server in `mcp_server.py` for recipe search,\n  retrieval, and opt-in upstream MCP context.\n- Docker and Docker Compose configuration for local or droplet hosting.\n- Helper scripts for site maintenance, validation, imports, and deployment.\n\n## Repository map\n\n| Path | Purpose |\n| --- | --- |\n| `content/` | Recipes, documentation, remediation guides, and agent setup pages. |\n| `eleventy.config.js` | Site build configuration (permalinks, feeds, tag pages). |\n| `_includes/` | Page layouts: docs chrome and the standalone home page. |\n| `lib/` | Build modules: shortcode ports, JSON feed builders, SEO head. |\n| `assets/` | Site CSS and JavaScript for the recipe browser, navigation, and helper tools. |\n| `static/` | Images, logos, schemas, and static assets. |\n| `static/api/cve-catalog/` | Complete sharded CVE catalog, year-partitioned machine index, compressed browser-search index, provenance manifest, and archetypes. |\n| `data/cve/` | Human-reviewed remediation archetypes, deterministic AI-enrichment cache, and generated-recipe ownership ledger. |\n| `data/compliance-frameworks/` | Structured compliance-framework catalog and source registry. |\n| `data/code-hygiene/` | Structured code-hygiene catalog, source registry, and routing fixtures. |\n| `docs/` | Repository documentation and legacy screenshot assets; current README and visual-guide images live in `static/images/`. |\n| `mcp_server.py` | Optional read-only MCP server for recipe search and approved upstream MCP context. |\n| `mcp-server.toml.example` | MCP server configuration template. |\n| `Dockerfile` | Site image. |\n| `Dockerfile.mcp-server` | Optional MCP server image. |\n| `docker-compose.yml` | Production-style local stack. |\n| `scripts/` | Helper scripts for maintenance and deployment. |\n\n## Core content areas\n\n- **[CVE Database](https://security-recipes.ai/cve-database/)**: sourced CVE\n  intelligence, affected-version evidence, and canonical remediation records.\n- **[AI Vulnerability Remediation](https://security-recipes.ai/security-remediation/)**:\n  evidence-gated playbooks from one finding to a reviewed patch or triage note.\n- **[AI Agent Security](https://security-recipes.ai/agentic-security/)**:\n  threat modeling, production baselines, source boundaries, control routing,\n  evidence, and incident readiness for the AI-agent system itself.\n- **[Quick Start](https://security-recipes.ai/quickstart/)**: one finding to one\n  reviewed PR or triage note.\n- **[AI Agent Comparison](https://security-recipes.ai/agents/)**: verified\n  operating modes, native instructions, expected artifacts, prerequisites, and\n  review gates for Copilot, Claude Code, Cursor, Codex, and Devin.\n- **[Recipes](https://security-recipes.ai/recipes/)**: reusable prompts,\n  instructions, rules, skills, and review checklists.\n- **[MCP Integration](https://security-recipes.ai/mcp-servers/)**: how to connect\n  security context safely.\n- **[Visual Guide](https://security-recipes.ai/how-to-use/)**: the qualified\n  search-discovery, CVE-to-plan, proof, rollback, review, and read-only MCP flow\n  in five diagrams.\n- **[Docs](https://security-recipes.ai/docs/)**: site usage, agent consumption\n  patterns, and contribution guidance.\n\n## Python remediation tooling\n\nThe Python suite is an optional execution companion to the documentation. It\ncan inspect a bounded workspace, select any of the 75 remediation playbooks,\ncreate a durable run packet, record integrity-hashed evidence, and verify the\npacket before agent or reviewer handoff. It remains local and conservative: it\ndoes not merge code, deploy changes, or call external systems on its own.\n\n```bash\npython scripts/security_recipes_remediation_suite.py playbook list\npython scripts/security_recipes_remediation_suite.py playbook inspect \\\n  --playbook vulnerable-dependencies --workspace .\npython scripts/security_recipes_remediation_suite.py playbook start \\\n  --playbook vulnerable-dependencies --workspace . \\\n  --finding finding.json --run-dir .security-recipes/runs/dependency-fix\npython scripts/security_recipes_remediation_suite.py playbook verify \\\n  --run-dir .security-recipes/runs/dependency-fix\n```\n\nThe repository also includes domain-specific generators and evaluators for\nplaybooks that need richer evidence packs or runtime policy decisions. The\nsite and JSON registry remain useful without Python; the tools make the same\nworkflow contracts directly executable by CI, orchestrators, and approved\ncoding agents.\n\nDeployment helpers worth knowing:\n\n- `scripts/setup_digitalocean_droplet.sh`: Ubuntu droplet bootstrap with\n  Docker, host hardening, and optional Caddy-managed HTTPS.\n- `scripts/configure_nginx_letsencrypt.sh`: host nginx reverse proxy setup for\n  teams that want Let's Encrypt on nginx instead of Caddy.\n- `README.nginx-letsencrypt.md`: operator-focused walkthrough for the nginx\n  deployment path.\n\nRecommended operating model:\n\n1. Let existing SCA, SAST, secrets, CI, cloud, and ticketing systems produce\n   findings.\n2. Attach a matching security-recipes.ai recipe and prompt.\n3. Let the agent read only the files and MCP context needed for the finding.\n4. Require tests and human review before merge.\n5. Keep broad automation, write access, and deployment outside the first loop.\n\n## Guidebook and execution tools\n\nThe site is a guidebook for remediation work: recipes, prompts, agent setup,\nMCP/API integration notes, and review patterns. Runtime automation belongs in\nthe user's approved agent host, CI system, ticketing workflow, or scanner\nplatform rather than a site-hosted chatbot.\n\nPython tools in `scripts/`, `tools/`, and `mcp_server.py` support maintainers\nand self-hosters with playbook execution packets, evidence verification,\ndomain-specific evaluation and generation, validation, advisory import,\nrecipe search, and optional read-only MCP access.\n\n## Optional MCP server\n\nThe MCP server is read-only by default. Its baseline role is to let\nMCP-compatible agents search and retrieve recipes. Self-hosted deployments can\nalso configure it as a context hub for approved upstream MCP servers without\nputting those credentials into the public site.\n\nRetrieved context never grants mutation authority. Any connector that can\nchange repositories, tickets, secrets, deployments, or production systems must\nbe configured and approved separately by the calling host.\n\nCommon tools:\n\n- `recipes_search`\n- `recipes_list`\n- `recipes_get`\n- `recipes_cve_catalog_info`\n- `recipes_cve_search`\n- `recipes_cve_get`\n- `recipes_match_finding`\n- `recipes_playbooks_list`\n- `recipes_playbook_get`\n- `recipes_playbook_plan`\n- `recipes_mcp_upstream_servers`\n- `recipes_mcp_upstream_tools`\n- `recipes_mcp_upstream_call`\n- `recipes_mcp_upstream_context`\n\nThe MCP server accepts both generated recipe feeds:\n\n- `/api/recipes.json` is the preferred agent feed with category, severity,\n  CVE/GHSA, ecosystem, and handoff metadata.\n- `/recipes-index.json` remains supported for legacy consumers.\n- `/recipes-browser.json` is the compact interactive-library feed. The\n  `/recipes/` page server-renders 18 crawlable recipe cards and an exactly\n  matching hydration seed, then requests the complete feed only when a visitor\n  focuses search, filters, sorts, follows a filtered URL, or loads more.\n\nThe complete CVE catalog is also available without MCP:\n\n- `/api/cve-catalog/manifest.json` declares the exact date/severity policy,\n  source hashes, coverage counts, and shard inventory.\n- `/api/cve-catalog/runtime-summary.json` is the small browser bootstrap with\n  coverage totals and content-derived cache versions for every runtime asset.\n- `/api/cve-catalog/index.json` is a small manifest for the complete\n  publication-year partitions under `/api/cve-catalog/indexes/`. Offline\n  consumers can fetch only the years they need; neither a browser page load\n  nor an exact MCP lookup parses those partitions.\n- `/api/cve-catalog/search` is the bounded, same-origin broad-search endpoint.\n  It is pinned to the shard-set revision declared by `runtime-summary.json`,\n  rate-limited at nginx, and returns at most 100 previews. The production MCP\n  image serves it from a read-only SQLite FTS database built and whole-file\n  verified against the same manifest. Focus alone and an incomplete\n  `CVE-YYYY-NNNN` identifier make no search request.\n- `/api/cve-catalog/records/{cve}` is the bounded, same-origin exact-record\n  endpoint. Every request pins the shard-set revision, and the MCP service\n  verifies and opens only the one deterministic shard containing that CVE.\n  Current browsers use this endpoint instead of learning the shard namespace.\n- `/api/cve-catalog/browser-index.json.gz` remains for one compatibility\n  window when an older runtime summary does not declare the search and record\n  APIs. Current browsers do not download it when the APIs are declared, so\n  visitors no longer pay the complete-corpus transfer or memory cost.\n- Canonical CVE pages server-render their overview, affected-version evidence,\n  selected remediation authority, AI implementation and verification handoff,\n  sources, provenance, citation, and schema. They do not embed or hydrate the\n  catalog application. A compact link to the exact gzip JSON Lines shard remains\n  available for machine-readable provenance without adding a browser fetch.\n- `/api/cve-catalog/search-indexable.json` is the compact, integrity-hashed\n  allowlist for canonical CVE pages, related-CVE links, and search discovery.\n  Its policy accepts only reviewed stable Markdown or complete AI enrichment\n  that passes the deterministic recipe-ready evidence contract. Every browser\n  result links to its local `/cve/<ID>/` record. Allowlisted records are\n  materialized as indexable static pages; all other records use the bounded\n  runtime renderer with `noindex,follow` and retain their official CVE.org\n  source in the record.\n- `/api/cve-catalog/archetypes.json` contains the reviewed remediation\n  contracts used to compose a conservative recipe for every catalog record.\n  It also contains the versioned agentic action schema and ecosystem-specific\n  file-target hints shared by the browser and MCP server.\n- Each partition maps every in-scope CVE to its integrity-hashed compressed\n  JSONL shard. Shard records contain CVSS, CWE, bounded CPE, reference, and KEV\n  provenance for exact-CVE retrieval.\n- To keep records bounded, a shard stores at most 12 vulnerable CPE/version\n  rows together with the source match total and an explicit truncation flag;\n  consumers must follow NVD/vendor evidence when that flag is set.\n\nCanonical CVE pages use one primary-reference set for the visible source list\nand structured-data citations. Raw generated records admit NVD, CVE.org,\nscoped CISA KEV records, and source-linked vendor advisories, patches, release\nnotes, or mitigations; broken, third-party-only, exploit-only, and generic\nvulnerability-database links are not promoted automatically. Stable reviewed\nMarkdown can deliberately cite additional HTTPS evidence in its References\nsection. When remediation spans several supported branches or product\nfamilies, the displayed action preserves every trusted fixed-release claim\ninstead of collapsing the guidance to one incomplete upgrade.\n\nDevelopment and catalog-owned stable CVE Markdown emit no standalone page in\nthe pure static build and are excluded from Eleventy and generic recipe/search\nfeeds, tag pages, RSS, and the sitemap. The three pre-catalog historical stable\nrecipes remain ordinary rendered content.\nProduction can retain a legacy recipe URL as a redirect to the canonical CVE\nroute through nginx and the MCP-backed landing service. Use the dedicated\ncatalog or `recipes_cve_*` MCP tools for complete discovery.\n\nThe browser's exact-ID path and revision-pinned search API cover every in-scope\nMedium, High, and Critical record declared by the manifest. The MCP server\nexposes the same SQLite-backed coverage through `recipes_cve_search`; a successful\n`recipes_cve_get` returns the normalized source record, source identifiers and\nreferences, applicable archetypes, composed remediation contract, and a\nself-contained `agentic_change_plan`. The plan expands each mitigation and\nremediation instruction into ordered code/file operations with verification,\nrollback, evidence, approval, and triage requirements. It also preserves\nexplicit CPE truncation metadata when the source match set exceeds the bounded\nrecord.\n\n### Daily CVE synchronization and optional AI enrichment\n\n`.github/workflows/cve-catalog-sync.yml` runs every day at `09:23 UTC` and can\nalso be dispatched manually. It verifies and joins the NVD JSON 2.0 annual\nfeeds and CISA KEV catalog, regenerates every catalog index/shard, validates the\nresult, refreshes recipe-derived deterministic evidence in dependency order,\nruns the catalog tests, and opens or refreshes\n`automation/cve-catalog-sync` as a pull request to the default branch.\nRepository **Settings > Actions > General > Workflow permissions** must allow\nGitHub Actions to create pull requests for first-run PR publication.\n\nSet `CVE_AUTO_MERGE_ENABLED=true` to deliver a safety-approved catalog PR after\nits exact head revision passes the dedicated validation workflow. When\n`CVE_AUTOMATION_APP_CLIENT_ID` and the `CVE_AUTOMATION_APP_PRIVATE_KEY` secret\nare configured, the workflow prefers that GitHub App identity so ordinary PR\nand main-branch `Build` runs fire naturally. Without App credentials, the\nworkflow remains automatic: after the guarded `GITHUB_TOKEN` merge it verifies\nthat the returned merge SHA is still current `main`, then dispatches the real\n`build.yml` workflow with that exact SHA. The production deploy gate recognizes\nonly those CVE-qualified Build dispatches, so scheduled monitors and unrelated\nmanual workflows cannot deadlock or satisfy a release.\n\nThe source sync does not require a secret. Leftover-gold review, content\nrefresh, AI maintenance, AI issue maintenance, and this repository's\nsecurity-health action also use Grok. Add one Actions secret named\n`XAI_API_KEY` (the official xAI environment variable; do not use\n`GROK_API_KEY`):\n\n```bash\ngh secret set XAI_API_KEY --repo stevologic/security-recipes.ai\n```\n\nThe workflow defaults to xAI's `grok-4.6` Responses API model and at most 20\nnew or source-changed records per run. The scheduled queue is\nderived from the tracked NVD/CISA catalog: a candidate must have a valid tagged\nvendor advisory, patch, release-note, or mitigation URL. Source-complete records\nremain eligible because they still need a sourced remediation synthesis; within\neach KEV and severity band they rank ahead of records with deterministic source\ngaps, followed by affected-product/version evidence and recency. This uses the\nexisting daily request budget and does not require an additional manual run.\nBoth the model and limit can be changed with optional Actions variables; the\nenrichment limit is hard-bounded from 0 to 50:\n\n```bash\ngh variable set XAI_MODEL --body \"grok-4.6\" --repo stevologic/security-recipes.ai\ngh variable set XAI_ENRICHMENT_LIMIT --body \"20\" --repo stevologic/security-recipes.ai\n```\n\nAI output is supplemental and explicitly labeled. It uses strict structured\noutput, only cites URLs actually returned in the Responses API web-search\nprovenance, and is stored reproducibly in `data/cve/ai-enrichments.json`. A\ncomplete enrichment becomes a CVE-specific Markdown draft only when a separate\ngate finds claim-level affected-product, exposure, remediation, and\nverification evidence tied to the exact URL of a tagged trusted advisory\nreference. Every required claim must independently meet that rule, and every\ngenerated recipe requires a cited, concrete fixed-version claim.\n\nCached enrichment is re-evaluated instead of becoming permanent: recipe-ready\nentries become refresh candidates after 30 days, KEV entries after 60 days,\nand other complete/not-specific or insufficient-evidence entries after 180\ndays. A manually prioritized CVE forces a refresh inside the existing request\ncap. The last valid cached result stays attached if that refresh fails; an\ninvalid source fingerprint remains fail-closed. The synchronization report and\nautomation-health summary expose refresh-due and manually prioritized counts.\n\nEligible drafts are written as `maturity: development` files named\n`content/recipes/cve/ai-enrichment-cve-*.md`. They stay outside generic recipe\ndiscovery and never override a stable reviewed recipe. A human reviewer can\nset `ai_enrichment_review_status: human-reviewed-development-draft` to withhold\nan otherwise evidence-ready enrichment from public remediation authority, or\n`ai_enrichment_review_status: approved-for-ai-authority` to approve that use.\nUnannotated generator-owned drafts retain the automated evidence gate, while\nstable Markdown always wins. The ownership ledger\nin `data/cve/ai-generated-recipes.json` records each generated file hash;\nautomation may refresh or remove only an untouched hash-matching draft. A human\nedit, or any existing human development/stable recipe for the same CVE, makes\nthat Markdown human-owned and blocks automated replacement. AI generation never\nchanges source CVSS/KEV facts, affected-version data, archetype selection, or\nreviewed stable Markdown. A\nmissing key, API refusal, timeout, or rate limit does not block the NVD/CISA\nrefresh; calls stop after three consecutive failures or a 15-minute budget,\nand valid cached enrichments remain attached. A manual run may prioritize named\nCVEs, but those IDs consume slots inside that run's existing cap and never\nbypass the recipe-ready evidence gate:\n\n```bash\ngh workflow run cve-catalog-sync.yml --ref main \\\n  -f ai_enrichment_limit=20 \\\n  -f priority_cve_ids=\"CVE-2026-58644,CVE-2026-56164\"\n```\n\nA manual dispatch is an additional workflow run and can therefore make\nadditional requests; it is not needed for the daily deterministic queue. A\nmanual run on a non-default branch uploads its enrichment cache, ownership\nledger, and generated drafts as a short-lived workflow artifact for review.\n\n`.github/workflows/leftover-review.yml` runs every day at `13:17 UTC` and\nlive-verifies leftover-gold CVE leftovers against GitHub Advisories and NVD.\nLeftover-gold criticals and highs drain first. After those close, each run\nreviews up to 25 leftover-gold medium and low pages, records completed IDs\nin `data/cve/leftover-review-state.json`, and opens a labeled auto-merge PR.\nThe leftover-review job uses the Grok Build CLI with `XAI_API_KEY` and\nno-ops when that secret is missing or the leftover-gold queue is empty.\n\nThe runtime paths are deliberately bounded for catalog-scale traffic:\n\n- the hub bootstraps from the compact runtime summary, exact lookups call the\n  revision-pinned same-origin record API, and title/product/vendor/filter\n  search calls the search API only after explicit search intent;\n- broad search returns at most 100 previews from immutable read-only SQLite,\n  has a three-second HTTP boundary, and never decodes the complete catalog in\n  a visitor process or on the browser main thread;\n- the exact-record service verifies and opens one shard per request; MCP exact\n  retrieval uses the same shard-only path, while non-exact text search uses the\n  manifest-pinned SQLite database behind a dedicated executor, bounded\n  admission queue, query deadlines, and nginx rate limit;\n- immutable browser cache keys come from the declared record/search contract,\n  archetype hash, and shard-set revision rather than an upstream timestamp.\n\nThe implemented build boundary, exact-shard delivery model, evidence-gated SEO\npolicy, SQLite search runtime, and remaining artifact-publication migration are documented in\n[CVE scale architecture](docs/cve-scale-architecture.md).\n\nThe production image builds the SQLite artifact once in its cached image layer,\nrecords its independent SHA-256 sidecar, and validates schema, catalog revision,\nrecord count, manifest digest, file digest, and representative FTS postings at\nstartup. `RECIPES_MCP_EAGER_CVE_SEARCH` now applies only to the legacy local\nfallback when no SQLite path is configured. For sustained search traffic, run\nmultiple paired MCP instances; exact shard reads remain isolated from the\nbounded text-search executor and queue.\n\nRun `npm run icons` after changing the site mark. It regenerates the opaque\nApple touch icon and the 192/512/maskable installed-app assets checked by the\nproduction performance gate.\n\nProduction builds precompress large JSON/XML feeds for nginx `gzip_static`,\nvalidate stable/draft discovery boundaries, and enforce payload/file-count\nbudgets with `npm run check:performance`.\n\nRun it with Docker:\n\n```bash\ndocker build -f Dockerfile.mcp-server -t security-recipes-mcp .\ndocker run --rm -p 8123:80 security-recipes-mcp\n```\n\nConnect an MCP client to:\n\n```text\nhttp://localhost:8123/mcp\n```\n\nRun it locally with Python:\n\n```bash\npython -m venv .venv\nsource .venv/bin/activate\npip install -r requirements-mcp-server.txt\npython mcp_server.py\n```\n\nWindows PowerShell activation:\n\n```powershell\n.\\.venv\\Scripts\\Activate.ps1\npython mcp_server.py\n```\n\n## Run the site locally\n\nPrerequisites:\n\n- Node.js `>= 20`\n- Python `>= 3.10` with `requirements-mcp-server.txt` installed for the\n  production `npm run build` CVE prerender step\n- Git\n\n```bash\npython -m pip install -r requirements-mcp-server.txt\nnpm install\nnpm run serve\n```\n\nOpen:\n\n```text\nhttp://localhost:8080\n```\n\n`npm run serve` watches for changes and rebuilds incrementally. A one-off\nproduction build is `npm run build` (output lands in `public/`). The build\nperforms a Python/dependency preflight before deleting an existing output and\nthen uses the same CVE renderer as the MCP runtime. Eleventy deliberately does\nnot passthrough-copy `static/api/cve-catalog/`: after page materialization, a\nbounded post-build step rejects links, orphan files, unsafe paths, and\nmanifest byte/hash mismatches before installing that catalog subtree. Static\nassets outside the catalog, including root dotfiles, retain normal passthrough\nbehavior.\n\nFor an isolated catalog build, set\n`SECURITY_RECIPES_CVE_CATALOG_ROOT` to its absolute publication directory.\nEleventy data, qualified-page materialization, and the validated catalog copy\nall use that same root. `npm run serve` does not rerun the materializer or\ncatalog copy, so run `npm run build` once first when you need canonical\n`/cve/<ID>/` pages and the catalog API tree in the development server; later\nincremental rebuilds retain those post-build outputs.\n\n## Docker Compose\n\nCreate an environment file:\n\n```bash\ncp .env.example .env\n```\n\nStart the stack:\n\n```bash\ndocker compose up -d --build\n```\n\nUse the Docker Compose v2 plugin (`docker compose`). The legacy Python\n`docker-compose` v1 package is not supported for this stack; it can crash with\n`KeyError: 'id'` while following logs or `KeyError: 'ContainerConfig'` while\nrecreating containers on newer Docker Engine releases.\n\nOn Ubuntu/Debian hosts, install Compose v2 and a compatibility shim with:\n\n```bash\nsudo bash scripts/install_docker_compose_v2.sh\n```\n\nDefault routes:\n\n```text\nsite: http://127.0.0.1:8080/\nagent recipe feed: /api/recipes.json\nMCP endpoint: /mcp\n```\n\nThe Compose stack keeps the public site and its dynamic CVE/MCP renderer in\nmatching blue/green pairs:\n\n- `security-recipes` / `mcp-server-blue`: blue site and renderer.\n- `security-recipes-green` / `mcp-server-green`: green site and renderer.\n- `mcp-server`: transitional singleton retained for the first paired rollout\n  and backwards-compatible manual Compose workflows. It reads the\n  locally built site feed at `http://security-recipes/api/recipes.json`, so a\n  fork or droplet serves its own recipes instead of depending on the public\n  production index.\n\n`deploy.sh` starts and revision-verifies the withdrawn slot's MCP container\nbefore its site container, validates a canonical CVE directly, and only then\nadmits the pair to Caddy. Manual Compose startup retains the singleton default\nso the first rollout remains compatible with the previously installed script.\n\nFor an nginx or Caddy reverse proxy with Let's Encrypt, keep Docker bound to\nloopback and let the proxy own public ports `80` and `443`:\n\n```env\nSECURITY_RECIPES_HTTP_PORT=127.0.0.1:8080\n```\n\nThen proxy to:\n\n```nginx\nlocation / {\n    proxy_pass http://127.0.0.1:8080;\n    proxy_set_header Host $host;\n    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n    proxy_set_header X-Forwarded-Proto $scheme;\n}\n```\n\nIf you want a turnkey host nginx + Let's Encrypt setup, run:\n\n```bash\nsudo bash scripts/configure_nginx_letsencrypt.sh \\\n  --domain security-recipes.ai \\\n  --email admin@security-recipes.ai\n```\n\nThe full operator guide lives in `README.nginx-letsencrypt.md`.\n\n## DigitalOcean droplet\n\nFor a fresh Ubuntu droplet, use the helper script:\n\n```bash\nsudo bash scripts/setup_digitalocean_droplet.sh \\\n  --domain security-recipes.ai \\\n  --email admin@security-recipes.ai\n```\n\nThe script installs Docker/Compose, configures a locked app user, enables basic\nhost hardening, starts the Compose stack, and can place Caddy in front for\nHTTPS. It also enables a Caddy-aware Fail2Ban jail: five final HTTP 404\nresponses for high-confidence exploit-probe paths (for example `.env`, Git,\nWordPress, phpMyAdmin, or PHPUnit probes) from one client within five seconds\nblock that address from the site's TCP and HTTP/3 ports for one hour, after\nwhich access is restored automatically. Ordinary missing pages, CVE-shaped\nmisses, and archive pagination misses do not consume the ban budget.\n\nPoint both the apex and `www` DNS records at the Droplet before setup. Managed\nCaddy obtains certificates for both names and permanently redirects `www` to\nthe apex canonical host; redirecting only at HTTP would leave HTTPS crawlers\nunable to complete the TLS handshake.\n\nExisting Droplets need this one-time, idempotent activation after deploying\nthe commit that contains the jail:\n\n```bash\nsudo bash scripts/configure_caddy_404_ban.sh\nsudo fail2ban-client status security-recipes-caddy-404\n```\n\nIf the Droplet still runs bundled Caddy with the old named log volume, first\nset `SECURITY_RECIPES_TRAFFIC_LOGS_SOURCE=/var/log/caddy` in `.env`, then\nrecreate only Caddy once during a maintenance window:\n\n```bash\ndocker compose --profile caddy up -d \\\n  --no-deps --force-recreate --pull never caddy\nsudo bash scripts/configure_caddy_404_ban.sh\n```\n\nThe filter uses Caddy's structured `client_ip`, not spoofable forwarding\nheaders or User-Agent values. If the origin is later placed behind a CDN or\nload balancer, move the ban action to that provider's WAF/API; an origin\nfirewall cannot directly block an end client whose packets arrive from a\ntrusted proxy.\n\nThe jail does not trust Googlebot User-Agent strings. Before counting a public\nclient, it performs Google's reverse-then-forward DNS check: the PTR hostname\nmust be under `googlebot.com`, and resolving that hostname must return the same\nIP. Results are cached by IP for one hour; lookup errors and the five-second\nresolver deadline fail closed, so an unverified client remains subject to the\nscanner-path 404 budget.\n\nFor a fully Compose-managed Caddy deployment, Fail2Ban can instead run in the\nstack. Set `DEPLOY_COMPOSE_FAIL2BAN=true` in `.env` and keep Caddy's log source\non the default `caddy_logs` volume (or a host bind). On its next run,\n`deploy.sh` pulls, starts, health-checks, and subsequently updates the Fail2Ban\ncontainer. It also initializes Caddy's access-log file before starting the jail\nbecause Fail2Ban requires the configured file to exist. To start it manually\nwithout waiting for a deployment, use:\n\n```bash\ndocker compose up -d caddy fail2ban\ndocker compose exec fail2ban fail2ban-client status security-recipes-caddy-404\n```\n\nThe container shares the host network namespace and has only the\n`NET_ADMIN`/`NET_RAW` capabilities required to apply the jail's nftables rules\nto host and Docker-forwarded web traffic. Do not enable the Compose jail while\nthe host `security-recipes-caddy-404` jail is active; choose one owner for the\nfirewall rules. This mitigates repeated application-layer 404 scanning, but it\ndoes not replace upstream volumetric DDoS protection or request rate limiting.\nWhen the option is `false`, `deploy.sh` does not require the host `fail2ban`\npackage; host-managed installations remain the responsibility of the droplet\nsetup and `scripts/configure_caddy_404_ban.sh` workflows.\n\nIf you prefer nginx instead of Caddy on the droplet, bootstrap the host without\nthe proxy and then run the nginx helper:\n\n```bash\nsudo bash scripts/setup_digitalocean_droplet.sh --no-caddy\nsudo bash scripts/configure_nginx_letsencrypt.sh \\\n  --domain security-recipes.ai \\\n  --email admin@security-recipes.ai\n```\n\nFor a local-only or pre-proxied droplet:\n\n```bash\nsudo bash scripts/setup_digitalocean_droplet.sh --no-caddy --no-firewall --no-upgrade\ndocker compose up -d --build\n```\n\nIf a previous `docker-compose` v1 run failed with `KeyError:\n'ContainerConfig'`, upgrade Compose and remove the stale project containers\nbefore recreating the stack:\n\n```bash\nsudo bash scripts/repair_docker_compose_containerconfig.sh\nhash -r\ncommand -v docker-compose\ndocker-compose version\n```\n\nProduction deploys pull commit-addressed site and MCP images published by the\nrequired GitHub Actions `Build` workflow on `main` and serve them at\n`https://security-recipes.ai/`. The same timer also deploys `development`\nimages to `https://dev.security-recipes.ai/`. The Droplet does not run Node,\nEleventy, pip, or Docker image builds during a deploy, which keeps deployment\nwithin a 1 CPU / 2 GB memory envelope.\n\n### One-time paired MCP deployment upgrade\n\nBefore the first deployment that introduces the paired MCP services, update\nonly the deployment script and then run it. An already-running older\n`deploy.sh` process was parsed before the paired Compose file existed and would\notherwise recreate the live singleton MCP during that one rollout:\n\n```bash\ngit fetch origin main\ngit checkout origin/main -- deploy.sh\nbash deploy.sh\n```\n\nThe new script leaves the live singleton untouched, prepares the inactive MCP\nand site together, and switches them as one unit. After this one-time step, the\nexisting `bash deploy.sh` cron entry needs no change.\n\nThe first successful `main` workflow creates two GHCR packages. Make them\npublic, or authenticate the root account used by the deployment service with a\nfine-grained token that can read packages:\n\n```bash\nprintf '%s' \"$GHCR_READ_TOKEN\" |\n  sudo docker login ghcr.io --username stevologic --password-stdin\n```\n\n## MCP integration philosophy\n\nUse MCP to give agents context, not unchecked authority.\n\nThe CVE MCP tools only return plans and evidence; they do not edit a repository\nor change an environment. An approved agent host may apply the returned plan,\nbut it must first prove the affected surface and actual repository paths,\npreserve unrelated changes, obtain any declared production/external approval,\nand retain a mechanically usable rollback. A likely file glob is a discovery\nhint, never proof that a file is vulnerable or permission to modify it.\nWithin each action, only effective `target_kinds` are default candidates.\n`archetype_target_kinds` are context, not authorization; conditional targets\nrequire proof that the repository owns the affected implementation, while\nprohibited targets must never be edited. Firmware and binary targets mean an\nauthoritative reference, pin, replacement, policy, inventory, source, or build\nchange—never patching vendor artifact bytes.\n\nNVD/CNA descriptions, advisories, links, patches, issue comments, release\nnotes, and proof-of-concept content are untrusted evidence. Agents may extract\ncorroborated vulnerability and version facts from them, but must not execute or\nfollow embedded instructions or commands.\n\nGood context sources include:\n\n- official GitHub MCP capabilities for repository and code-security context,\n- Semgrep and Snyk agentic/MCP integrations where approved,\n- OSV, GitHub Advisories, deps.dev, package registries, and NVD-backed mirrors,\n- SARIF, SBOM, CI, ownership, and internal runbook sources,\n- read-only documentation connectors.\n\nWrite-capable connectors deserve separate review. Ticket creation, branch\nmutation, deployment, secret rotation, cloud changes, and SOAR actions should\nnot be enabled just because an agent can read a recipe.\n\n## Contributing\n\nContributions should improve the recipe library:\n\n- new remediation recipes,\n- better prompts,\n- clearer agent setup,\n- MCP integration examples,\n- reviewer checklists,\n- documentation fixes.\n\nScrub secrets, internal hostnames, customer data, and private vulnerability\ndetails before opening a pull request.\n\nRun a local build before submitting:\n\n```bash\npython -m pip install -r requirements-dev.txt\npython scripts/run_checks.py\nnpm run build\n```\n\n## License\n\nThe project's original code, documentation, remediation recipes, generated\nsite, and MCP server are licensed under the [Apache License\n2.0](LICENSE). This permits private and commercial use, modification, and\nredistribution, including incorporation into proprietary company systems,\nsubject to the license's notice and change-marking requirements.\n\nSource vulnerability data and bundled third-party software retain their own\nterms and attribution requirements. See [NOTICE](NOTICE) and\n[THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md).\n",
  "bytes": 42558,
  "sha": "b5ef626267f51e8e1636f5224b316115225bc34823ef7a84ae572caeed2d1b09",
  "repo_slug": "stevologic/security-recipes.ai",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_stevologic_security_recipes_50c47c50/readme"
}