speckit-security

How It Works

Six gates, five hooks, eight commands and how they fit into Spec Kit's lifecycle.

The SDD lifecycle with speckit-security wired in

Spec Kit's native lifecycle has five phases: specify, plan, tasks, implement, analyze. speckit-security layers six gates on top of those phases via Spec Kit's hook system.

The after_specify and after_plan hooks run commands that help the author write the data contract and threat model. The gates themselves (A–F) are then all executed by gate-check.sh at the before_implement hook — that's the single blocking step. audit.sh runs at after_implement for the post-code scan, and red-team runs at before_analyze.

Rendering diagram…

The six gates

Each gate is an actual check run by a real bash script, not a checkbox on a form. Gates emit pass / fail / skip verdicts and append a JSONL entry to an append-only gate log.

Gate A, Data Contract

Data Contract section + Zod schema file, no z.any()

Gate B, Threat Model

Threat model section, no High/Critical unmitigated threats

Gate C, Model Governance

No unpinned model versions, rollback plan documented

Gate D, Guardrails

Guardrail YAML with blocked_patterns + redact_patterns

Gate E, Red Team

Red team report file present (runner is separate)

Gate F, Inline Content Scan

No inline system prompts, no committed secrets, no .env in git

Gate A, Data Contract

Runs three checks against the active spec and its schemas:

  1. The spec contains a ## 2. Data Contract or ## Data Contract section
  2. A Zod schema file exists at src/schemas/<slug>.ts
  3. The schema file does not contain z.any() (which bypasses type safety)

Blocks if any check fails. Note: the gate verifies the section and schema file exist, it does not parse the content of the section or enforce what's inside it. The reviewer is responsible for validating that PII, bias, drift, and retention policies are actually declared.

Gate B, Threat Model

Runs two checks:

  1. The spec contains a ## Security / Threat Model section (or a ## Security section that mentions STRIDE or Spoofing)
  2. No [UNMITIGATED] markers exist adjacent to High or Critical severity strings in the spec

Blocks if the section is missing or if the regex [UNMITIGATED].*(High|Critical) matches.

Gate C, Model Governance

Only applies to features with an AI integration (detected by the presence of AI Integration or model: in the spec). Runs two checks:

  1. The spec does not contain latest (anywhere) or "stable" (with quotes), both indicate an unpinned model version
  2. The spec contains the word Rollback (case-insensitive)

Blocks on unpinned versions or missing rollback mention. Note: the gate verifies the rollback mention, it does not parse the rollback plan to check triggers, target versions, or time budgets.

Gate D, Guardrails

Only runs when Gate C did not skip. Four checks:

  1. prompts/guardrails/<slug>.yml exists
  2. prompts/system/<slug>.md exists
  3. The YAML contains blocked_patterns:
  4. The YAML contains redact_patterns:

Blocks if any file is missing or if either pattern section is absent from the guardrail YAML.

Gate E, Red Team

Checks that a file matching red-team/RT-*-<slug>.md exists. Skips with a warning if no file is found (red team is a VERIFY-phase activity and not required at before_implement time).

The separate red-team-run.sh helper reads that report file, parses scenarios from it, and POSTs them to a staging endpoint with safety guards: refuses URLs matching prod/production, rate-limits to max_rps (default 10), and injects an X-Red-Team header. That script is triggered by the red-team command with the --run flag.

Gate F, Inline Content Scan

Three checks, in order:

  1. Inline prompts, greps src/**/*.{ts,tsx,js,jsx,py} for patterns like you are a, as an ai, <|system|> (case-insensitive). Files with gateway in their path are excluded so the gateway client itself can reference model SDKs.
  2. Committed secrets, greps *.ts, *.tsx, *.js, *.py files across the repo (excluding node_modules/, .git/, .next/, out/, .source/, .wrangler/, and dist/) for sk_live_, sk_test_, BEGIN (RSA|EC|OPENSSH) PRIVATE KEY, ghp_ (GitHub personal tokens), AKIA[A-Z0-9]{16} (AWS), and AIza[A-Za-z0-9_-]{35} (Google). The post-implementation audit.sh scans an even wider set, including xoxb- Slack tokens, gho_/ghs_, DSA and ENCRYPTED private keys, and also inspects .env* files directly.
  3. .env in git, runs git ls-files and checks for any path matching ^\.env(\..*)?$.

Blocks if any of the three checks finds a hit.

Note: direct model SDK imports outside the gateway are checked by audit.sh, not Gate F. Gate F is about inline prompts, secrets, and committed .env only. See the audit command for the direct-SDK-import check.

The five hooks

Hooks are how the gates fire automatically without the developer remembering to run them. Each hook is registered in extension.yml under the hooks: block.

HookCommand it runsBlocking?
after_specifydata-contractOptional, prompts the user
after_planthreat-modelOptional, prompts the user
before_implementgate-checkRequired, blocks on failure
after_implementauditRequired, blocks on critical findings
before_analyzered-teamOptional, prompts the user

The eight commands

CommandPurposeHook?
/speckit.tekimax-security.data-contractDeclare data contract (schemas, PII, bias, drift, retention)after_specify
/speckit.tekimax-security.threat-modelGenerate STRIDE threat modelafter_plan
/speckit.tekimax-security.model-governancePin model version, define eval criteria, rollback planmanual
/speckit.tekimax-security.guardrailsGenerate input/output guardrail configmanual
/speckit.tekimax-security.gate-checkRun all gates and emit verdictbefore_implement
/speckit.tekimax-security.auditPost-implementation scanafter_implement
/speckit.tekimax-security.red-teamGenerate adversarial scenarios and run thembefore_analyze
/speckit.tekimax-security.install-rulesInstall dev rules into docs, constitution, and agent contextmanual

Append-only gate log

Every gate-check run appends a JSONL entry to .tekimax-security/gate-log.jsonl:

{"spec":"F-001","phase":"before_implement","verdict":"PASS","ts":"2026-04-13T08:30:00Z","user":"Christian Kaman","gates":{"A":"pass","B":"pass","C":"pass","D":"pass","E":"skip","F":"pass"}}

Same for audit.sh.tekimax-security/audit-log.jsonl. The log is append-only by convention, never rewrite or delete entries. This is the audit trail your compliance reviewer reads.

Runtime dependencies

The scripts use only standard tools that already ship with macOS and Linux: bash, grep, sed, git, and python3. The shared lib/config.sh helper shells out to python3 for a small inline YAML reader so each script can fall back to config-defined patterns, allowlists, and thresholds. install-rules.sh and red-team-run.sh also use python3 for JSON handling.

No npm install. No pip install. No third-party Python packages, just the standard library. No language runtime or package manager beyond what your OS already provides. The full test suite runs in under a second.

On this page