Build Guard
Commit-time scanning. Offline. Deterministic. Two engines.
Overview
Build Guard runs at git commit time through a pre-commit hook. Two detection engines run in sequence: a regex engine (cross-language) and an AST engine (Python only at present). Both are offline and require no network after the initial bundle pull.
The default behaviour is to block the commit if a critical or high finding is detected. Medium and low findings are reported but do not block. This is configurable per project.
How to install
$ ekmire hook install
To also run AI dev-audit on every commit diff:
$ ekmire hook install --ai
Verify:
$ cat .git/hooks/pre-commit
To uninstall and remove the hook:
$ ekmire hook uninstallOn-demand scan
Scan staged files (default), a specific path, or recursively:
$ ekmire scan # staged files only (pre-commit default)
$ ekmire scan src/auth.py # single file
$ ekmire scan --deep src/ # full recursive scan of directory
Output formats — useful in CI:
$ ekmire scan --output json --deep . | jq '.findings'
$ ekmire scan --output sarif --deep . > results.sarif
To scan the whole project and report to the dashboard as a device scan:
$ ekmire device-scan .Suppressing a finding
Inline comment suppression uses the # ekmire-ignore:RULE_ID directive (colon, no space before the rule ID):
api_key = "AKIA..." # ekmire-ignore:HARDCODED_AWS_KEY
The suppression must appear on the same line or the line immediately above the flagged code. Suppressions are logged to the dashboard for audit.
Detection engines
Engine A — Regex
Cross-language. Applied to raw file content. Best for secrets and trivial pattern detection.
| RULE ID | SEVERITY | WHAT IT CATCHES |
|---|---|---|
| HARDCODED_AWS_KEY | critical | AWS access keys (AKIA…) |
| HARDCODED_PRIVATE_KEY | critical | PEM private keys |
| HARDCODED_GITHUB_TOKEN | critical | GitHub tokens (gho_, ghp_, …) |
| HARDCODED_GITHUB_PAT | critical | GitHub PATs (ghp_ prefix) |
| HARDCODED_STRIPE_KEY | critical | Stripe secret keys (sk_live_, sk_test_) |
| HARDCODED_GCP_KEY | critical | GCP API keys (AIza…) |
| HARDCODED_ANTHROPIC_KEY | critical | Anthropic API keys (sk-ant-…) |
| HARDCODED_OPENAI_KEY | critical | OpenAI API keys (sk-…) |
| HARDCODED_RAZORPAY_KEY | critical | Razorpay keys (rzp_live_, rzp_test_) |
| HARDCODED_SECRET_GENERIC | critical | Unquoted .env-style assignments (password=, secret=, token=, etc.) — CLI only: pattern uses lookaheads unsupported by the proxy regex engine |
| HARDCODED_GENERIC_SECRET | high | Quoted high-entropy secrets (password=“…”, secret=‘…’) |
| PROMPT_INJECTION_STATIC | high | Static prompt injection strings |
| PROMPT_INJECTION_PATTERN | high | Prompt injection phrases (ignore all previous instructions, …) |
| MCP_SERVER_NETWORK_EXPOSURE | critical | MCP servers bound to 0.0.0.0 |
| MCP_CONFIG_RUG_PULL_RISK | high | MCP servers without version-pinned URLs |
| HIDDEN_INSTRUCTION_IN_COMMENT | high | Hidden AI instructions in code comments |
| VIBE_CODING_XSS_RISK | high | XSS sinks in AI-generated code (innerHTML=, eval(), document.write()) |
Engine B — AST
Python only. Applied to parsed AST. Catches structural patterns that regex cannot reliably detect.
| RULE ID | SEVERITY |
|---|---|
| SQL_INJECTION_RISK | high |
| DANGEROUS_DESERIALISATION | high |
| COMMAND_INJECTION_RISK | high |
| UNSAFE_YAML_LOAD | high |
| MCP_TOOL_POISONING | critical |
Exit codes
| CODE | MEANING |
|---|---|
| 0 | No active findings (clean, or all findings suppressed). Commit allowed. |
| 1 | One or more active findings present. Commit blocked. Also emitted when --fail-on threshold is met. |
Use --fail-on to control the blocking threshold in CI:
# .github/workflows/ci.yml
- name: ekmire scan
run: ekmire scan --deep . --output sarif --fail-on high > results.sarifAI hook variant
$ ekmire hook install --ai
The AI variant runs ekmire scan and ekmire dev-audit --diff on every commit. Adds ~1500 tokens per typical commit. Requires authentication (ekmire auth login) and an LLM provider configured in the dashboard.