Security runbook #
Deterministic security workflow for Blit-Tech repos when MCP scanners are healthy, degraded, or unavailable. Use with
the /security-run skill and pnpm security:mcp-preflight.
Maintainers #
| Role | Contact / owner | Notes |
|---|---|---|
| Primary security | @vancura (CODEOWNERS) |
Sole maintainer for blit-tech and blit-tech-demos (May 2026). |
| Backup / escalation | None (solo project) | No secondary on-call; treat delayed response as accepted project risk. |
Incident triage (solo maintainer):
- Open or triage a GitHub issue: apply label
securityif that label exists in the repository and you have permission; if it does not exist, create the issue and add the label when you can edit repository labels. If you cannot create or label issues, contact @vancura (primary security owner) and record the incident in Linear. - Run Repo-native commands for the affected repo (
pnpm security:audit,pnpm preflight). - Follow dependency-policy.md for CI failures or temporary risk acceptance.
- Record findings using the Report template (Linear comment or issue body).
Bus-factor evidence (optional): run the security-ownership-map skill and attach summary.json to hardening reviews.
VV-522 (backup-owner process) was canceled; the Maintainers section above (including incident triage) is the
documented fallback instead of a fictional backup owner.
When to run #
- Before a comprehensive security assessment or hardening pass.
- Before
/deep-reviewwhen security tooling is in scope. - Monthly MCP governance audit (see Periodic governance).
MCP preflight (required first step) #
Agents must pass the Cursor project MCP descriptor path from the session (for example
~/.cursor/projects/<workspace-id>/mcps).
cd <repo-root> # blit-tech: directory containing this repo's package.json
pnpm security:mcp-preflight -- \
--mcps-dir "<cursor-project-mcps-path>" \
--repo-root . \
--allow-fallback \
--output-json security-reports/mcp-preflight-latest.json
Governance-only (monthly):
pnpm security:mcp-preflight -- \
--mcps-dir "<cursor-project-mcps-path>" \
--repo-root . \
--governance-only \
--include-user-config \
--output-json security-reports/mcp-governance-$(date +%Y-%m).json
Exit codes:
0— proceed (critical MCP healthy, or--allow-fallbackwith documented fallbacks).1— missing--mcps-dir, invalid path, or critical MCP down without--allow-fallback.
Never skip the preflight silently. If a tier is unavailable, run the fallback row from the matrix below and record it in the report.
Fallback matrix #
| Capability | Primary MCP | Fallback (always available) |
|---|---|---|
| Dependency / SCA | Opsera security-scan, JFrog |
pnpm security:audit, pnpm security:audit:prod (per repo); CI gate in blit-tech dependency-policy.md |
| SAST / code patterns | Opsera, Semgrep MCP | pnpm lint (eslint-plugin-security), targeted rg patterns (below), optional semgrep --config auto only if CLI is already installed (do not install) |
| Compliance | Opsera compliance-audit |
Manual checklist below |
| Architecture | Opsera architecture-analyze |
security-threat-model and security-ownership-map skills under ~/.codex/skills/ |
| Supply chain metadata | JFrog MCP | pnpm outdated --format json, npm view <pkg> version time.modified license for key direct deps |
| MCP governance | — | pnpm security:mcp-preflight --governance-only plus Runlayer MCP governance rules |
SAST rg patterns (fallback) #
Run from each repo root when Semgrep/Opsera SAST is unavailable:
rg -n "innerHTML|outerHTML|insertAdjacentHTML|document\\.write\\(|eval\\(|new Function|postMessage\\(|localStorage|sessionStorage" src/
rg -n "CSP|Content-Security-Policy|X-Frame-Options|frame-ancestors|Referrer-Policy" .
Compliance fallback checklist #
When Opsera compliance-audit MCP is unavailable, gather evidence manually:
| Control area | Evidence source |
|---|---|
| Dependency vulnerabilities | pnpm security:audit, pnpm security:audit:prod — see dependency-policy.md |
| CI dependency gate | .github/workflows/ci.yml job Dependency Security Audit (moderate+, every PR and main) |
| Code quality / static checks | pnpm preflight, pnpm lint |
| Secrets in repo | .gitignore, hooks blocking .env; rg for hardcoded tokens (no secret values in reports) |
| CI integrity | .github/workflows/*.yml — pinned actions, least privilege |
| Deploy headers (demos) | blit-tech-demos/public/_headers, curl -I on deployed URLs |
| Ownership / bus factor | Maintainers (solo); optional security-ownership-map skill output (summary.json) |
| MCP governance | pnpm security:mcp-preflight --governance-only |
Repo-native commands #
blit-tech #
cd <repo-root> # or: cd "$PWD" after cloning blit-tech
pnpm security:mcp-preflight -- --mcps-dir "<mcps>" --repo-root . --allow-fallback
pnpm security:audit
pnpm security:audit:prod
pnpm audit --dev --audit-level=moderate
pnpm preflight
Key direct dependencies for supply-chain spot checks: vite, typescript, eslint, vitest, happy-dom.
npm view vite version time.modified license
npm view typescript version time.modified license
blit-tech-demos #
cd <repo-root> # blit-tech-demos: directory containing this repo's package.json
pnpm security:mcp-preflight -- \
--mcps-dir "<mcps>" \
--repo-root . \
--allow-fallback
pnpm security:audit
pnpm security:audit:prod
pnpm audit --dev --audit-level=moderate
pnpm preflight
pnpm build
After toolchain or dependency upgrades, always run pnpm build as a smoke test.
Demos can invoke the canonical preflight script from the library repo (prefer pnpm security:mcp-preflight when the
sibling layout matches package.json). If invoking the script directly, set <blit-tech-root> to the blit-tech repo
path (or export BLIT_TECH_ROOT and use "$BLIT_TECH_ROOT"):
node "<blit-tech-root>/scripts/security/mcp-preflight.mjs" \
--mcps-dir "<mcps>" \
--repo-root . \
--allow-fallback
# Example: export BLIT_TECH_ROOT=/path/to/blit-tech
# node "$BLIT_TECH_ROOT/scripts/security/mcp-preflight.mjs" --mcps-dir "<mcps>" --repo-root . --allow-fallback
Periodic governance (monthly) #
- Run governance-only preflight for both repos (use each repo as
--repo-root). - Review shadow MCP flags; migrate or remove unmanaged servers per organizational policy.
- Re-authenticate critical MCPs (Opsera) if status is
auth_required. - Store reports under
security-reports/(gitignored).
Report template #
Use this structure in agent output or Linear comments:
## Security run report
### MCP preflight
- Opsera: <status>
- JFrog: <status>
- Semgrep: <status>
- Fallbacks used: <list>
### blit-tech
- security:audit: <pass/fail summary>
- prod audit: <pass/fail>
- preflight: <pass/fail>
### blit-tech-demos
- security:audit: <pass/fail summary>
- prod audit: <pass/fail>
- preflight: <pass/fail>
- build: <pass/fail>
### Governance
- Shadow MCPs: <count / none>
- Config paths scanned: <list>