Prompt file imported from blit386/blit386 (
.cursor/commands/security-run.md). Copyright stays with the author.
Security Run
Deterministic security workflow for the monorepo. Use before comprehensive security scans, hardening passes, or when MCP scanner availability is uncertain.
Usage
/security-run <package>
Where <package> is blit386 or demos. website, kit, and create-blit386 have no MCP-backed security scanning -
run the root pnpm run security:audit directly (see /deep-review <package> step 3) instead of this skill.
Prerequisites
- The session's MCP descriptor path (
mcpsfolder for the active workspace; agent/tooling-specific) - Node.js and pnpm per
packages/blit386/package.json
Steps
- MCP preflight (required)
-
Read tool schemas before any MCP tool calls (per environment rules)
-
Run from
packages/blit386(canonical script location for both packages):pnpm run security:mcp-preflight -- \ --mcps-dir "<mcps-path>" \ --repo-root . \ --allow-fallback \ --output-json security-reports/mcp-preflight-latest.jsonFor
demos, either run frompackages/blit386with--repo-root ../demos, orcd packages/demosand run with--repo-root .:node ../blit386/scripts/security/mcp-preflight.mjs --mcps-dir "<mcps-path>" --repo-root . --allow-fallback .... -
Record each security MCP status:
healthy,auth_required,errored, orabsent -
If Opsera (
plugin-opsera-devsecops-opsera) is nothealthy, do not skip scans; continue with fallbacks from docs/security/security-runbook.md
- Repo-native checks (per package)
pnpm run security:auditpnpm audit --prod --audit-level=moderatepnpm audit --dev --audit-level=moderate/preflight <package>demosonly:pnpm run buildafter dependency/toolchain changes
- Optional MCP-backed scans (only when healthy)
- Opsera:
architecture-analyze,security-scan,compliance-audit(inspect plugin tool schemas first) - JFrog / Semgrep: only when server status is
healthy
- Cross-package (when assessing both)
- Repeat step 2 for the other package, using the same
--mcps-dirfor both
- Report
- Emit the report template from the runbook
- List every fallback executed and why
Periodic governance (monthly)
.github/workflows/mcp-governance-audit.yml runs a governance-only pass from the repo root automatically every month
and fails (exit 1) if it finds an unaccepted shadow MCP entry - that is the enforced check. Run it by hand only as an
early check or when you specifically need agent-session context; from a package directory:
pnpm run security:mcp-preflight -- \
--repo-root . \
--governance-only \
--include-user-config \
--output-json security-reports/mcp-governance-$(date +%Y-%m).json
--mcps-dir is not required for governance-only calls - that mode never reads the MCP session's tool-state folder, only
static *.mcp.json files.
Then run it once more with the monorepo root as --repo-root (--repo-root ../.. from a package directory), keeping
--include-user-config and writing to a distinct --output-json path so the repo-root report does not overwrite the
per-package one. discoverMcpConfigPaths only walks one level up, so a package-rooted run never reaches the repo root
and never scans the tracked root .mcp.json.
Review shadow MCP flags. Exactly one entry is accepted, and only when all four fields match: name blit386-docs,
classification shadow-remote, config path the repo-root .mcp.json, and URL https://blit386.dev/mcp. A shadow count
of one matching all four is a clean run; anything else - a different name, a different config path, or the same name
pointing elsewhere - is a finding, not an accepted entry. See "Accepted MCP entries" in the runbook. This is no longer
just a human judgment call: the report's governance.unacceptedShadowServers and summary.proceed (the exit code)
already reflect it, matched against ACCEPTED_SHADOW_MCP_ENTRIES in mcp-preflight.mjs (name and classification;
config path is checked against the repo root's own .mcp.json) - the URL field is enforced separately by
pnpm run agents:check, so a finding here still needs a human to decide migrate/remove vs. update the allowlist.
The preflight report prints name, classification, and config path but not the URL, so the URL half is enforced
separately by pnpm run agents:check (findProjectMcpFailures in scripts/check-agent-config.mjs). It pins the
literal https://blit386.dev/mcp rather than just comparing the root .mcp.json against the website's discovery card,
so a coordinated edit aiming both files at another host fails CI too.
Report exactly the three fields the runbook's report template asks for - server name, classification, and config path - and nothing else. Never output secrets, credentials, auth headers, or a full MCP config body. Rewrite config paths repo-relative before pasting them anywhere: the preflight prints absolute paths, so a copied report otherwise leaks the local username.
References
- docs/security/security-runbook.md
packages/blit386/scripts/security/mcp-preflight.mjs.github/workflows/mcp-governance-audit.yml(automated monthly enforcement)- Runlayer MCP governance rule (shadow MCP detection)
