Reads the lifecycle hooks in ~/.claude/settings.json and the project’s .claude/settings.json: commands the agent runs on its own, before or after a tool call, on stop, or on prompt submit. Every hook is surfaced, benign ones included; a hook is standing executable state most people forget, and the target a persistence path (AP003) would write. Rules HOOK000–HOOK005 in Rules.
Every server’s capabilities with evidence, allowed roots, file scope, and the agent-state files a writable root reaches, then the compositions. Also shown in a normal scan; this view adds --json with the full capability list.
shadow finds two servers exposing a tool with the same name; the model may route calls to either non-deterministically. phantom connects twice and diffs the tool lists; a tool that appears only on the second call is hiding from enumeration.
PHANTOM TOOLS DETECTED Server: analytics-mcp Call 1: query_db, export_csv Call 2: query_db, export_csv, exfil_data ← appeared on second call
Phantom tool behavior is a strong indicator of malicious intent. Remove the server until you can audit its source.
Finds every hardcoded credential in MCP config env blocks and moves it to macOS Keychain, replacing the plaintext value with a $(security find-generic-password ...) substitution resolved at server start.
install-hook writes a Git pre-commit hook that runs aspex-scan --no-exec --fail-on high and blocks the commit on a HIGH or CRITICAL finding; it reads your .aspex.yaml, so accepted risks apply. cron --interval 6h keeps a scan loop running in the foreground and can post new HIGH or CRITICAL findings to a webhook with --notify. For active development, aspex scan --watch is lighter: it re-scans on any config change and prints the security-relevant drift.
--share writes a privacy-safe Markdown summary with server commands, env values and paths redacted. --report soc2 or --report iso27001 maps findings to controls and emits PASS/FAIL per control.--html writes a self-contained report (one file, no external assets) built to be shared: attach it to a PR, drop it in Slack, or open it in a browser. Alongside the per-server findings it renders the two things that are hard to read as terminal text:
Attack paths. Each composed cross-server path drawn hop by hop, from the source instruction through the servers involved to where the data leaves, with the impact and what removes it.
Blast radius. The overall reach (HIGH/MEDIUM/LOW), with every contributing reason listed present or absent, and a note explaining any score cap.
aspex scan --html report.html
The report contains no secret values, only what a scan already prints. Server tool names and descriptions are HTML-escaped, so an untrusted server cannot inject markup into a report you share.
{"docsConfig":{"theme":"mint","$schema":"https://mintlify.com/docs.json","name":"Aspex","colors":{"primary":"#ec3013","light":"#ff9783","dark":"#ae1800"},"logo":{"light":"https://mintcdn.com/aspex/AsYxeTAcjauo5hC7/logo/light.svg?fit=max\u0026auto=format\u0026n=AsYxeTAcjauo5hC7\u0026q=85\u0026s=291ecea15a099f8047decc0604202c15","dark":"https://mintcdn.com/aspex/AsYxeTAcjauo5hC7/logo/dark.svg?fit=max\u0026auto=format\u0026n=AsYxeTAcjauo5hC7\u0026q=85\u0026s=cbccbbea1c0bc688e22550711e3590f0","href":"/introduction"},"favicon":"https://mintcdn.com/aspex/AsYxeTAcjauo5hC7/favicon.svg?fit=max\u0026auto=format\u0026n=AsYxeTAcjauo5hC7\u0026q=85\u0026s=a76f00414e8ed34f1441b09d2bfaa544","navbar":{"links":[{"href":"https://github.com/aspex-security/aspex","label":"GitHub"},{"href":"https://github.com/aspex-security/aspex/blob/main/CHANGELOG.md","label":"Changelog"}],"primary":{"type":"button","label":"Install","href":"/install"}},"footer":{"socials":{"github":"https://github.com/aspex-security/aspex"}},"fonts":{"family":"Archivo"},"styling":{"eyebrows":"section","codeblocks":"dark","latex":false},"navigation":{"pages":[]}},"deployment":{"deploymentMetadataValue":{"subdomain":"aspex","hasAudioNarration":false,"actualSubdomain":"aspex","customDomains":[],"gitSource":{"type":"github","owner":"aspex-security","repo":"docs","deployBranch":"main","contentDirectory":"","isPrivate":false,"mountPath":"","label":""},"entitlements":{"AI_CHAT":{"status":"DISABLED"}},"buildId":"6aa7ebb78a94481b048c0895","clientVersion":"0.0.4076","searchFilterCounts":[{"language":"default","tag":"Commands","count":13},{"language":"default","tag":"Concepts","count":4},{"language":"default","tag":"Guides","count":4},{"language":"default","tag":"Start","count":4},{"language":"default","tag":"Reference","count":4}]},"assistantConfig":{"enableAskAiButton":false,"enableStarterQuestions":false,"enableContextualStarterQuestions":false,"enableAskAiSearchBar":true},"basePath":"","hasChatPermissions":false,"hasWebMcpPermissions":false,"toggles":[{"name":"kill-isr","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-mintlify-slack","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-integrations-settings","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"rbac-expansion","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-pr-grouping","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"custom-prefix","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"analytics-v7","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"user-flows-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"no-publish-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-onboarding","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"llms-txt-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving-live","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"stripTemperatureMiddleware","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"support-platform-pylon-zendesk","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"instant-rollback","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications-server","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-fable","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fixed-ai-action-pricing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automation-resolve-merge-conflict","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"scoped-publishing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"mintql","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"page-level-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-version-history-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-page-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"full-page-search","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workspace-projects","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"assistant-v5","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fork-pr-previews","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"revalidation-jwt","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-sso-scim","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"hobby-abuse-scan","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"dashboard-inbox","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-signup","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"turbopuffer-dual-write","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-enabled","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"approve-review-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-metadata","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"sso-setup-deadline-banner","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"turbopuffer-serve","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"live-agents","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"comment-mode","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false}],"googleFontsInlined":true},"customCss":[{"filePath":"style.css","content":":root{--aspex-ink: #201e1d;--aspex-ground: #f3f2f2;--aspex-surface: #eae9e9;--aspex-accent: #ec3013;--aspex-accent-deep: #ae1800;--aspex-divider: rgba(32, 30, 29, 0.4)}#content-area *,#sidebar *,#navbar *,#topbar *,.prose *{border-radius:0!important}html:not(.dark) body,html:not(.dark) #navbar,html:not(.dark) #sidebar{background:var(--aspex-ground)}html.dark{--aspex-ink: #f3f2f2;--aspex-ground: #201e1d;--aspex-surface: #2c2a29;--aspex-divider: rgba(243, 242, 242, 0.35)}#navbar,#topbar{border-bottom:2px solid var(--aspex-divider)!important}#sidebar{border-right:2px solid var(--aspex-divider)!important}.prose hr{height:2px;border:0;background:var(--aspex-divider)}.prose h1{font-weight:800;letter-spacing:-0.02em;line-height:1.08}.prose h2{font-weight:800;letter-spacing:-0.015em}.prose h3,.prose h4{font-weight:800}#sidebar h5,.eyebrow,[class*=\"eyebrow\"]{font-size:11px;letter-spacing:0.08em;text-transform:uppercase;font-weight:600}#sidebar a,#sidebar li a{border-left:2px solid transparent;padding-left:12px}#sidebar a[aria-current=\"page\"],#sidebar li.active>a{border-left-color:var(--aspex-accent)!important;background:transparent!important;color:var(--aspex-ink)!important;font-weight:600}#navbar a[href=\"/install\"],.prose a.button-primary{background:var(--aspex-accent)!important;color:var(--aspex-ground)!important;font-weight:800;justify-content:flex-start}#navbar a[href=\"/install\"]:hover{background:#dd2b0f!important}.prose pre,[class*=\"codeblock\"] pre{background:#201e1d!important;border-top:2px solid var(--aspex-accent)}.prose :not(pre)>code,[class*=\"card\"] code{background:var(--aspex-surface);color:var(--aspex-ink);padding:2px 6px;font-size:0.9em}.prose table th{font-size:11px;letter-spacing:0.08em;text-transform:uppercase;color:rgba(32, 30, 29, 0.6);border-bottom:2px solid var(--aspex-divider)}html.dark .prose table th{color:rgba(243, 242, 242, 0.6)}.prose table td{border-bottom:1px solid var(--aspex-divider)}.prose table tr:nth-child(2n) td{background:transparent}.prose .card,[class*=\"card\"]{border:2px solid var(--aspex-divider)!important;box-shadow:none!important}.prose .card:hover{background:var(--aspex-surface)}.callout,[class*=\"callout\"]{border-left:2px solid var(--aspex-accent)!important;background:transparent!important}[class*=\"step-indicator\"]{background:var(--aspex-ink)!important;color:var(--aspex-ground)!important;font-weight:800}:focus-visible{outline:2px solid var(--aspex-accent);outline-offset:2px}::selection{background:rgba(236, 48, 19, 0.3)}.prose a{color:var(--aspex-accent-deep);text-underline-offset:3px}html.dark .prose a{color:var(--aspex-light, #ff9783)}html.dark #sidebar a[aria-current=\"page\"],html.dark #sidebar li.active>a{color:var(--aspex-ink)!important}"}],"page":{"pagePath":"tools/scan-subcommands","slug":"/tools/scan-subcommands","pageMetadata":{"title":"scan subcommands","description":"hooks, inspect, inventory, attack-paths, shadow, phantom, fix env, cron, install-hook and the rest of aspex scan.","href":"/tools/scan-subcommands"},"description":{"compiledSource":"\"use strict\";\nconst {jsx: _jsx} = arguments[0];\nconst {useMDXComponents: _provideComponents} = arguments[0];\nfunction _createMdxContent(props) {\n const _components = {\n p: \"p\",\n ..._provideComponents(),\n ...props.components\n };\n return _jsx(_components.p, {\n children: \"hooks, inspect, inventory, attack-paths, shadow, phantom, fix env, cron, install-hook and the rest of aspex scan.\"\n });\n}\nfunction MDXContent(props = {}) {\n const {wrapper: MDXLayout} = {\n ..._provideComponents(),\n ...props.components\n };\n return MDXLayout ? _jsx(MDXLayout, {\n ...props,\n children: _jsx(_createMdxContent, {\n ...props\n })\n }) : _createMdxContent(props);\n}\nreturn {\n default: MDXContent\n};\n","frontmatter":{},"scope":{}},"pageType":"default","mdx":{"mdxSource":{"compiledSource":"\"use strict\";const{Fragment:_Fragment,jsx:_jsx,jsxs:_jsxs}=arguments[0];const{useMDXComponents:_provideComponents}=arguments[0];function _createMdxContent(props){const _components={a:`a`,code:`code`,li:`li`,p:`p`,pre:`pre`,span:`span`,strong:`strong`,tbody:`tbody`,td:`td`,th:`th`,thead:`thead`,tr:`tr`,ul:`ul`,..._provideComponents(),...props.components},{CodeBlock,Heading,Table,Warning}=_components;if(!CodeBlock)_missingMdxReference(`CodeBlock`,true);if(!Heading)_missingMdxReference(`Heading`,true);if(!Table)_missingMdxReference(`Table`,true);if(!Warning)_missingMdxReference(`Warning`,true);return _jsxs(_Fragment,{children:[_jsxs(Table,{children:[_jsx(_components.thead,{children:_jsxs(_components.tr,{children:[_jsx(_components.th,{children:`Subcommand`}),_jsx(_components.th,{children:`Runs`})]})}),_jsxs(_components.tbody,{children:[_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`init`})}),_jsxs(_components.td,{children:[`Write a starter `,_jsx(_components.code,{children:`.aspex.yaml`}),` policy in the current directory`]})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`hooks`})}),_jsx(_components.td,{children:`Discover and judge agent lifecycle hooks`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`doctor`})}),_jsxs(_components.td,{children:[`2-second offline pre-flight. `,_jsx(_components.a,{href:`/tools/doctor`,children:`Own page →`})]})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`inspect \u003ctarget>`})}),_jsx(_components.td,{children:`Scan a single server by command string or URL`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`inventory`})}),_jsx(_components.td,{children:`List every detected server and all their tools`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`attack-paths`})}),_jsx(_components.td,{children:`Every server’s capabilities with evidence, and the compositions they form`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`shadow`})}),_jsx(_components.td,{children:`Tool name collisions across servers`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`phantom`})}),_jsx(_components.td,{children:`Servers that return different tool lists on successive calls`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`fix env`})}),_jsx(_components.td,{children:`Migrate hardcoded credentials from config to macOS Keychain`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`explain \u003cserver>`})}),_jsx(_components.td,{children:`Full risk narrative for one server`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`redteam`})}),_jsxs(_components.td,{children:[`Active adversarial probing. See `,_jsx(_components.a,{href:`/tools/attack`,children:`aspex attack`})]})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`install-hook`})}),_jsx(_components.td,{children:`Git pre-commit hook that blocks risky MCP config changes`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`cron`})}),_jsx(_components.td,{children:`Run on a schedule for continuous monitoring`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`corpus test`})}),_jsxs(_components.td,{children:[`Run the public benchmark. `,_jsx(_components.a,{href:`/reference/corpus`,children:`Corpus →`})]})]})]})]}),`\n`,_jsx(Heading,{level:`2`,id:`hooks`,children:`hooks`}),`\n`,_jsxs(_components.p,{children:[`Reads the lifecycle hooks in `,_jsx(_components.code,{children:`~/.claude/settings.json`}),` and the project’s `,_jsx(_components.code,{children:`.claude/settings.json`}),`: commands the agent runs on its own, before or after a tool call, on stop, or on prompt submit. Every hook is surfaced, benign ones included; a hook is standing executable state most people forget, and the target a persistence path (AP003) would write. Rules HOOK000–HOOK005 in `,_jsx(_components.a,{href:`/reference/rules#agent-hooks`,children:`Rules`}),`.`]}),`\n`,_jsx(Heading,{level:`2`,id:`inspect`,children:`inspect`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`2`,language:`shellscript`,children:_jsx(_components.pre,{className:`shiki shiki-themes dark-plus dark-plus`,style:{backgroundColor:`#0B0C0E`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#D4D4D4`,\"--shiki-dark\":`#D4D4D4`},language:`shellscript`,children:_jsxs(_components.code,{language:`shellscript`,numberOfLines:`2`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#DCDCAA`,\"--shiki-dark\":`#DCDCAA`},children:`aspex`}),_jsx(_components.span,{style:{color:`#CE9178`,\"--shiki-dark\":`#CE9178`},children:` scan`}),_jsx(_components.span,{style:{color:`#CE9178`,\"--shiki-dark\":`#CE9178`},children:` inspect`}),_jsx(_components.span,{style:{color:`#CE9178`,\"--shiki-dark\":`#CE9178`},children:` \"npx -y @modelcontextprotocol/server-filesystem ~/projects\"`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#DCDCAA`,\"--shiki-dark\":`#DCDCAA`},children:`aspex`}),_jsx(_components.span,{style:{color:`#CE9178`,\"--shiki-dark\":`#CE9178`},children:` scan`}),_jsx(_components.span,{style:{color:`#CE9178`,\"--shiki-dark\":`#CE9178`},children:` inspect`}),_jsx(_components.span,{style:{color:`#CE9178`,\"--shiki-dark\":`#CE9178`},children:` https://mcp.example.com/sse`})]}),`\n`]})})}),`\n`,_jsx(_components.p,{children:`One server, not yet in any config. Useful before pasting a README’s config block, and for cloud connectors that have no local file.`}),`\n`,_jsx(Heading,{level:`2`,id:`attack-paths`,children:`attack-paths`}),`\n`,_jsxs(_components.p,{children:[`Every server’s capabilities with evidence, allowed roots, file scope, and the agent-state files a writable root reaches, then the compositions. Also shown in a normal scan; this view adds `,_jsx(_components.code,{children:`--json`}),` with the full capability list.`]}),`\n`,_jsx(Heading,{level:`2`,id:`shadow-and-phantom`,children:`shadow and phantom`}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.code,{children:`shadow`}),` finds two servers exposing a tool with the same name; the model may route calls to either non-deterministically. `,_jsx(_components.code,{children:`phantom`}),` connects twice and diffs the tool lists; a tool that appears only on the second call is hiding from enumeration.`]}),`\n`,_jsx(CodeBlock,{numberOfLines:`5`,language:`text`,children:_jsx(_components.pre,{className:`shiki shiki-themes dark-plus dark-plus`,style:{backgroundColor:`#0B0C0E`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#D4D4D4`,\"--shiki-dark\":`#D4D4D4`},language:`text`,children:_jsxs(_components.code,{language:`text`,numberOfLines:`5`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`PHANTOM TOOLS DETECTED`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` Server: analytics-mcp`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` Call 1: query_db, export_csv`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` Call 2: query_db, export_csv, exfil_data ← appeared on second call`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})})]})})}),`\n`,_jsx(Warning,{children:_jsx(_components.p,{children:`Phantom tool behavior is a strong indicator of malicious intent. Remove the server until you can audit its source.`})}),`\n`,_jsx(Heading,{level:`2`,id:`fix-env`,children:`fix env`}),`\n`,_jsxs(_components.p,{children:[`Finds every hardcoded credential in MCP config `,_jsx(_components.code,{children:`env`}),` blocks and moves it to macOS Keychain, replacing the plaintext value with a `,_jsx(_components.code,{children:`$(security find-generic-password ...)`}),` substitution resolved at server start.`]}),`\n`,_jsx(CodeBlock,{numberOfLines:`4`,language:`text`,children:_jsx(_components.pre,{className:`shiki shiki-themes dark-plus dark-plus`,style:{backgroundColor:`#0B0C0E`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#D4D4D4`,\"--shiki-dark\":`#D4D4D4`},language:`text`,children:_jsxs(_components.code,{language:`text`,numberOfLines:`4`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` ✓ GITHUB_TOKEN → keychain:aspex/github/GITHUB_TOKEN`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` ✓ SLACK_TOKEN → keychain:aspex/slack/SLACK_TOKEN`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Config updated. Plaintext values removed.`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})})]})})}),`\n`,_jsx(Heading,{level:`2`,id:`install-hook-and-cron`,children:`install-hook and cron`}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.code,{children:`install-hook`}),` writes a Git pre-commit hook that runs `,_jsx(_components.code,{children:`aspex-scan --no-exec --fail-on high`}),` and blocks the commit on a HIGH or CRITICAL finding; it reads your `,_jsx(_components.code,{children:`.aspex.yaml`}),`, so accepted risks apply. `,_jsx(_components.code,{children:`cron --interval 6h`}),` keeps a scan loop running in the foreground and can post new HIGH or CRITICAL findings to a webhook with `,_jsx(_components.code,{children:`--notify`}),`. For active development, `,_jsx(_components.code,{children:`aspex scan --watch`}),` is lighter: it re-scans on any config change and prints the security-relevant drift.`]}),`\n`,_jsx(Heading,{level:`2`,id:`reports`,children:`Reports`}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.code,{children:`--share`}),` writes a privacy-safe Markdown summary with server commands, env values and paths redacted. `,_jsx(_components.code,{children:`--report soc2`}),` or `,_jsx(_components.code,{children:`--report iso27001`}),` maps findings to controls and emits PASS/FAIL per control.`]}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.code,{children:`--html`}),` writes a self-contained report (one file, no external assets) built to be shared: attach it to a PR, drop it in Slack, or open it in a browser. Alongside the per-server findings it renders the two things that are hard to read as terminal text:`]}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Attack paths.`}),` Each composed cross-server path drawn hop by hop, from the source instruction through the servers involved to where the data leaves, with the impact and what removes it.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Blast radius.`}),` The overall reach (HIGH/MEDIUM/LOW), with every contributing reason listed present or absent, and a note explaining any score cap.`]}),`\n`]}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`1`,language:`shellscript`,children:_jsx(_components.pre,{className:`shiki shiki-themes dark-plus dark-plus`,style:{backgroundColor:`#0B0C0E`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#D4D4D4`,\"--shiki-dark\":`#D4D4D4`},language:`shellscript`,children:_jsxs(_components.code,{language:`shellscript`,numberOfLines:`1`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#DCDCAA`,\"--shiki-dark\":`#DCDCAA`},children:`aspex`}),_jsx(_components.span,{style:{color:`#CE9178`,\"--shiki-dark\":`#CE9178`},children:` scan`}),_jsx(_components.span,{style:{color:`#569CD6`,\"--shiki-dark\":`#569CD6`},children:` --html`}),_jsx(_components.span,{style:{color:`#CE9178`,\"--shiki-dark\":`#CE9178`},children:` report.html`})]}),`\n`]})})}),`\n`,_jsx(_components.p,{children:`The report contains no secret values, only what a scan already prints. Server tool names and descriptions are HTML-escaped, so an untrusted server cannot inject markup into a report you share.`})]})}function MDXContent(props={}){const{wrapper:MDXLayout}={..._provideComponents(),...props.components};return MDXLayout?_jsx(MDXLayout,{...props,children:_jsx(_createMdxContent,{...props})}):_createMdxContent(props)}return{default:MDXContent};function _missingMdxReference(id,component){throw new Error(`Expected `+(component?`component`:`object`)+\" `\"+id+\"` to be defined: you likely forgot to import, pass, or provide it.\")}","frontmatter":{},"scope":{"codeStyling":"dark","config":{},"pageMetadata":{"title":"scan subcommands","description":"hooks, inspect, inventory, attack-paths, shadow, phantom, fix env, cron, install-hook and the rest of aspex scan.","href":"/tools/scan-subcommands"}}},"mdxSourceWithNoJs":null},"mdxExtracts":{"tableOfContents":[{"title":"hooks","slug":"hooks","depth":2,"children":[]},{"title":"inspect","slug":"inspect","depth":2,"children":[]},{"title":"attack-paths","slug":"attack-paths","depth":2,"children":[]},{"title":"shadow and phantom","slug":"shadow-and-phantom","depth":2,"children":[]},{"title":"fix env","slug":"fix-env","depth":2,"children":[]},{"title":"install-hook and cron","slug":"install-hook-and-cron","depth":2,"children":[]},{"title":"Reports","slug":"reports","depth":2,"children":[]}],"codeExamples":{}},"jsLinks":[],"subdomain":"aspex","siteName":"Aspex","title":"scan subcommands - Aspex","navMaps":{"firstHrefInVersion":{},"firstHrefInLanguage":{}},"lastModified":"2026-09-14T09:48:04.534Z","originalFileLocation":"tools/scan-subcommands.mdx"},"headHtml":"\u003cscript data-mint-head>(function(){var d=document.documentElement,p=null;if(!p){try{p=localStorage.getItem(\"isDarkMode\")}catch(e){}if(p==='true')p='dark';else if(p==='false')p='light';if(p!=='light'\u0026\u0026p!=='dark'\u0026\u0026p!=='system')p=\"system\"}var r=p==='system'?(matchMedia(\"(prefers-color-scheme: dark)\").matches?'dark':'light'):p;d.classList.remove(r==='dark'?'light':'dark');d.classList.add(r);d.setAttribute(\"data-theme-preference\",p)})();\u003c/script>\u003cmeta data-mint-head name=\"description\" content=\"hooks, inspect, inventory, attack-paths, shadow, phantom, fix env, cron, install-hook and the rest of aspex scan.\">\u003cmeta data-mint-head name=\"application-name\" content=\"Aspex\">\u003cmeta data-mint-head name=\"generator\" content=\"Mintlify\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/aspex/QVudd8SD-Ga_PaCT/_generated/favicon/android-chrome-192x192.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"apple-touch-icon\" type=\"image/png\" sizes=\"180x180\" href=\"/mintlify-assets/_mintlify/favicons/aspex/QVudd8SD-Ga_PaCT/_generated/favicon/apple-touch-icon.png\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/aspex/QVudd8SD-Ga_PaCT/_generated/favicon/favicon-16x16.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/aspex/QVudd8SD-Ga_PaCT/_generated/favicon/favicon-32x32.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/aspex/QVudd8SD-Ga_PaCT/_generated/favicon/favicon.ico\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/aspex/QVudd8SD-Ga_PaCT/_generated/favicon-dark/android-chrome-192x192.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/aspex/QVudd8SD-Ga_PaCT/_generated/favicon-dark/favicon-16x16.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/aspex/QVudd8SD-Ga_PaCT/_generated/favicon-dark/favicon-32x32.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/aspex/QVudd8SD-Ga_PaCT/_generated/favicon-dark/favicon.ico\" media=\"(prefers-color-scheme: dark)\">\u003cmeta data-mint-head property=\"og:title\" content=\"scan subcommands - Aspex\">\u003cmeta data-mint-head property=\"og:description\" content=\"hooks, inspect, inventory, attack-paths, shadow, phantom, fix env, cron, install-hook and the rest of aspex scan.\">\u003cmeta data-mint-head property=\"og:site_name\" content=\"Aspex\">\u003cmeta data-mint-head property=\"og:url\" content=\"https://aspex.mintlify.app/tools/scan-subcommands\">\u003cmeta data-mint-head property=\"og:type\" content=\"website\">\u003cmeta data-mint-head property=\"og:image\" content=\"https://aspex.mintlify.site/_mintlify/api/og/v2?division=Commands\u0026amp;title=scan+subcommands\u0026amp;description=hooks%2C+inspect%2C+inventory%2C+attack-paths%2C+shadow%2C+phantom%2C+fix+env%2C+cron%2C+install-hook+and+the+rest+of+aspex+scan.\u0026amp;theme=32228760862f899422b398a8\u0026amp;signature=df95d1a027e34172d23646d739d416f92e98922debae317adbd2483785770bb7\">\u003cmeta data-mint-head property=\"og:image:width\" content=\"1200\">\u003cmeta data-mint-head property=\"og:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"twitter:card\" content=\"summary_large_image\">\u003cmeta data-mint-head name=\"twitter:title\" content=\"scan subcommands - Aspex\">\u003cmeta data-mint-head name=\"twitter:description\" content=\"hooks, inspect, inventory, attack-paths, shadow, phantom, fix env, cron, install-hook and the rest of aspex scan.\">\u003cmeta data-mint-head name=\"twitter:image\" content=\"https://aspex.mintlify.site/_mintlify/api/og/v2?division=Commands\u0026amp;title=scan+subcommands\u0026amp;description=hooks%2C+inspect%2C+inventory%2C+attack-paths%2C+shadow%2C+phantom%2C+fix+env%2C+cron%2C+install-hook+and+the+rest+of+aspex+scan.\u0026amp;theme=32228760862f899422b398a8\u0026amp;signature=df95d1a027e34172d23646d739d416f92e98922debae317adbd2483785770bb7\">\u003cmeta data-mint-head name=\"twitter:image:width\" content=\"1200\">\u003cmeta data-mint-head name=\"twitter:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"msapplication-config\" content=\"/mintlify-assets/_mintlify/favicons/aspex/QVudd8SD-Ga_PaCT/_generated/favicon/browserconfig.xml\">\u003cmeta data-mint-head name=\"apple-mobile-web-app-title\" content=\"Aspex\">\u003cmeta data-mint-head name=\"msapplication-TileColor\" content=\"#ec3013\">\u003clink data-mint-head rel=\"canonical\" href=\"https://aspex.mintlify.app/tools/scan-subcommands\">\u003clink data-mint-head rel=\"alternate\" type=\"application/xml\" href=\"/sitemap.xml\">\u003clink data-mint-head rel=\"alternate\" type=\"text/markdown\" href=\"/tools/scan-subcommands.md\">\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https://aspex.mintlify.app/#organization\",\"name\":\"Aspex\",\"url\":\"https://aspex.mintlify.app\",\"logo\":{\"@type\":\"ImageObject\",\"url\":\"https://mintcdn.com/aspex/AsYxeTAcjauo5hC7/logo/light.svg?fit=max\u0026auto=format\u0026n=AsYxeTAcjauo5hC7\u0026q=85\u0026s=291ecea15a099f8047decc0604202c15\"}},{\"@type\":\"WebSite\",\"@id\":\"https://aspex.mintlify.app#website\",\"name\":\"Aspex\",\"url\":\"https://aspex.mintlify.app\",\"publisher\":{\"@id\":\"https://aspex.mintlify.app/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https://aspex.mintlify.app/tools/scan-subcommands#webpage\",\"url\":\"https://aspex.mintlify.app/tools/scan-subcommands\",\"name\":\"scan subcommands\",\"description\":\"hooks, inspect, inventory, attack-paths, shadow, phantom, fix env, cron, install-hook and the rest of aspex scan.\",\"dateModified\":\"2026-09-14T09:48:04.534Z\",\"isPartOf\":{\"@id\":\"https://aspex.mintlify.app#website\"},\"breadcrumb\":{\"@id\":\"https://aspex.mintlify.app/tools/scan-subcommands#breadcrumb\"}},{\"@type\":\"BreadcrumbList\",\"@id\":\"https://aspex.mintlify.app/tools/scan-subcommands#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Commands\",\"item\":\"https://aspex.mintlify.app/tools/launcher\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"scan subcommands\",\"item\":\"https://aspex.mintlify.app/tools/scan-subcommands\"}]},{\"@type\":[\"Article\",\"TechArticle\"],\"@id\":\"https://aspex.mintlify.app/tools/scan-subcommands#article\",\"headline\":\"scan subcommands\",\"name\":\"scan subcommands\",\"description\":\"hooks, inspect, inventory, attack-paths, shadow, phantom, fix env, cron, install-hook and the rest of aspex scan.\",\"url\":\"https://aspex.mintlify.app/tools/scan-subcommands\",\"mainEntityOfPage\":{\"@id\":\"https://aspex.mintlify.app/tools/scan-subcommands#webpage\"},\"dateModified\":\"2026-09-14T09:48:04.534Z\",\"publisher\":{\"@id\":\"https://aspex.mintlify.app/#organization\"},\"isPartOf\":{\"@id\":\"https://aspex.mintlify.app#website\"}}]}\u003c/script>\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@type\":\"WebSite\",\"name\":\"Aspex\",\"creator\":{\"@type\":\"Organization\",\"name\":\"Mintlify\",\"url\":\"https://mintlify.com\"}}\u003c/script>","siteName":"Aspex","nav":{"global":null,"groups":[{"group":"Start","pages":[{"title":"Know what your agents can do. Know what they actually did.","sidebarTitle":"Introduction","href":"/introduction"},{"title":"Quickstart","href":"/quickstart"},{"title":"Common workflows","href":"/guides/common-workflows"},{"title":"Install","href":"/install"}]},{"group":"Concepts","pages":[{"title":"How Aspex reasons","href":"/concepts/how-aspex-reasons"},{"title":"Capabilities and attack paths","href":"/concepts/capabilities-and-attack-paths"},{"title":"Observed vs inferred","href":"/concepts/observed-vs-inferred"},{"title":"Score and blast radius","href":"/concepts/score-and-blast-radius"}]},{"group":"Commands","pages":[{"title":"aspex (front door)","href":"/tools/launcher"},{"title":"aspex scan","description":"Every configured server, its live tool list, the attack paths they compose, and the blast radius. Offline; nothing is sent anywhere.","href":"/tools/scan"},{"title":"scan subcommands","href":"/tools/scan-subcommands"},{"title":"aspex trace","description":"What did your agents actually do? A full audit trail from the logs your AI clients already write. No proxy, no config change.","href":"/tools/trace"},{"title":"aspex explain","href":"/tools/explain"},{"title":"aspex simulate","href":"/tools/simulate"},{"title":"lock, verify, diff","href":"/tools/change-detection"},{"title":"aspex explore","href":"/tools/explore"},{"title":"aspex tighten","href":"/tools/tighten"},{"title":"aspex bom","href":"/tools/bom"},{"title":"aspex mcp","href":"/tools/mcp"},{"title":"aspex doctor","href":"/tools/doctor"},{"title":"aspex-attack","href":"/tools/attack"}]},{"group":"Guides","pages":[{"title":"Daily Workflow","href":"/guides/daily-workflow"},{"title":"CI integration","href":"/guides/ci-integration"},{"title":"Policy, baselines and prioritization","href":"/guides/policy"},{"title":"VS Code and Cursor","href":"/guides/vscode"}]},{"group":"Reference","pages":[{"title":"Rules","href":"/reference/rules"},{"title":"Supported Clients","href":"/reference/clients"},{"title":"Agent Security Corpus","href":"/reference/corpus"},{"title":"Privacy","href":"/privacy"}]}]},"basePath":"","title":"scan subcommands - Aspex","buildId":"dpl_8LJbrAiZvr1K98WQNZXCyY5AvT34","deploymentId":"dpl_8LJbrAiZvr1K98WQNZXCyY5AvT34","dynamics":[],"chunks":[]}