mirror of
https://github.com/KeygraphHQ/shannon.git
synced 2026-10-03 14:56:50 +02:00
Compare commits
37
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
954ad242dd | ||
|
|
4fbad2fde9 | ||
|
|
f649aa249a | ||
|
|
5e9bcb7aff | ||
|
|
d544bb9bd6 | ||
|
|
343ce7b2c7 | ||
|
|
81aa81c590 | ||
|
|
3bbd030fde | ||
|
|
4dee532437 | ||
|
|
492a38bb9a | ||
|
|
55a5881fe8 | ||
|
|
d7b9e6813c | ||
|
|
840fabf030 | ||
|
|
7b67302a39 | ||
|
|
1b440c853c | ||
|
|
d8a10963a8 | ||
|
|
4e145a0f3f | ||
|
|
e9cf782081 | ||
|
|
ddfd026f93 | ||
|
|
602bc27bbc | ||
|
|
0fe0c67ca5 | ||
|
|
8df9eb3db4 | ||
|
|
8bab4ccb1b | ||
|
|
098bf4be05 | ||
|
|
162db4be29 | ||
|
|
d71e550b56 | ||
|
|
321f441f4b | ||
|
|
e3c6e8df16 | ||
|
|
2469e6deac | ||
|
|
85d5cbd657 | ||
|
|
c3864c9785 | ||
|
|
f5e7143619 | ||
|
|
242f85f158 | ||
|
|
3bdcfac85d | ||
|
|
98c66e051d | ||
|
|
c33132b0ab | ||
|
|
980607c602 |
No files matched your search
+8
-4
@@ -22,15 +22,21 @@ SHANNON_AI_MODEL=anthropic:claude-sonnet-4-6
|
||||
# SHANNON_AI_MODEL=amazon-bedrock:us.anthropic.claude-opus-4-8
|
||||
|
||||
# --- Custom Base URL ---------------------------------------------------------
|
||||
# Anthropic Messages API:
|
||||
# Route through a proxy or gateway (LiteLLM, an internal endpoint).
|
||||
# Pick the block matching the API dialect your gateway speaks, and uncomment all
|
||||
# three lines. The provider prefix picks the dialect; the model id is whatever
|
||||
# name your gateway serves it under.
|
||||
|
||||
# Anthropic compatible - Anthropic Messages:
|
||||
# SHANNON_AI_API_KEY=your-gateway-key-here
|
||||
# SHANNON_AI_BASE_URL=https://llm-gateway.example.com
|
||||
# SHANNON_AI_MODEL=anthropic:claude-sonnet-4-6
|
||||
|
||||
# OpenAI Responses API:
|
||||
# OpenAI compatible - Chat Completions (default) or Responses:
|
||||
# SHANNON_AI_API_KEY=your-gateway-key-here
|
||||
# SHANNON_AI_BASE_URL=https://llm-gateway.example.com/v1
|
||||
# SHANNON_AI_MODEL=openai:gpt-5.5
|
||||
# SHANNON_AI_OPENAI_FORMAT=responses
|
||||
|
||||
# --- Other provider ----------------------------------------------------------
|
||||
# Any other provider the Pi harness supports. Name it in SHANNON_AI_MODEL and
|
||||
@@ -38,8 +44,6 @@ SHANNON_AI_MODEL=anthropic:claude-sonnet-4-6
|
||||
# and model at preflight.
|
||||
# SHANNON_AI_MODEL=openrouter:moonshotai/kimi-k3
|
||||
# SHANNON_AI_API_KEY=your-api-key-here
|
||||
# Optional: point that provider at a proxy or LLM gateway.
|
||||
# SHANNON_AI_BASE_URL=https://llm-gateway.example.com
|
||||
|
||||
# --- Misc --------------------------------------------------------------------
|
||||
# Forward /etc/hosts entries into the worker container.
|
||||
|
||||
@@ -121,8 +121,8 @@ body:
|
||||
- "xAI"
|
||||
- "AWS Bedrock"
|
||||
- "Custom base URL - Anthropic Messages"
|
||||
- "Custom base URL - OpenAI Chat Completions"
|
||||
- "Custom base URL - OpenAI Responses"
|
||||
- "Other provider (Pi catalogue)"
|
||||
validations:
|
||||
required: true
|
||||
|
||||
|
||||
@@ -165,7 +165,7 @@ Around those phases:
|
||||
- **Configuration** — YAML configs in `apps/worker/configs/` use the closed JSON Schema in `config-schema.json`. Every fresh scan runs the fixed five analysis classes; there is no public class selector. `agentic_sast.enabled` is the only public agentic-SAST setting. Finding reconciliation runs on every scan and has no public setting of its own. Config also supports authentication (MFA/TOTP), URL/code rule scoping (`rules.avoid`/`rules.focus`), `exploit`, free-form `rules_of_engagement`, and post-hoc `report` options (`min_severity`, `min_confidence`, `guidance`, and exploit-only `sarif` output via `apps/worker/src/services/sarif-renderer.ts`, on by default for exploit runs and opt out with `report.sarif: "false"`). `code_path` avoid rules are enforced via the `@gotgenes/pi-permission-system` extension: `apps/worker/src/temporal/activities.ts:syncCodePathDenyRules` writes a global `path` deny config once per workflow (`apps/worker/src/ai/pi/permission-system.ts:syncPermissionSystemConfig`), and the executor loads the extension when that config is present (`apps/worker/src/ai/pi/pi-executor.ts`), so denies fire across every tool and child `task` session. Credential resolution — local mode: env vars → `./.env`; npx mode: env vars → `~/.shannon/config.toml` (via `npx @keygraph/shannon setup`)
|
||||
- **Agentic SAST progress** — Capella runs as a child workflow, so its activities are absent from the parent's `pendingActivities` and invisible to the CLI. The child signals each stage boundary up via `capellaStageProgress` (`apps/worker/src/temporal/shared.ts`); the parent's handler validates the payload and writes the child-supplied `startedAt` and `durationMs` directly to `operationalStages['agentic-sast:<stage>']`, so both the live `getProgress` query and the terminal result carry per-stage rows. Signalling is best-effort and every failure is swallowed — a closed or unreachable parent must never fail a SAST run. `CAPELLA_STAGE_LABELS` in `apps/worker/src/ai/sast/types.ts` is the one label table, shared by the scan log and the status tree; `CAPELLA_PROGRESS_STAGES` omits `export`, which runs no model and so never becomes a row. Scans predating the signal keep the aggregate `agentic-sast` span and render as a bare phase line
|
||||
- **Prompts** — Per-phase templates in `apps/worker/prompts/` with variable substitution (`{{TARGET_URL}}`, `{{CONFIG_CONTEXT}}`). Shared partials in `apps/worker/prompts/shared/` via `apps/worker/src/services/prompt-manager.ts`, including `_code-path-rules.txt` (focus/avoid `[FILE]`/`[GLOB]` routing) and `_rules-of-engagement.txt` (free-text engagement rules). When `exploit: false`, `apps/worker/src/services/findings-renderer.ts` deterministically converts each `*_exploitation_queue.json` into a `*_findings.md` for report assembly — no LLM in the loop
|
||||
- **Agent Harness (pi)** — Uses the **pi harness** (`@earendil-works/pi-coding-agent`, requires Node ≥ 22.19) via `apps/worker/src/ai/pi/pi-executor.ts` (`runPiPrompt` → `createAgentSession`). Retry is split in `apps/worker/src/ai/pi/retry-settings.ts`: pi's agent-level loop is off so Temporal owns agent restarts, while `provider.maxRetries` stays on — pi reads the `provider` block independently of the `enabled` flag — so transport faults are absorbed in-session rather than costing a full agent re-run. `maxRetryDelayMs` is left at pi's 60s default. One model runs every phase, named by `SHANNON_AI_MODEL=<provider>:<model-id>` (default `anthropic:claude-sonnet-4-6`). `apps/worker/src/ai/models.ts` parses the spec — splitting on the **first** colon only, so Bedrock IDs keep theirs — and resolves it through pi's `ModelRuntime`. pi ships the `CredentialStore` interface but no in-memory implementation (its own reads `auth.json` from disk), so `RuntimeCredentialStore` in that file supplies one: credentials arrive as env vars in an ephemeral container and must never touch disk. `createModelRuntime(providerId, apiKey)` builds the runtime; `allowModelNetwork` stays at its default `false` so a scan never blocks on a catalog refresh. `resolveModelSelection()` is **async** because `ModelRuntime.create()` is. Any pi-ai provider id is accepted — `parseModelSpec` no longer rejects against a hardcoded list, so pi's registry is the authority (an unknown provider/model surfaces as a clear "not found in pi registry" error at preflight, which points to the browsable catalogue at `pi.dev/models` — `PI_CATALOG_URL` in `apps/worker/src/ai/models.ts`, appended to the not-found errors and shown in the setup wizard's "Other provider" hint). Four providers are **curated** (`CURATED_PROVIDERS`: `anthropic`, `openai`, `xai`, `amazon-bedrock`) with their own credential variables, config sections, and setup flows; each provider's API key env var is declared once in `PROVIDER_API_KEY_ENV` — Shannon uses each vendor's own variable name (`OPENAI_API_KEY`, `XAI_API_KEY`, …), never an invented one; Bedrock's entry is `AWS_BEARER_TOKEN_BEDROCK`, paired with `AWS_REGION`, which preflight requires separately as provider config rather than a credential. Any other provider uses the **generic** credential path: `SHANNON_AI_API_KEY` (`GENERIC_API_KEY_ENV`) supplies the key for any provider whose credential is a plain API key. Curated providers' own variables take precedence over it, and it also works as a fallback for them — Bedrock is the sole exception (it authenticates through its AWS_ variables, so the generic key never stands in for it). The CLI forwards `SHANNON_AI_API_KEY` in `COMMON_FORWARD_VARS` (it is provider-neutral, binding to whatever `SHANNON_AI_MODEL` names, so the "only one provider configured" guard counts only named credentials), and stores it under a generic `[provider]` config.toml section (`provider.api_key`). `npx @keygraph/shannon setup` exposes this as the "Other provider" option: free-text provider id + model id + key (a curated provider id is rejected there, since it has its own option). `SHANNON_AI_BASE_URL` overrides the endpoint for any provider (proxies/gateways); the credential and API dialect are unchanged. A base URL only changes the address — `resolveModel` (`apps/worker/src/ai/models.ts`) carries it onto the model descriptor and nothing else. pi's builtin `openai` provider serves a single API (Responses) and dispatches on the provider rather than `model.api`, so an `openai:` gateway run always speaks Responses; a Chat-Completions-only gateway must be reached through a completions-native provider such as `openrouter` instead. `buildEnvFlags` forwards only the selected provider's credential into the worker container. The CLI mirrors the parse rule and the provider/credential tables in `apps/cli/src/model-spec.ts` (it cannot import from the worker package); the two must stay in sync. pi ships no JSON-schema output or `Task`/`TodoWrite` built-ins, so structured queues are captured via a `submit_exploitation_queue` custom tool (`apps/worker/src/ai/queue-schemas.ts`), and `task` (child sessions scoped to `read`, `grep`, `find`, `ls`, `write`, and `bash` — no nested `task` or collector tools; `CHILD_TOOLS` in `apps/worker/src/ai/pi/task-tool.ts`) + `todo_write` (`apps/worker/src/ai/pi/session-tools.ts`) are provided as custom tools; the per-phase collectors are pi custom tools (TypeBox `defineTool` in `apps/worker/src/collectors/`). Shannon sets no thinking configuration at all — no `thinkingLevel` is passed to any `createAgentSession` call, so pi's own default applies. There is no adaptive-thinking support and no `CLAUDE_ADAPTIVE_THINKING` / `core.adaptive_thinking` setting. Browser automation via `playwright-cli` with session isolation (`-s=<session>`). TOTP generation via `generate-totp` CLI tool. Login flow template at `apps/worker/prompts/shared/login-instructions.txt` supports form, SSLine truncated
|
||||
- **Agent Harness (pi)** — Uses the **pi harness** (`@earendil-works/pi-coding-agent`, requires Node ≥ 22.19) via `apps/worker/src/ai/pi/pi-executor.ts` (`runPiPrompt` → `createAgentSession`). Retry is split in `apps/worker/src/ai/pi/retry-settings.ts`: pi's agent-level loop is off so Temporal owns agent restarts, while `provider.maxRetries` stays on — pi reads the `provider` block independently of the `enabled` flag — so transport faults are absorbed in-session rather than costing a full agent re-run. `maxRetryDelayMs` is left at pi's 60s default. One model runs every phase, named by `SHANNON_AI_MODEL=<provider>:<model-id>` (default `anthropic:claude-sonnet-4-6`). `apps/worker/src/ai/models.ts` parses the spec — splitting on the **first** colon only, so Bedrock IDs keep theirs — and resolves it through pi's `ModelRuntime`. pi ships the `CredentialStore` interface but no in-memory implementation (its own reads `auth.json` from disk), so `RuntimeCredentialStore` in that file supplies one: credentials arrive as env vars in an ephemeral container and must never touch disk. `createModelRuntime(providerId, apiKey)` builds the runtime; `allowModelNetwork` stays at its default `false` so a scan never blocks on a catalog refresh. `resolveModelSelection()` is **async** because `ModelRuntime.create()` is. Any pi-ai provider id is accepted — `parseModelSpec` no longer rejects against a hardcoded list, so pi's registry is the authority (an unknown provider/model surfaces as a clear "not found in pi registry" error at preflight, which points to the browsable catalogue at `pi.dev/models` — `PI_CATALOG_URL` in `apps/worker/src/ai/models.ts`, appended to the not-found errors and shown in the setup wizard's "Other provider" hint). Four providers are **curated** (`CURATED_PROVIDERS`: `anthropic`, `openai`, `xai`, `amazon-bedrock`) with their own credential variables, config sections, and setup flows; each provider's API key env var is declared once in `PROVIDER_API_KEY_ENV` — Shannon uses each vendor's own variable name (`OPENAI_API_KEY`, `XAI_API_KEY`, …), never an invented one; Bedrock's entry is `AWS_BEARER_TOKEN_BEDROCK`, paired with `AWS_REGION`, which preflight requires separately as provider config rather than a credential. Any other provider uses the **generic** credential path: `SHANNON_AI_API_KEY` (`GENERIC_API_KEY_ENV`) supplies the key for any provider whose credential is a plain API key. Curated providers' own variables take precedence over it, and it also works as a fallback for them — Bedrock is the sole exception (it authenticates through its AWS_ variables, so the generic key never stands in for it). The CLI forwards `SHANNON_AI_API_KEY` in `COMMON_FORWARD_VARS` (it is provider-neutral, binding to whatever `SHANNON_AI_MODEL` names, so the "only one provider configured" guard counts only named credentials), and stores it under a generic `[provider]` config.toml section (`provider.api_key`). `npx @keygraph/shannon setup` exposes this as the "Other provider" option: free-text provider id + model id + key (a curated provider id is rejected there, since it has its own option). `SHANNON_AI_BASE_URL` overrides the endpoint for any provider (proxies/gateways); the credential is unchanged. `pointAtGateway` (`apps/worker/src/ai/models.ts`) applies the one dialect change: behind a base URL, `openai` follows `SHANNON_AI_OPENAI_FORMAT` (`chat-completions` default, or `responses`). On `chat-completions` it switches the API to `openai-completions` and drops the catalogue's Responses-shaped `compat` block so pi's `detectCompat` derives completions settings; on `responses` the descriptor is unchanged but for the endpoint. `resolveGatewayFormat` rejects the variable when the provider is not `openai` or no base URL is set, since it cannot take effect there. All other providers keep their API. The CLI mirrors the accepted values in `apps/cli/src/model-spec.ts`, forwards the variable in `COMMON_FORWARD_VARS`, and maps it to `openai.format` in config.toml. `buildEnvFlags` forwards only the selected provider's credential into the worker container. The CLI mirrors the parse rule and the provider/credential tables in `apps/cli/src/model-spec.ts` (it cannot import from the worker package); the two must stay in sync. pi ships no JSON-schema output or `Task`/`TodoWrite` built-ins, so structured queues are captured via a `submit_exploitation_queue` custom tool (`apps/worker/src/ai/queue-schemas.ts`), and `task` (child sessions scoped to `read`, `grep`, `find`, `ls`, `write`, and `bash` — no nested `task` or collector tools; `CHILD_TOOLS` in `apps/worker/src/ai/pi/task-tool.ts`) + `todo_write` (`apps/worker/src/ai/pi/session-tools.ts`) are provided as custom tools; the per-phase collectors are pi custom tools (TypeBox `defineTool` in `apps/worker/src/collectors/`). Shannon sets no thinking configuration at all — no `thinkingLevel` is passed to any `createAgentSession` call, so pi's own default applies. There Line truncated
|
||||
- **Pi Credential Reuse** — `SHANNON_USE_PI_AUTH=1` opts into reusing the host's Pi login, including an `openai-codex` ChatGPT Plus/Pro subscription (`SHANNON_AI_MODEL=openai-codex:<model-id>`) or an `xai` Grok subscription (`SHANNON_AI_MODEL=xai:<model-id>`); the mechanism is provider-agnostic and works for any Pi login. `apps/cli/src/env.ts` requires `~/.pi/agent/auth.json`; `start.ts` passes its path to `spawnWorker`, which mounts only that file read-write at `/tmp/.pi/agent/auth.json`. The flag itself is not forwarded: the worker detects the file with `piAuthPresent()` and passes its path to `ModelRuntime.create`. CLI and worker API-key presence checks are skipped on this path, but the normal preflight model probe still validates the credential. The image and UID-remapping entrypoint keep `/tmp/.pi/agent` owned by `pentest` so adjacent Pi/Shannon configuration remains writable. Refreshed OAuth state is persisted to the host for subsequent scans.
|
||||
- **Audit System** — Crash-safe append-only logging in `workspaces/{hostname}_{sessionId}/`. The run directory's top level holds the human-facing report in both formats (`Security-Assessment-Report.pdf` and `Security-Assessment-Report.md`, `FINAL_REPORT_PDF_FILENAME`/`FINAL_REPORT_MD_FILENAME` in `apps/worker/src/paths.ts`); everything else — deliverables, per-agent logs, prompts, `session.json`, `workflow.log`, and browser artifacts — is nested under a hidden `.shannon/` internals dir (`INTERNAL_DIR`) so a customer sees only the report. Audit path helpers route through `generateInternalPath` (`apps/worker/src/audit/utils.ts`); the CLI nests the overlay backing dirs under the same `.shannon/` (`apps/cli/src/docker.ts`, `start.ts`). `session.json`/`workflow.log` reads use dual-read resolvers (`resolveSessionJsonPath`, `resolveRunFile`) that prefer `.shannon/` and fall back to the legacy run-root layout, so pre-restructure workspaces stay listable (`scans`/`logs`) without migration. A pre-restructure workspace cannot be resumed: `classifyWorkspaceLaunch` (`apps/cli/src/commands/start.ts`) requires `.shannon/launch.json`, and its absence fails the launch as "created by an earlier version of Shannon" before anything on disk is touched. There is no in-place migration — the workspace's files and report are left untouched, and the operator starts a new scan under a different `-w` name. The report agent writes structured findings to `report.json`, from which `report-renderer.ts` renders the assembled markdown and `report-json-adapter.ts` produces the Typst-shaped JSON that `pdf-renderer.ts` compiles into `comprehensive_security_assessment_report.pdf` using the bundled `apps/worker/templates/typst/report.typ` template (the `typst` binary is installed in the worker image). `copyReportToRunRoot` (`apps/worker/src/services/reporting.ts`) surfaces both the PDF and the markdown to the run root as `Security-Assessment-Report.pdf` and `Security-Assessment-Report.md`; the deliverables-dir copies remain as the git-checkpointed sources. PDF compilation is best-effort — a failure is logged and the run still completes. WorkflowLogger (`apps/worker/src/audit/workflow-logger.ts`) provides unified human-readable per-workflow logs, backed by LogStream (`apps/worker/src/audit/log-stream.ts`) shared stream primitive. Every combined-log line is also projected into a per-agent file under `.shannon/agents/<slug>.log` (one per pipeline agent, one per Capella stage; subagents fold into the parent's file, and a stage's concurrent sessions share its file with an inline session label). The projection boundary is `apps/worker/src/audit/actor-projection.ts` (`projectActor` maps a `TraceActor` to its combined prefix and owning file slug — slugs come only from closed fields); fan-out is best-effort and never blocks the canonical combined log. A lifecycle owner holds a `LogStream` lease per agent file (the pipeline agent's `logAgent` span, or a Capella stage activity's `try/finally`) so per-line writes ride the reference count; `CapellaStageTrace.drain()` flushes a stage's trace queue before its activity returns. The CLI tails one file with `shannon logs --agent <name>` (`--list-agents` to enumerate); the default `shannon logs` path is unchanged
|
||||
- **Deliverables** — Saved to `.shannon/deliverables/` in the target repo via the `save-deliverable` CLI script (`apps/worker/src/scripts/save-deliverable.ts`)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
> [!NOTE]
|
||||
> **[Shannon 3.0 is live](https://github.com/KeygraphHQ/shannon/discussions/439):** deeper security code analysis, more thoroughly vetted findings, a rebuilt CLI, native CI/CD, professional PDF reports, and SARIF.
|
||||
> **Shannon 3.0 is live:** deeper security code analysis, a rebuilt terminal experience, native CI/CD workflows, professional PDF reports, and SARIF—still fully open source, self-hosted, and bring-your-own-model.
|
||||
|
||||
<div align="center">
|
||||
|
||||
@@ -17,14 +17,6 @@ It analyzes your source code, identifies attack paths, and executes real exploit
|
||||
|
||||
**This repository is Shannon Open Source: the full agent, run locally from your command line.**
|
||||
|
||||
<p><strong>Launch Shannon</strong></p>
|
||||
|
||||
```bash
|
||||
npx @keygraph/shannon@latest
|
||||
```
|
||||
|
||||
<sub>The interactive launcher will guide you through setup and your first pentest.</sub>
|
||||
|
||||
---
|
||||
|
||||
<a href="https://discord.gg/9ZqQPuhJB7"><picture><source media="(prefers-color-scheme: dark)" srcset="./assets/discord_button_dark.png"><source media="(prefers-color-scheme: light)" srcset="./assets/discord_button_light.png"><img src="./assets/discord_button_light.png" height="40" alt="Join Discord"></picture></a> <a href="https://keygraph.io/"><picture><source media="(prefers-color-scheme: dark)" srcset="./assets/keygraph_button_dark.png"><source media="(prefers-color-scheme: light)" srcset="./assets/keygraph_button_light.png"><img src="./assets/keygraph_button_light.png" height="40" alt="Visit Keygraph.io"></picture></a>
|
||||
@@ -78,29 +70,19 @@ Shannon analyzes your web application's source code to identify potential attack
|
||||
|
||||
Shannon is the agent. This repository is Shannon Open Source, the standalone pentester you run yourself. The same Shannon also powers the [Keygraph platform](https://keygraph.io), Keygraph's commercial pentesting product. See [Editions](#editions) for how the two compare.
|
||||
|
||||
<a id="why-shannon-exists"></a>
|
||||
<details>
|
||||
<summary><strong>Why Shannon Exists</strong></summary>
|
||||
### Why Shannon Exists
|
||||
|
||||
Thanks to tools like Claude Code and Cursor, your team ships code non-stop. But your penetration test? That happens once a year. This creates a massive security gap. For the other 364 days, you could be unknowingly shipping vulnerabilities to production.
|
||||
|
||||
Shannon closes that gap by providing on-demand, automated penetration testing that can run against every build or release.
|
||||
|
||||
</details>
|
||||
|
||||
<a id="why-shannon"></a>
|
||||
<details>
|
||||
<summary><strong>Why "Shannon"?</strong></summary>
|
||||
### Why "Shannon"?
|
||||
|
||||
It's named after Claude Shannon, the father of information theory. At its core, pentesting is an information problem: every probe reduces uncertainty about a system's state. The best tools maximize the signal gained from every request, turning those bits of knowledge into an exploit path.
|
||||
|
||||
Also, we wanted you to be able to say, "Hey Claude, run Shannon" to find all the security flaws in your vibe-coded app.
|
||||
|
||||
</details>
|
||||
|
||||
<a id="not-a-replacement-for-human-pentesters"></a>
|
||||
<details>
|
||||
<summary><strong>Not a replacement for human pentesters</strong></summary>
|
||||
### Not a replacement for human pentesters
|
||||
|
||||
Shannon is built to work alongside expert pentesters and red teamers, not replace them. Great pentesters understand the business, chain attacks in ways nobody anticipated, and bring years of judgment that current models can't match.
|
||||
|
||||
@@ -108,13 +90,11 @@ Shannon solves a different problem: there is far more software to test than secu
|
||||
|
||||
Shannon shifts pentesting left into the software development lifecycle (SDLC). Use it to run exploitation-backed tests against staging environments and releases at the cadence they actually ship, and save expert human time for the risks that need someone who knows the organization.
|
||||
|
||||
</details>
|
||||
|
||||
## Shannon in Action
|
||||
|
||||

|
||||
|
||||
These reports are from Shannon Open Source scans of Photoview 2.4.0, one of the applications in Doyensec's comparison of Aikido and XBOW. We ran Shannon against the same application version and evaluated its results separately. Read the [Doyensec study](https://doyensec.com/resources/ComparingAIApplicationSecurityTestingPlatforms_Doyensec.pdf) and our [Shannon follow-up comparison](docs/shannon-xbow-aikido-benchmark.md) for the methodology, limitations, costs, and results.
|
||||
Penetration test reports from Shannon Open Source scanning Photoview 2.4.0. Read the [announcement][announcement] and the full [benchmark writeup][benchmark] for methodology, cost, and the comparison against Aikido and XBOW.
|
||||
|
||||
|
||||
| Model | Report | SARIF |
|
||||
@@ -123,6 +103,12 @@ These reports are from Shannon Open Source scans of Photoview 2.4.0, one of the
|
||||
| Grok 4.6 | [View report](benchmark/photoview-grok-4-6.pdf) | [SARIF](benchmark/photoview-grok-4-6.sarif) |
|
||||
| Claude Opus 5 | [View report](benchmark/photoview-opus-5.pdf) | [SARIF](benchmark/photoview-opus-5.sarif) |
|
||||
|
||||
[announcement]: https://github.com/KeygraphHQ/shannon/discussions/439
|
||||
[benchmark]: docs/shannon-xbow-aikido-benchmark.md
|
||||
|
||||
|
||||
|
||||
|
||||
## Quick Start
|
||||
|
||||
|
||||
@@ -131,7 +117,7 @@ These reports are from Shannon Open Source scans of Photoview 2.4.0, one of the
|
||||
|
||||
- **Docker**: required for the worker container.
|
||||
- **Node.js 18+**: required for the recommended `npx` workflow.
|
||||
- **AI provider credentials**: Shannon runs on Anthropic, OpenAI, xAI, AWS Bedrock, and [any other provider](docs/ai-providers.md#any-other-provider) in the harness catalogue — each of which you can point at a proxy or LLM gateway through a [custom base URL](docs/ai-providers.md#custom-base-url). You bring your own key, and Keygraph never proxies your model traffic. Shannon is provider-agnostic. See [AI providers](docs/ai-providers.md#suggested-models) for suggested model IDs.
|
||||
- **AI provider credentials**: Shannon runs on Anthropic, OpenAI, xAI, AWS Bedrock, [any other provider](docs/ai-providers.md#any-other-provider) in the harness catalogue, and any endpoint that speaks the Anthropic Messages API or the OpenAI Chat Completions or Responses API through a [custom base URL](docs/ai-providers.md#custom-base-url). You bring your own key, and Keygraph never proxies your model traffic. Shannon is provider-agnostic. See [AI providers](docs/ai-providers.md#suggested-models) for suggested model IDs.
|
||||
- **Cyber safeguards cleared with your provider**: Anthropic and OpenAI apply real-time safeguards to cyber-security workloads, which can interrupt a scan mid-run. Complete their guidance for legitimate security testers before your first run - see [AI providers](docs/ai-providers.md#cyber-safeguards-do-this-before-your-first-scan).
|
||||
|
||||
|
||||
@@ -166,17 +152,17 @@ For source builds, authenticated scans, provider-specific setup, and platform no
|
||||
|
||||
## Key Capabilities
|
||||
|
||||
- **No exploit, no report**: Reports only vulnerabilities confirmed with a reproducible proof of concept, reducing speculative scanner noise.
|
||||
- **Advanced code analysis**: Maps architecture, trust boundaries, interfaces, data flows, and critical assets before sending credible attack paths to live pentesting agents.
|
||||
- **Autonomous execution**: Runs reconnaissance, analysis, exploitation, and reporting from a single command.
|
||||
- **Live terminal experience**: Simplifies scan setup and shows agent progress and results without exposing orchestration logs.
|
||||
- **Authenticated testing**: Supports credentials, login flows, TOTP, email authentication, focus areas, and rules of engagement through configuration.
|
||||
- **OWASP-focused coverage**: Tests for exploitable injection, XSS, SSRF, broken authentication, and broken authorization.
|
||||
- **Resumable workspaces**: Resumes interrupted scans without repeating completed work.
|
||||
- **Native CI/CD integrations**: Runs through the official GitHub Action or GitLab CI/CD component, preserves artifacts, publishes findings, and gates releases on proven vulnerabilities.
|
||||
- **Multi-format reports**: Produces evidence-rich PDF and Markdown reports plus JSON and SARIF 2.1.0. SARIF is enabled by default for exploit-mode scans.
|
||||
- **Provider agnostic and BYOK**: Supports Anthropic, OpenAI, xAI, AWS Bedrock, compatible APIs and LLM gateways, and local models served through Ollama, vLLM, or LM Studio.
|
||||
- **Private by design**: Runs in your infrastructure, stores results locally, and sends model requests directly to your chosen endpoint. A local endpoint keeps data inside your environment.
|
||||
- **No exploit, no report**: Shannon includes a vulnerability only after validating it with a working, reproducible proof of concept—eliminating the speculative warnings typical of scanners.
|
||||
- **Advanced security code analysis**: Before it sends a single payload, Shannon reads the codebase and builds a picture of the application: architecture, trust boundaries, exposed interfaces, data flows, and the assets worth attacking. From there it opens targeted investigations and filters the candidates they turn up. What survives goes to the live pentesting agents.
|
||||
- **Autonomous execution**: Shannon launches reconnaissance, vulnerability analysis, exploitation, and report generation from a single command.
|
||||
- **Live terminal experience**: A rebuilt CLI makes scans easy to configure and shows agent progress and clean results without requiring operators to inspect the underlying orchestration logs.
|
||||
- **Authenticated testing**: configuration files can describe login flows, test credentials, TOTP, email-based login flows, focus areas, and rules of engagement.
|
||||
- **OWASP-focused coverage**: Shannon targets exploitable Injection, XSS, SSRF, Broken Authentication, and Broken Authorization issues.
|
||||
- **Resumable workspaces**: Shannon can resume interrupted runs without re-running completed agents.
|
||||
- **Native CI/CD integrations**: Run Shannon through the official GitHub Action or reusable GitLab CI/CD component. Preserve reports, SARIF, and logs as pipeline artifacts; publish findings into native security workflows; and gate releases only on vulnerabilities Shannon actually demonstrates.
|
||||
- **Professional and machine-readable reports**: Shannon generates evidence-rich PDF and Markdown reports plus structured JSON and SARIF 2.1.0. SARIF is enabled by default on exploit-mode scans and can be disabled with `report.sarif: "false"`.
|
||||
- **Bring your own key, provider-agnostic**: Shannon runs on Anthropic, OpenAI, xAI, AWS Bedrock, and any endpoint speaking the Anthropic Messages API or the OpenAI Chat Completions or Responses API, including self-hosted models served through Ollama, vLLM, or LM Studio and gateways such as OpenRouter and LiteLLM. You supply the credentials and choose exactly where model traffic goes. Local and self-hosted models are supported.
|
||||
- **Private by design**: Shannon runs inside your infrastructure and writes results to a local workspace. Model requests go straight to the provider or endpoint you configure, and they carry source and application context with them, so choose that endpoint deliberately. Point Shannon at a local model endpoint and nothing leaves your environment.
|
||||
|
||||
|
||||
|
||||
@@ -235,11 +221,24 @@ See the [Shannon GitHub Action documentation](https://github.com/KeygraphHQ/shan
|
||||
|
||||
## Editions
|
||||
|
||||
**Shannon Open Source** is a complete autonomous pentester, especially well suited to individual developers and small teams running focused security tests locally or in CI/CD.
|
||||
**Shannon Open Source** is the complete autonomous pentester for developers and security teams. It is optimized for fast local and CI/CD runs: understand the application, execute real attacks, and report only proven vulnerabilities.
|
||||
|
||||
**Keygraph Enterprise Platform** is for organizations that need a shared platform for continuous agentic pentesting/AppSec across many teams, repositories, and environments. It centralizes deeper analysis, vulnerability management, remediation, verification, governance, and reporting so teams do not have to assemble and maintain those workflows themselves.
|
||||
**Keygraph Enterprise Platform** turns Shannon's proof engine into an organization-wide AppSec program, adding exhaustive analysis, centralized vulnerability management, automated remediation, enterprise governance, and continuous operation at scale.
|
||||
|
||||
[Learn about the Keygraph Enterprise Platform and compare editions →](docs/keygraph-platform.md)
|
||||
|
||||
| | Shannon Open Source | Keygraph Enterprise Platform |
|
||||
| ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Best for | Local and CI/CD pentesting | Continuous AppSec across teams and repositories |
|
||||
| Security analysis | Multi-stage agentic review models architecture, trust boundaries, and data flows, filters candidate vulnerabilities, and hands the survivors to live pentesting agents | Exhaustive parsed-code agentic SAST: persistent Code Property Graphs, interprocedural source-to-sink and sanitizer modeling, cross-repository context, exploit-chain analysis, and business-logic testing |
|
||||
| Additional coverage | Not included | SCA with reachability, secrets scanning, and business-logic testing |
|
||||
| AppSec operations | N/A — standalone CLI | Canonical findings, deduplication, SLAs, analytics, automated remediation, and targeted verification |
|
||||
| Governance | N/A — local, single-operator CLI | SSO, SCIM, granular access control, APIs, and full audit logging |
|
||||
| Deployment | Self-hosted, air-gapped, BYOM, AGPL-3.0 | On-premises or air-gapped, granular model routing, commercial support |
|
||||
|
||||
|
||||
Shannon Open Source is not a trial edition. Choose Keygraph Enterprise when you need deeper analysis and a governed, closed-loop AppSec program.
|
||||
|
||||
[Explore the Keygraph Enterprise Platform →](docs/keygraph-platform.md)
|
||||
|
||||
## Architecture
|
||||
|
||||
@@ -286,7 +285,7 @@ Use these guides for operational detail:
|
||||
| --------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| [Source build and CLI commands](docs/development.md) | Cloning, building, common commands, output paths, and local development. |
|
||||
| [Configuration](docs/configuration.md) | Authenticated testing, login flows, rules of engagement, and report filters. |
|
||||
| [AI providers](docs/ai-providers.md) | Selecting the model, the supported providers (Anthropic, OpenAI, xAI, AWS Bedrock, and any other Pi-supported provider), and custom LLM gateways. |
|
||||
| [AI providers](docs/ai-providers.md) | Selecting the model, the supported providers (Anthropic, OpenAI, xAI, AWS Bedrock, and any other Pi-supported provider), and custom gateways. |
|
||||
| [Platforms and networking](docs/platforms.md) | Windows/WSL2, Linux, macOS, Docker networking, local apps, and custom hostnames. |
|
||||
| [Workspaces and resuming](docs/workspaces.md) | Naming workspaces, resuming interrupted scans, and workspace storage. |
|
||||
| [Safety and limitations](docs/safety.md) | Authorized-use requirements, non-production guidance, mutative effects, cost, and model caveats. |
|
||||
@@ -306,7 +305,7 @@ Important limitations:
|
||||
|
||||
- Shannon Open Source is tuned for fast, code-informed pentesting in everyday development and CI/CD. Exhaustive agentic SAST, broader scanner coverage, centralized governance, and full-lifecycle vulnerability management are delivered through the Keygraph Enterprise Platform.
|
||||
- Findings still require human review. LLM-generated reports can contain weakly supported or incorrect details.
|
||||
- Anthropic, OpenAI, xAI, and AWS Bedrock are built-in providers, and any other provider in the harness catalogue works too — each reachable through a custom base URL that points it at a proxy or LLM gateway. Model capability varies, and a model that does not follow Shannon's instructions or tool-use constraints reliably will produce weaker results.
|
||||
- Anthropic, OpenAI, xAI, and AWS Bedrock are built-in providers, and any Anthropic Messages API or OpenAI Chat Completions or Responses API endpoint works through a custom base URL. Model capability varies, and a model that does not follow Shannon's instructions or tool-use constraints reliably will produce weaker results.
|
||||
- A full run can take roughly 1 to 1.5 hours and may incur LLM API costs depending on model pricing and application complexity.
|
||||
- Do not scan untrusted or adversarial codebases. AI-powered tools that read source code can be exposed to prompt injection.
|
||||
|
||||
@@ -375,14 +374,14 @@ Yes. Shannon emits SARIF 2.1.0, the OASIS standard format for static analysis re
|
||||
|
||||
### Which AI providers does Shannon support?
|
||||
|
||||
Anthropic, OpenAI, xAI, and AWS Bedrock are built in and configured directly by provider ID. Beyond those, Shannon runs on any provider in the Pi harness catalogue, named the same `<provider>:<model-id>` way. Any provider can be pointed at a proxy or LLM gateway through a custom base URL, which overrides only the endpoint and keeps that provider's API dialect. Shannon uses a single unified model setting throughout a pentest.
|
||||
Anthropic, OpenAI, xAI, and AWS Bedrock are built in and configured directly by provider ID. Beyond those, Shannon runs on any endpoint that implements the Anthropic Messages API or the OpenAI Chat Completions or Responses API, reached through a custom base URL. The rule is the API format, not the vendor. Shannon uses a single unified model setting throughout a pentest.
|
||||
|
||||
### Can I run Shannon on a local or self-hosted model?
|
||||
|
||||
Shannon works with local models served through Ollama, vLLM, or LM Studio, which expose an OpenAI-compatible endpoint, as well as routers such as OpenRouter and LLM gateways such as LiteLLM. Point Shannon at the endpoint with a custom base URL. Capability varies, and a model that does not follow Shannon's instructions or tool-use constraints reliably will produce weaker pentests than a frontier model, so take this path only if you know how your chosen model behaves. See [AI providers](docs/ai-providers.md#custom-base-url).
|
||||
Shannon works with local models served through Ollama, vLLM, or LM Studio, which expose an OpenAI-compatible endpoint, as well as routers such as OpenRouter and gateways such as LiteLLM. Point Shannon at the endpoint with a custom base URL. Capability varies, and a model that does not follow Shannon's instructions or tool-use constraints reliably will produce weaker pentests than a frontier model, so take this path only if you know how your chosen model behaves. See [AI providers](docs/ai-providers.md#custom-base-url).
|
||||
|
||||
### Does Shannon actually exploit vulnerabilities, or just scan?
|
||||
|
||||
Shannon executes real exploits. It reports a finding only when it has produced a working proof-of-concept, and discards hypotheses it cannot prove. It is a pentester, not a passive scanner.
|
||||
|
||||
**Built by [Keygraph](https://keygraph.io)**
|
||||
**Built by [Keygraph](https://keygraph.io)**
|
||||
+1
-1
@@ -22,7 +22,7 @@ It analyzes your source code, identifies attack paths, and executes real exploit
|
||||
|
||||
- **Docker**: required for the worker container.
|
||||
- **Node.js 18+**: required for the recommended `npx` workflow.
|
||||
- **AI provider credentials**: Shannon runs on Anthropic, OpenAI, xAI, AWS Bedrock, and any other provider in the harness catalogue — each of which you can point at a proxy or LLM gateway through a custom base URL. You bring your own key, and Keygraph never proxies your model traffic. Shannon is provider-agnostic.
|
||||
- **AI provider credentials**: Shannon runs on Anthropic, OpenAI, xAI, AWS Bedrock, any other provider in the harness catalogue, and any endpoint that speaks the Anthropic Messages API or the OpenAI Chat Completions or Responses API through a custom base URL. You bring your own key, and Keygraph never proxies your model traffic. Shannon is provider-agnostic.
|
||||
- **Cyber safeguards cleared with your provider**: Anthropic and OpenAI apply real-time safeguards to cyber-security workloads, which can interrupt a scan mid-run. Complete their guidance for legitimate security testers before your first run.
|
||||
|
||||
### Run Shannon
|
||||
|
||||
@@ -10,7 +10,7 @@ import os from 'node:os';
|
||||
import path from 'node:path';
|
||||
import * as p from '@clack/prompts';
|
||||
import { type ShannonConfig, saveConfig } from '../config/writer.js';
|
||||
import { CURATED_PROVIDERS, type CuratedProviderId, isCuratedProvider } from '../model-spec.js';
|
||||
import { CURATED_PROVIDERS, type CuratedProviderId, isCuratedProvider, type OpenAiFormat } from '../model-spec.js';
|
||||
import { displaySplash } from '../splash.js';
|
||||
import { requireInteractive } from '../tty.js';
|
||||
import { getVersion } from '../version.js';
|
||||
@@ -22,16 +22,24 @@ const CUSTOM_BASE_URL = '__custom_base_url__';
|
||||
const OTHER_PROVIDER = '__other_provider__';
|
||||
|
||||
/**
|
||||
* API dialects reachable through the gateway route. The dialect picks the provider
|
||||
* that supplies the credential and names the wire protocol the endpoint must speak.
|
||||
* Wire formats reachable through the gateway route. The format picks the provider
|
||||
* that supplies the credential, and for OpenAI it also picks which of the two
|
||||
* OpenAI APIs Shannon calls.
|
||||
*/
|
||||
const GATEWAY_DIALECTS: readonly {
|
||||
value: string;
|
||||
label: string;
|
||||
provider: 'anthropic' | 'openai';
|
||||
format?: OpenAiFormat;
|
||||
}[] = [
|
||||
{ value: 'anthropic', label: 'Anthropic Messages', provider: 'anthropic' },
|
||||
{ value: 'openai', label: 'OpenAI Responses', provider: 'openai' },
|
||||
{
|
||||
value: 'openai-chat-completions',
|
||||
label: 'OpenAI Chat Completions',
|
||||
provider: 'openai',
|
||||
format: 'chat-completions',
|
||||
},
|
||||
{ value: 'openai-responses', label: 'OpenAI Responses', provider: 'openai', format: 'responses' },
|
||||
];
|
||||
|
||||
/** Suggested models per curated provider, best-first. Free-text entry accepts any model in the provider's catalogue. */
|
||||
@@ -70,11 +78,7 @@ export async function setup(): Promise<void> {
|
||||
{ value: 'openai' as const, label: 'OpenAI', hint: 'GPT models' },
|
||||
{ value: 'xai' as const, label: 'xAI', hint: 'Grok models' },
|
||||
{ value: 'amazon-bedrock' as const, label: 'AWS Bedrock', hint: 'Claude models via AWS' },
|
||||
{
|
||||
value: CUSTOM_BASE_URL as typeof CUSTOM_BASE_URL,
|
||||
label: 'Custom Base URL',
|
||||
hint: 'route through a proxy or LLM gateway',
|
||||
},
|
||||
{ value: CUSTOM_BASE_URL as typeof CUSTOM_BASE_URL, label: 'Custom Base URL', hint: 'your own proxy or gateway' },
|
||||
{
|
||||
value: OTHER_PROVIDER as typeof OTHER_PROVIDER,
|
||||
label: 'Other provider',
|
||||
@@ -84,21 +88,20 @@ export async function setup(): Promise<void> {
|
||||
});
|
||||
if (p.isCancel(selected)) return cancelAndExit();
|
||||
|
||||
// 2. Credentials, and any endpoint override. A base URL overrides the endpoint
|
||||
// for whichever provider is chosen — the curated gateway route names it via
|
||||
// the dialect, the "Other provider" route asks for it directly.
|
||||
const { provider, config, baseUrl } = await setupSelection(selected);
|
||||
// 2. Credentials — and, on the gateway route, the endpoint and its dialect.
|
||||
const { provider, config, gateway } = await setupSelection(selected);
|
||||
|
||||
// 3. The model that runs every phase.
|
||||
const modelId = await promptModel(provider);
|
||||
config.core = { ...config.core, model: `${provider}:${modelId}` };
|
||||
if (baseUrl) config.core = { ...config.core, base_url: baseUrl };
|
||||
if (gateway) config.core = { ...config.core, base_url: gateway.baseUrl };
|
||||
|
||||
saveConfig(config);
|
||||
|
||||
const configPath = path.join(SHANNON_HOME, 'config.toml');
|
||||
const summary = [`Provider ${provider}`, `Model ${modelId}`];
|
||||
if (baseUrl) summary.push(`Endpoint ${baseUrl}`);
|
||||
if (gateway) summary.push(`Endpoint ${gateway.baseUrl}`);
|
||||
if (gateway?.format) summary.push(`API ${gateway.format}`);
|
||||
|
||||
p.log.success(`Configuration saved to ${configPath}`);
|
||||
p.log.info(summary.join('\n'));
|
||||
@@ -108,7 +111,7 @@ export async function setup(): Promise<void> {
|
||||
interface Selection {
|
||||
provider: string;
|
||||
config: ShannonConfig;
|
||||
baseUrl?: string;
|
||||
gateway?: GatewaySetup;
|
||||
}
|
||||
|
||||
/** Resolve the provider selection into a provider id and its credential config. */
|
||||
@@ -117,7 +120,7 @@ async function setupSelection(
|
||||
): Promise<Selection> {
|
||||
if (selected === CUSTOM_BASE_URL) {
|
||||
const gateway = await setupGateway();
|
||||
return { provider: gateway.provider, config: gateway.config, baseUrl: gateway.baseUrl };
|
||||
return { provider: gateway.provider, config: gateway.config, gateway };
|
||||
}
|
||||
if (selected === OTHER_PROVIDER) {
|
||||
return setupOtherProvider();
|
||||
@@ -141,8 +144,6 @@ async function setupProvider(provider: CuratedProviderId): Promise<ShannonConfig
|
||||
/**
|
||||
* Any pi provider Shannon does not curate. The id is free text — the worker's
|
||||
* preflight validates it — and the key is stored generically as SHANNON_AI_API_KEY.
|
||||
* An optional base URL points that provider at a proxy or LLM gateway; left blank, the
|
||||
* provider's own endpoint is used.
|
||||
*/
|
||||
async function setupOtherProvider(): Promise<Selection> {
|
||||
p.log.info('Browse supported providers and models at https://pi.dev/models');
|
||||
@@ -158,13 +159,7 @@ async function setupOtherProvider(): Promise<Selection> {
|
||||
if (p.isCancel(provider)) return cancelAndExit();
|
||||
|
||||
const apiKey = await promptSecret('Enter the API key');
|
||||
const baseUrl = await promptOptionalBaseUrl();
|
||||
|
||||
return {
|
||||
provider: provider.trim(),
|
||||
config: { provider: { api_key: apiKey } },
|
||||
...(baseUrl && { baseUrl }),
|
||||
};
|
||||
return { provider: provider.trim(), config: { provider: { api_key: apiKey } } };
|
||||
}
|
||||
|
||||
// === Provider Setup Flows ===
|
||||
@@ -205,10 +200,11 @@ interface GatewaySetup {
|
||||
provider: CuratedProviderId;
|
||||
config: ShannonConfig;
|
||||
baseUrl: string;
|
||||
format?: OpenAiFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gateway route: the endpoint decides where requests go, but the dialect still
|
||||
* Gateway route: the endpoint decides where requests go, but the format still
|
||||
* picks a real provider, because that is what supplies the credential and the
|
||||
* wire protocol.
|
||||
*/
|
||||
@@ -240,9 +236,11 @@ async function setupGateway(): Promise<GatewaySetup> {
|
||||
|
||||
const authToken = await promptSecret('Enter the auth token for the endpoint');
|
||||
const config: ShannonConfig =
|
||||
provider === 'anthropic' ? { anthropic: { api_key: authToken } } : { openai: { api_key: authToken } };
|
||||
provider === 'anthropic'
|
||||
? { anthropic: { api_key: authToken } }
|
||||
: { openai: { api_key: authToken, ...(dialect.format && { format: dialect.format }) } };
|
||||
|
||||
return { provider, config, baseUrl };
|
||||
return { provider, config, baseUrl, ...(dialect.format && { format: dialect.format }) };
|
||||
}
|
||||
|
||||
// === Model Selection ===
|
||||
@@ -310,31 +308,6 @@ async function promptModelId(provider: string, placeholder?: string): Promise<st
|
||||
|
||||
// === Helpers ===
|
||||
|
||||
/**
|
||||
* Optional endpoint override. Empty input means the provider's default endpoint;
|
||||
* any value must be a valid URL.
|
||||
*/
|
||||
async function promptOptionalBaseUrl(): Promise<string | undefined> {
|
||||
const baseUrl = await p.text({
|
||||
message: 'Custom base URL (optional, leave blank for the provider default)',
|
||||
placeholder: 'https://llm-gateway.example.com',
|
||||
validate: (value) => {
|
||||
const trimmed = value?.trim();
|
||||
if (!trimmed) return undefined;
|
||||
try {
|
||||
new URL(trimmed);
|
||||
} catch {
|
||||
return 'Must be a valid URL';
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
});
|
||||
if (p.isCancel(baseUrl)) return cancelAndExit();
|
||||
|
||||
const trimmed = baseUrl?.trim();
|
||||
return trimmed ? trimmed : undefined;
|
||||
}
|
||||
|
||||
async function promptSecret(message: string): Promise<string> {
|
||||
const value = await p.password({
|
||||
message,
|
||||
|
||||
@@ -40,8 +40,9 @@ const CONFIG_MAP: readonly ConfigMapping[] = [
|
||||
{ env: 'ANTHROPIC_API_KEY', toml: 'anthropic.api_key', type: 'string' },
|
||||
{ env: 'CLAUDE_CODE_OAUTH_TOKEN', toml: 'anthropic.oauth_token', type: 'string' },
|
||||
|
||||
// OpenAI
|
||||
// OpenAI — format picks the wire API a gateway serves
|
||||
{ env: 'OPENAI_API_KEY', toml: 'openai.api_key', type: 'string' },
|
||||
{ env: 'SHANNON_AI_OPENAI_FORMAT', toml: 'openai.format', type: 'string' },
|
||||
|
||||
// xAI
|
||||
{ env: 'XAI_API_KEY', toml: 'xai.api_key', type: 'string' },
|
||||
|
||||
@@ -10,7 +10,7 @@ import { getConfigFile } from '../home.js';
|
||||
export interface ShannonConfig {
|
||||
core?: { model?: string; base_url?: string };
|
||||
anthropic?: { api_key?: string; oauth_token?: string };
|
||||
openai?: { api_key?: string };
|
||||
openai?: { api_key?: string; format?: string };
|
||||
xai?: { api_key?: string };
|
||||
bedrock?: { region?: string; token?: string };
|
||||
/** Generic credential for any provider Shannon does not curate. Maps to SHANNON_AI_API_KEY. */
|
||||
|
||||
@@ -30,6 +30,7 @@ import {
|
||||
const COMMON_FORWARD_VARS = [
|
||||
'SHANNON_AI_MODEL',
|
||||
'SHANNON_AI_BASE_URL',
|
||||
'SHANNON_AI_OPENAI_FORMAT',
|
||||
// Opt-in debug flag: when set, the worker persists a bounded, sanitized snippet of a failed
|
||||
// provider turn's raw error message to error.log. Off by default; provider prose stays out of
|
||||
// durable state unless an operator deliberately enables it for a diagnosis.
|
||||
|
||||
@@ -52,6 +52,15 @@ export const PROVIDER_CREDENTIAL_HINT: Readonly<Record<CuratedProviderId, string
|
||||
/** Model used when SHANNON_AI_MODEL is unset. */
|
||||
export const DEFAULT_MODEL_SPEC = 'anthropic:claude-sonnet-4-6';
|
||||
|
||||
/**
|
||||
* Values SHANNON_AI_OPENAI_FORMAT accepts, selecting the wire format an
|
||||
* OpenAI-compatible gateway serves. Mirrors OPENAI_FORMATS in
|
||||
* apps/worker/src/ai/models.ts; the worker validates and applies it.
|
||||
*/
|
||||
export const OPENAI_FORMATS = ['chat-completions', 'responses'] as const;
|
||||
|
||||
export type OpenAiFormat = (typeof OPENAI_FORMATS)[number];
|
||||
|
||||
export interface ModelSpec {
|
||||
providerId: string;
|
||||
modelId: string;
|
||||
|
||||
@@ -78,6 +78,42 @@ export const DEFAULT_MODEL_SPEC = 'anthropic:claude-sonnet-4-6';
|
||||
/** Browsable pi model catalogue — the source of valid `<provider>:<model-id>` ids. */
|
||||
export const PI_CATALOG_URL = 'https://pi.dev/models';
|
||||
|
||||
/**
|
||||
* Wire formats an OpenAI-compatible gateway may serve, named by
|
||||
* SHANNON_AI_OPENAI_FORMAT. Only `openai` offers a choice: every other supported
|
||||
* provider has exactly one API in pi's registry.
|
||||
*/
|
||||
export const OPENAI_FORMATS = {
|
||||
'chat-completions': 'openai-completions',
|
||||
responses: 'openai-responses',
|
||||
} as const;
|
||||
|
||||
export type OpenAiFormat = keyof typeof OPENAI_FORMATS;
|
||||
|
||||
/** Format assumed when a gateway is configured but no format is named. */
|
||||
export const DEFAULT_OPENAI_FORMAT: OpenAiFormat = 'chat-completions';
|
||||
|
||||
function isOpenAiFormat(value: string): value is OpenAiFormat {
|
||||
return value in OPENAI_FORMATS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read SHANNON_AI_OPENAI_FORMAT. Unset returns undefined, which lets the caller
|
||||
* distinguish "not configured" from an explicit choice and reject the variable
|
||||
* where it has no effect.
|
||||
*/
|
||||
export function resolveOpenAiFormat(): OpenAiFormat | undefined {
|
||||
const raw = process.env.SHANNON_AI_OPENAI_FORMAT?.trim();
|
||||
if (!raw) return undefined;
|
||||
|
||||
if (!isOpenAiFormat(raw)) {
|
||||
throw new Error(
|
||||
`SHANNON_AI_OPENAI_FORMAT must be one of: ${Object.keys(OPENAI_FORMATS).join(', ')}. Got "${raw}".`,
|
||||
);
|
||||
}
|
||||
return raw;
|
||||
}
|
||||
|
||||
export interface ModelSpec {
|
||||
providerId: string;
|
||||
modelId: string;
|
||||
@@ -220,6 +256,26 @@ export interface ModelSelection {
|
||||
readonly credentialSource: 'api-key' | 'pi-auth' | 'ambient';
|
||||
}
|
||||
|
||||
/**
|
||||
* Point a model descriptor at a gateway.
|
||||
*
|
||||
* An OpenAI gateway may serve either wire format, named by
|
||||
* SHANNON_AI_OPENAI_FORMAT and defaulting to chat completions, which is what
|
||||
* most gateway software exposes. Switching to completions also drops the stored
|
||||
* `compat` block: the catalogue's block describes Responses, and an explicit
|
||||
* entry outranks pi's `detectCompat`, so leaving it would apply Responses
|
||||
* settings to a completions request. Staying on Responses keeps it, since it
|
||||
* then describes the format in use. Every other provider has one API and only
|
||||
* changes address.
|
||||
*/
|
||||
function pointAtGateway(model: Model<Api>, providerId: string, baseUrl: string, format: OpenAiFormat): Model<Api> {
|
||||
if (providerId !== 'openai') return { ...model, baseUrl };
|
||||
if (format === 'responses') return { ...model, baseUrl, api: OPENAI_FORMATS.responses };
|
||||
|
||||
const { compat: _responsesCompat, ...withoutCompat } = model;
|
||||
return { ...withoutCompat, baseUrl, api: OPENAI_FORMATS['chat-completions'] };
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve a model against a runtime.
|
||||
*
|
||||
@@ -237,17 +293,44 @@ export function resolveModel(
|
||||
providerId: string,
|
||||
modelId: string,
|
||||
baseUrl: string | undefined,
|
||||
format: OpenAiFormat = DEFAULT_OPENAI_FORMAT,
|
||||
): Model<Api> | undefined {
|
||||
const found = modelRuntime.getModel(providerId, modelId);
|
||||
if (found) {
|
||||
return baseUrl ? { ...found, baseUrl } : found;
|
||||
return baseUrl ? pointAtGateway(found, providerId, baseUrl, format) : found;
|
||||
}
|
||||
if (!baseUrl) return undefined;
|
||||
|
||||
const reference = modelRuntime.getModels(providerId)[0];
|
||||
if (!reference) return undefined;
|
||||
|
||||
return { ...reference, id: modelId, name: modelId, baseUrl };
|
||||
return pointAtGateway({ ...reference, id: modelId, name: modelId }, providerId, baseUrl, format);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate SHANNON_AI_OPENAI_FORMAT against the rest of the configuration and
|
||||
* return the format a gateway run should use.
|
||||
*
|
||||
* The variable only reaches a request when both an OpenAI model and a gateway
|
||||
* are configured, so it is rejected outside that combination rather than
|
||||
* silently ignored.
|
||||
*/
|
||||
export function resolveGatewayFormat(providerId: string, baseUrl: string | undefined): OpenAiFormat {
|
||||
const configured = resolveOpenAiFormat();
|
||||
if (!configured) return DEFAULT_OPENAI_FORMAT;
|
||||
|
||||
if (providerId !== 'openai') {
|
||||
throw new Error(
|
||||
`SHANNON_AI_OPENAI_FORMAT applies to openai models only, but SHANNON_AI_MODEL selects "${providerId}". ` +
|
||||
`${providerId} serves a single API, so there is no format to choose.`,
|
||||
);
|
||||
}
|
||||
if (!baseUrl) {
|
||||
throw new Error(
|
||||
'SHANNON_AI_OPENAI_FORMAT applies to gateway runs only. Set SHANNON_AI_BASE_URL, or unset the format to call OpenAI directly.',
|
||||
);
|
||||
}
|
||||
return configured;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -257,11 +340,12 @@ export function resolveModel(
|
||||
export async function resolveModelSelection(): Promise<ModelSelection> {
|
||||
const { providerId, modelId } = resolveModelSpec();
|
||||
const credentials = resolveProviderCredentials(providerId);
|
||||
const format = resolveGatewayFormat(providerId, credentials.baseUrl);
|
||||
|
||||
const mountedPiAuth = piAuthPresent();
|
||||
const modelRuntime = await createModelRuntime(providerId, credentials.apiKey);
|
||||
|
||||
const model = resolveModel(modelRuntime, providerId, modelId, credentials.baseUrl);
|
||||
const model = resolveModel(modelRuntime, providerId, modelId, credentials.baseUrl, format);
|
||||
if (!model) {
|
||||
throw new Error(
|
||||
`Model not found in pi registry: provider="${providerId}" model="${modelId}". Browse valid providers and models at ${PI_CATALOG_URL}.`,
|
||||
|
||||
@@ -40,8 +40,10 @@ import {
|
||||
createModelRuntime,
|
||||
GENERIC_API_KEY_ENV,
|
||||
type ModelSpec,
|
||||
type OpenAiFormat,
|
||||
PI_CATALOG_URL,
|
||||
piAuthPresent,
|
||||
resolveGatewayFormat,
|
||||
resolveModel,
|
||||
resolveModelSpec,
|
||||
resolveProviderCredentials,
|
||||
@@ -327,7 +329,24 @@ async function validateCredentials(logger: ActivityLogger): Promise<Result<void,
|
||||
// needs one API key.
|
||||
const credentials = resolveProviderCredentials(spec.providerId);
|
||||
|
||||
// With a mounted pi auth.json the env-var checks don't apply — step 4's probe validates it.
|
||||
// 3. Wire format for an OpenAI gateway. Rejects a format named where it cannot
|
||||
// take effect, rather than letting the run proceed on the wrong API.
|
||||
let format: OpenAiFormat;
|
||||
try {
|
||||
format = resolveGatewayFormat(spec.providerId, credentials.baseUrl);
|
||||
} catch (error) {
|
||||
return err(
|
||||
new PentestError(
|
||||
error instanceof Error ? error.message : String(error),
|
||||
'config',
|
||||
false,
|
||||
{ providerId: spec.providerId },
|
||||
ErrorCode.AUTH_FAILED,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// With a mounted pi auth.json the env-var checks don't apply — step 5's probe validates it.
|
||||
const isBedrock = spec.providerId === 'amazon-bedrock';
|
||||
const missing =
|
||||
isBedrock && !piAuthPresent() ? ['AWS_REGION', 'AWS_BEARER_TOKEN_BEDROCK'].filter((n) => !process.env[n]) : [];
|
||||
@@ -343,12 +362,12 @@ async function validateCredentials(logger: ActivityLogger): Promise<Result<void,
|
||||
);
|
||||
}
|
||||
|
||||
// 3. Model must exist in the registry, for every provider — Bedrock IDs are the
|
||||
// 4. Model must exist in the registry, for every provider — Bedrock IDs are the
|
||||
// easiest to get wrong, since region prefixes and version suffixes differ per
|
||||
// model (`us.anthropic.claude-opus-5` exists, bare `anthropic.` does not).
|
||||
// A custom endpoint is exempt: it may serve models under its own names.
|
||||
const modelRuntime = await createModelRuntime(spec.providerId, credentials.apiKey);
|
||||
const baseModel = resolveModel(modelRuntime, spec.providerId, spec.modelId, credentials.baseUrl);
|
||||
const baseModel = resolveModel(modelRuntime, spec.providerId, spec.modelId, credentials.baseUrl, format);
|
||||
if (!baseModel) {
|
||||
return err(
|
||||
new PentestError(
|
||||
@@ -366,10 +385,10 @@ async function validateCredentials(logger: ActivityLogger): Promise<Result<void,
|
||||
);
|
||||
}
|
||||
if (credentials.baseUrl && spec.providerId === 'openai') {
|
||||
logger.info(`Gateway API: ${baseModel.api}`);
|
||||
logger.info(`Gateway API: ${format} (${baseModel.api})`);
|
||||
}
|
||||
|
||||
// 4. One real request, so a credential the account cannot use fails here
|
||||
// 5. One real request, so a credential the account cannot use fails here
|
||||
// rather than partway through the run. Bedrock included: pi resolves the
|
||||
// bearer token from the primed credential and the region from AWS_REGION,
|
||||
// so the probe exercises the same auth path the scan will.
|
||||
|
||||
+26
-14
@@ -28,9 +28,8 @@ Shannon forwards only the selected provider's credential into the scan container
|
||||
Shannon accepts any provider and model present in the Pi harness catalogue. Browse them at [pi.dev/models](https://pi.dev/models).
|
||||
|
||||
```bash
|
||||
export SHANNON_AI_API_KEY=your-api-key # the provider's key — or the gateway's when a base URL is set
|
||||
export SHANNON_AI_MODEL=openrouter:moonshotai/kimi-k3 # <provider>:<model-id>
|
||||
export SHANNON_AI_BASE_URL=https://llm-gateway.example.com # optional: route through a proxy or LLM gateway
|
||||
export SHANNON_AI_API_KEY=your-api-key # the provider's API key
|
||||
export SHANNON_AI_MODEL=openrouter:moonshotai/kimi-k3 # <provider>:<model-id>
|
||||
```
|
||||
|
||||
This path covers providers whose credential is a single API key. Providers that need more than that are not currently supported.
|
||||
@@ -49,7 +48,7 @@ Review each vendor's guidance and complete the verification or enrollment they a
|
||||
- Anthropic - [Real-time cyber safeguards on Claude Opus and Sonnet](https://support.claude.com/en/articles/14604842-real-time-cyber-safeguards-on-claude-opus-and-sonnet)
|
||||
- OpenAI - [Cyber](https://chatgpt.com/cyber)
|
||||
|
||||
This applies to the Anthropic and OpenAI providers, including when either is reached through an LLM gateway. Bedrock serves Claude models and is subject to Anthropic's safeguards as well.
|
||||
This applies to the Anthropic and OpenAI providers, including when either is reached through a gateway. Bedrock serves Claude models and is subject to Anthropic's safeguards as well.
|
||||
|
||||
## Suggested models
|
||||
|
||||
@@ -105,16 +104,17 @@ Bedrock uses bearer-token authentication only. IAM access keys, session tokens,
|
||||
|
||||
## Custom base URL
|
||||
|
||||
`SHANNON_AI_BASE_URL` routes model traffic through a proxy or LLM gateway instead of the provider's default endpoint — an LLM gateway such as LiteLLM, a regional endpoint, or any other host you choose. It is a plain endpoint override: it changes only *where* requests go. The provider half of `SHANNON_AI_MODEL` still decides which credential is sent and which API dialect is spoken, and that is unchanged by the base URL.
|
||||
To route model traffic through your own infrastructure — a corporate proxy, an LLM gateway such as LiteLLM, or a regional endpoint — set a base URL alongside your normal model selection. The provider half of `SHANNON_AI_MODEL` decides which key is sent and which API Shannon speaks, so pick the one your gateway serves:
|
||||
|
||||
This works for **any** provider, curated or not. The one rule is that a provider's dialect is fixed, so the endpoint you point at must speak that provider's dialect:
|
||||
| Gateway serves | Model prefix | API key |
|
||||
| --- | --- | --- |
|
||||
| Anthropic Messages | `anthropic:` | `SHANNON_AI_API_KEY` |
|
||||
| OpenAI Chat Completions | `openai:` | `SHANNON_AI_API_KEY` |
|
||||
| OpenAI Responses | `openai:` + `SHANNON_AI_OPENAI_FORMAT=responses` | `SHANNON_AI_API_KEY` |
|
||||
|
||||
| Provider prefix | Dialect the endpoint must speak |
|
||||
| --- | --- |
|
||||
| `anthropic:` | Anthropic Messages |
|
||||
| `openai:` | OpenAI Responses |
|
||||
The model ID is whatever name your gateway serves it under; it does not have to exist in Shannon's catalogue.
|
||||
|
||||
Anthropic Messages LLM gateway:
|
||||
Anthropic Messages:
|
||||
|
||||
```bash
|
||||
export SHANNON_AI_API_KEY=sk-ant-...
|
||||
@@ -122,7 +122,7 @@ export SHANNON_AI_MODEL=anthropic:claude-sonnet-4-6
|
||||
export SHANNON_AI_BASE_URL=https://llm-gateway.example.com
|
||||
```
|
||||
|
||||
OpenAI Responses LLM gateway:
|
||||
OpenAI Chat Completions:
|
||||
|
||||
```bash
|
||||
export SHANNON_AI_API_KEY=sk-...
|
||||
@@ -130,7 +130,19 @@ export SHANNON_AI_MODEL=openai:gpt-5.6-sol
|
||||
export SHANNON_AI_BASE_URL=https://llm-gateway.example.com/v1
|
||||
```
|
||||
|
||||
`npx @keygraph/shannon setup` configures a base URL two ways: **Custom Base URL** covers the common Anthropic Messages and OpenAI Responses LLM gateways, and **Other provider** takes any provider ID plus an optional base URL of its own.
|
||||
`SHANNON_AI_MODEL` is always `<provider>:<model-id>`, gateway or not.
|
||||
|
||||
OpenAI is the one provider serving two APIs, so a gateway run picks one:
|
||||
|
||||
```bash
|
||||
export SHANNON_AI_OPENAI_FORMAT=responses # default: chat-completions
|
||||
```
|
||||
|
||||
Chat Completions is the default because that is what most gateway software exposes. Set `responses` for a gateway that passes the Responses API through — it preserves reasoning state between turns, which Chat Completions cannot. `openai:gpt-5` with no base URL always calls OpenAI's Responses API directly.
|
||||
|
||||
The variable is rejected in preflight where it cannot take effect: with a non-`openai` model, since Anthropic, xAI, and Bedrock each serve one API, and with no `SHANNON_AI_BASE_URL`, since a direct OpenAI run is always Responses.
|
||||
|
||||
`npx @keygraph/shannon setup` covers this under **Custom Base URL**, which asks which API your gateway serves and configures the matching provider for you.
|
||||
|
||||
## OpenAI Codex (ChatGPT Plus/Pro subscription)
|
||||
|
||||
@@ -197,7 +209,7 @@ These instructions apply only to `shannon-v1`.
|
||||
|
||||
Checks run before a scan starts, so mistakes fail immediately rather than partway through a run:
|
||||
|
||||
- **Provider and model ID** — validated against the Pi harness catalogue. An unknown provider or model ID fails preflight with a pointer to [pi.dev/models](https://pi.dev/models). A custom base URL exempts the model ID, since an LLM gateway may serve its own names.
|
||||
- **Provider and model ID** — validated against the Pi harness catalogue. An unknown provider or model ID fails preflight with a pointer to [pi.dev/models](https://pi.dev/models). A custom base URL exempts the model ID, since a gateway may serve its own names.
|
||||
- **Credential presence** — validated for the selected provider, or read from Pi when `SHANNON_USE_PI_AUTH=1`.
|
||||
- **Credential validity** — one minimal request against the model the scan will use, so a rejected key, an exhausted quota, or a model the account cannot reach fails before any agent runs. Bedrock included: its bearer token and region go through the same probe.
|
||||
|
||||
|
||||
+88
-56
@@ -1,101 +1,133 @@
|
||||
# Keygraph Enterprise Platform
|
||||
|
||||
Shannon 3.0 is an open-source pentester. It reads your source, maps routes and data flows, runs real attacks against a live target, and writes PDF and SARIF reports. It runs locally, in CI, or air-gapped with your own model. Shannon Open Source is a complete pentester, not a trial edition.
|
||||
Shannon 3.0 makes advanced, code-informed autonomous pentesting available to everyone. The open-source CLI maps routes and data flows, understands application architecture, executes real attacks, and produces PDF and SARIF results—locally, in CI/CD, or fully air-gapped with your own model.
|
||||
|
||||
Keygraph Enterprise runs an enterprise-hardened fork of Shannon continuously across hundreds of repositories and adds what a security team needs around it: audit-depth static analysis on a parsed code graph, business-logic testing, SCA and secrets scanning, one deduplicated record per vulnerability across scans and scanners, generated fixes, fix verification, and SSO, RBAC, and audit logs. It is for security teams that own vulnerability management across many engineering teams and need one place to triage, assign, fix, and verify.
|
||||
The **Keygraph Enterprise Platform** is the commercial AppSec operating system for organizations that need to run that process continuously across many repositories, teams, and environments. It adds exhaustive agentic SAST, business-logic and source-to-sink analysis, broader scanner coverage, centralized vulnerability management, automated remediation and targeted verification, enterprise governance, and organization-wide reporting.
|
||||
|
||||
Both editions are BYOK. Keygraph never receives your source and never proxies model traffic, open source or commercial. Shannon Open Source runs from your machine or CI runner. Keygraph Enterprise deploys as a platform inside your cloud or data center, including fully air-gapped.
|
||||
> Shannon Open Source is a complete autonomous pentester, not a trial edition. Keygraph Enterprise is for teams that need greater analysis depth, shared control, and a closed-loop vulnerability-management program.
|
||||
|
||||
## Shannon Open Source vs. Keygraph Enterprise
|
||||
## Who It Is For
|
||||
|
||||
| | Shannon Open Source | Keygraph Enterprise |
|
||||
| --- | --- | --- |
|
||||
| Best for | Developers and teams running repository-level pentests locally or in CI | Security organizations running continuous AppSec across many teams and repositories |
|
||||
| Code analysis | Agent pass over architecture, entry points, and data flows to seed the pentest, sized to finish inside a CI run | Persistent code property graph plus a long-running analysis harness with interprocedural taint, sanitizer modeling, cross-repo context, exploit chains, and multi-pass review |
|
||||
| Pentesting | On-demand, source-aware white-box pentesting with optional authenticated testing, focused on injection, XSS, SSRF, broken authentication, and broken authorization, with proof by exploitation | Enterprise-hardened Shannon fork run continuously, with grey-box and black-box targets and business-logic invariant testing |
|
||||
| SCA and secrets | Not included | SCA with reachability and secrets scanning including history |
|
||||
| Findings | Per-run PDF, Markdown, JSON, and SARIF, with SARIF ingestion into GitHub code scanning | One record per vulnerability per repo across scans and scanners, plus ownership, SLAs, dashboards, and audit evidence |
|
||||
| Fixes and verification | Not included | Fix PRs with verification by re-analysis and exploit replay, with no full rescan required |
|
||||
| CI/CD and source control | GitHub Action and GitLab CI component for pull-request, release, and scheduled runs, with gates on `status: exploited` | GitHub, GitLab, Azure DevOps, and Bitbucket with organization-wide policy and centrally managed integrations |
|
||||
| Deployment and models | Runs locally or on a CI runner with BYOK to any Anthropic- or OpenAI-compatible endpoint or local model | Deployed in your AWS, GCP, Azure, or on-prem environment. Customer-hosted services and stored platform data remain inside your environment. Model requests go directly to the provider, private endpoint, gateway, or local model you configure. A local model supports fully disconnected deployments |
|
||||
| Governance, license, support | AGPL-3.0 and community support | SSO, SCIM, RBAC, and audit logs, plus a commercial license, enterprise support, and SOC 2 Type II |
|
||||
Keygraph Enterprise is designed for organizations that need to:
|
||||
|
||||
## How it fits your pipeline
|
||||
- continuously test hundreds or thousands of repositories, services, applications, and APIs;
|
||||
- combine agentic pentesting, SAST, SCA, secrets, and business-logic findings in one system;
|
||||
- enforce security policy in GitHub Actions, GitLab CI, and enterprise delivery pipelines;
|
||||
- give developers one canonical, actionable record for each vulnerability instead of duplicate scanner alerts;
|
||||
- assign owners, apply SLAs, track status, and measure risk and remediation performance across the organization;
|
||||
- generate fixes and verify them without rerunning an entire scan;
|
||||
- enforce enterprise identity, authorization, audit, and API-access controls; and
|
||||
- deploy fully on-premises or air-gapped with customer-controlled models, keys, and routing.
|
||||
|
||||
1. Scans run on pull requests, releases, and a schedule against repositories in GitHub, GitLab, Azure DevOps, or Bitbucket.
|
||||
2. Pipelines gate on exploited severity. A code-analysis hypothesis never fails a build.
|
||||
3. Findings from every scanner and every run land as one record per vulnerability per repository, with an owner and an SLA. The same finding across ten runs is one record, not ten alerts.
|
||||
4. From a finding, Keygraph opens a fix PR into your normal review flow.
|
||||
5. Verification confirms the fix against the changed code and the original exploit. No full rescan is required.
|
||||
## Close the Entire AppSec Loop
|
||||
|
||||
## What is different technically
|
||||
The platform connects discovery, triage, remediation, and verification in one continuous workflow:
|
||||
|
||||
### Static analysis on a code property graph
|
||||
1. **Analyze** every repository with exhaustive agentic SAST and complementary scanners.
|
||||
2. **Prove** exploitability with source-aware white-box, black-box, and grey-box pentesting.
|
||||
3. **Normalize and deduplicate** results into a canonical finding per vulnerability and repository.
|
||||
4. **Prioritize and assign** using severity, reachability, exploit evidence, ownership, policy, and business context.
|
||||
5. **Remediate** with an AI-authored patch delivered as a reviewable pull request.
|
||||
6. **Verify** the specific fix with deterministic checks and adversarial agent reasoning—without rerunning the full scan.
|
||||
7. **Track and govern** status, exceptions, SLAs, audit history, trends, and compliance evidence until closure.
|
||||
|
||||
Shannon Open Source's code analysis is sized to finish inside a CI run: agents read the repository, map the attack surface, and hand candidates to the pentester. Enterprise is built for depth instead. It first parses each repository into a persistent code property graph, then runs an analysis harness derived from one built for long-running vulnerability audits, heavily adapted to query the graph rather than read files. The harness decomposes the application into risk, taint-flow, framework, and specialist tasks and supports longer-running audit workflows beyond typical CI job windows.
|
||||
## Exhaustive Agentic SAST
|
||||
|
||||
On the graph, it performs:
|
||||
Shannon 3.0's open-source code analysis runs a multi-stage agentic workflow. It models application architecture, trust boundaries, exposed interfaces, and data flows, opens targeted investigations, reviews the candidates they turn up, and hands the survivors to live pentesting agents. That workflow is built for practical local and CI/CD runs.
|
||||
|
||||
- Interprocedural taint tracking across functions, files, fields, containers, and framework request lifecycles.
|
||||
- Source, sink, and sanitizer modeling that records where validation, encoding, or authorization changes a path.
|
||||
- Cross-repository modeling of services, entry points, and trust boundaries.
|
||||
- Semantic deduplication of variants of the same defect, and exploit-chain analysis for combinations with higher impact than any single issue.
|
||||
- Multiple review passes per candidate, checking the agent's claim against the graph and available deployment and configuration context. Candidates that cannot be substantiated are not reported.
|
||||
The Enterprise engine goes further, for audits at organization scale. It parses the codebase and builds persistent structural context before agents start reasoning about security:
|
||||
|
||||
### Business-logic invariants
|
||||
- **Repository and architecture modeling** identifies services, frameworks, entry points, assets, trust boundaries, and cross-repository relationships.
|
||||
- **Interprocedural call and data-flow analysis** traces values across functions, files, fields, containers, and framework-managed request lifecycles.
|
||||
- **Source, sink, and sanitizer modeling** follows untrusted input to sensitive operations and records where validation, encoding, authorization, or other controls alter the path.
|
||||
- **Threat-driven decomposition** breaks large applications into risk, taint-flow, framework, and specialist analysis tasks so deep scans remain systematic.
|
||||
- **Exhaustive adversarial verification** challenges candidates across multiple review passes, weighing structural evidence against what the agents found, then asks whether each one is viable in the application's production configuration.
|
||||
- **Semantic deduplication and exploit-chain analysis** consolidate variants of the same defect and identify combinations whose impact is greater than any isolated issue.
|
||||
- **Business-logic invariant testing** derives rules the code is supposed to preserve—such as tenant isolation, workflow order, approval limits, balances, and state transitions—then agents fuzz those invariants for application-specific flaws.
|
||||
|
||||
Shannon Open Source focuses on injection, XSS, SSRF, and broken authentication and authorization. Enterprise adds testing for the bugs that do not fit a vulnerability class: it derives invariants the application is supposed to hold (tenant isolation, workflow ordering, approval limits, balance conservation, state transitions) and tests them against the running application. This is where application-specific vulnerabilities live and where pattern-based SAST often provides little or no signal.
|
||||
|
||||
### Proof by exploitation
|
||||
|
||||
The pentesting engine is a hardened fork of Shannon with the same rule: a pentest finding requires a working exploit. No exploit, no finding. Enterprise stores the exploit and replays it later to verify the fix.
|
||||
|
||||
SCA prioritizes vulnerable dependencies that application code actually reaches. Secrets scanning covers current source and repository history.
|
||||
The result is broad vulnerability hunting with precise paths back to the relevant code, not a flat list of pattern matches.
|
||||
|
||||
<p align="center">
|
||||
<img src="../assets/keygraph-platform/agentic-sast-results.png" alt="Keygraph Enterprise findings grouped into business-logic issues, point issues, and secrets" width="100%">
|
||||
<img src="../assets/keygraph-platform/agentic-sast-results.png" alt="Keygraph Enterprise SAST results grouped into business-logic issues, point issues, and secrets" width="100%">
|
||||
</p>
|
||||
|
||||
## Findings
|
||||
## Complete Application-Security Coverage
|
||||
|
||||
Shannon Open Source hands you a report per scan. Enterprise dedupes across runs and across scanners, deterministically and semantically, into one record per vulnerability per repository. Each record carries evidence, source location, severity, scan history, status, owner, resolution, and last-verified state.
|
||||
Agentic SAST and pentesting work alongside additional first-class scanners:
|
||||
|
||||
Workflows cover assignment, triage, false-positive and risk-acceptance decisions, and SLA policies with escalation and aging. Dashboards report open risk, coverage, new versus resolved, SLA compliance, and MTTR, exportable as evidence for customers and auditors.
|
||||
- **SCA with reachability** prioritizes vulnerable dependencies that application code can actually reach.
|
||||
- **Full secrets scanning** detects credentials, tokens, and keys across source and repository history.
|
||||
- **Agentic pentesting** correlates code intelligence with live application behavior and attempts real exploitation. The core rule remains: no exploit, no pentest finding.
|
||||
|
||||
Findings still require human review. Enterprise's extra review passes reduce weakly supported findings, but they do not eliminate them.
|
||||
## One System of Record for Every Finding
|
||||
|
||||
Keygraph ingests results from every analysis source, correlates them, and maintains one canonical finding per vulnerability per repository. Security and engineering teams work from the same record, with evidence, source location, severity, scan history, status, assignee, resolution, and last-verification state.
|
||||
|
||||
The vulnerability-management layer provides:
|
||||
|
||||
- deterministic and semantic deduplication across scans and scanners;
|
||||
- ownership, assignment, triage, false-positive, risk-acceptance, and resolution workflows;
|
||||
- SLA policies, escalation, aging, and last-verified tracking;
|
||||
- bidirectional developer-workflow integrations and APIs;
|
||||
- dashboards for risk, coverage, trends, new versus resolved findings, SLA compliance, and MTTR; and
|
||||
- exportable evidence for customers, auditors, and compliance programs.
|
||||
|
||||
<p align="center">
|
||||
<img src="../assets/keygraph-platform/canonical-findings.png" alt="Keygraph Enterprise findings inventory with severity, status, source, and verification filters" width="100%">
|
||||
<img src="../assets/keygraph-platform/canonical-findings.png" alt="Keygraph Enterprise canonical findings inventory with severity, status, source, and verification filters" width="100%">
|
||||
</p>
|
||||
|
||||
### Fix and verify
|
||||
## Remediate, Then Verify the Fix
|
||||
|
||||
From a finding, Keygraph generates a patch scoped to that finding and opens a pull request. It never commits to a protected branch.
|
||||
From an individual finding, a user can ask Keygraph to produce a focused patch. The remediation agent reasons from the root cause and evidence, changes only the required code, and opens a pull request into the existing review process. It does not silently apply fixes to a protected branch.
|
||||
|
||||
<p align="center">
|
||||
<img src="../assets/keygraph-platform/automated-remediation.png" alt="Keygraph Enterprise remediation workflow for generating a fix and opening a pull request" width="100%">
|
||||
</p>
|
||||
|
||||
Verification re-analyzes the changed code and, for pentest findings, replays the original exploit against the patched target. The verdict comes from deterministic checks plus a review pass, without rerunning the full scan.
|
||||
After a patch is available, targeted verification re-analyzes the affected code and, for dynamic pentest findings, re-tests the original proof of concept against the target. Deterministic checks and adversarial agent reasoning produce a clear verdict without the cost and delay of rerunning the entire scan.
|
||||
|
||||
<p align="center">
|
||||
<img src="../assets/keygraph-platform/targeted-verification.png" alt="Keygraph Enterprise finding-verification workflow" width="100%">
|
||||
<img src="../assets/keygraph-platform/targeted-verification.png" alt="Keygraph Enterprise targeted finding-verification workflow" width="100%">
|
||||
</p>
|
||||
|
||||
## Deployment and access control
|
||||
## Enterprise Governance and Integrations
|
||||
|
||||
Keygraph Enterprise deploys entirely inside your AWS, GCP, Azure, or on-prem environment, including networks with no internet egress. There is no Keygraph-operated control plane. Customer-hosted services and stored platform data remain inside your environment for the life of the deployment.
|
||||
Keygraph is built for shared operation across security, platform, and engineering teams:
|
||||
|
||||
Model access is BYOK and BYOM. Route workloads to Anthropic, OpenAI, xAI, or Bedrock, a private cloud endpoint, your own gateway such as LiteLLM with your routing and policy applied, or local models on vLLM or Ollama. Model requests go directly to the endpoint you configure. Keygraph never receives or proxies them. A local model supports a fully disconnected deployment.
|
||||
|
||||
Access control: SAML/OIDC SSO, SCIM, roles with repository-scoped visibility (RBAC, plus attribute and relationship rules where needed), full audit log, scoped API keys.
|
||||
- SAML 2.0 or OIDC single sign-on and SCIM provisioning;
|
||||
- organization, team, and user management;
|
||||
- built-in and custom roles with granular relationship-, attribute-, and role-based authorization (ReBAC, ABAC, and RBAC);
|
||||
- repository, pentest-profile, scanner, finding, and administration boundaries;
|
||||
- full audit logging and scoped API keys;
|
||||
- integrations with source control, CI/CD, ticketing, chat, and cloud environments; and
|
||||
- commercial support and enterprise onboarding.
|
||||
|
||||
<p align="center">
|
||||
<img src="../assets/keygraph-platform/enterprise-access-control.png" alt="Keygraph Enterprise roles and repository visibility controls" width="100%">
|
||||
<img src="../assets/keygraph-platform/enterprise-access-control.png" alt="Keygraph Enterprise granular roles and repository visibility controls" width="100%">
|
||||
</p>
|
||||
|
||||
Keygraph maintains a SOC 2 Type II audit. The report is available to customers under NDA.
|
||||
## On-Premises, Air-Gapped, and Customer-Controlled AI
|
||||
|
||||
Keygraph Enterprise can run entirely inside your AWS, GCP, Azure, or on-premises environment, including networks with no public internet access. Deployments can keep source code, scan artifacts, findings, prompts, completions, and model traffic inside your security perimeter.
|
||||
|
||||
AI access is bring-your-own-key and bring-your-own-model. Organizations can route workloads through approved commercial providers, private cloud endpoints, an internal LLM gateway, or local open-source models, with granular routing and policy controlled by the customer. There is no requirement for a Keygraph-operated control plane or model proxy.
|
||||
|
||||
Keygraph maintains a SOC 2 Type II audit and makes the current report available to customers under appropriate confidentiality terms.
|
||||
|
||||
## Shannon 3.0 vs. Keygraph Enterprise
|
||||
|
||||
| | Shannon Open Source | Keygraph Enterprise Platform |
|
||||
| --- | --- | --- |
|
||||
| Best for | Individual developers and teams running pentests locally or in CI/CD | Security organizations running a continuous AppSec program across many teams and repositories |
|
||||
| Code analysis | Multi-stage agentic review maps architecture, trust boundaries, exposed interfaces, and data flows, filters candidate vulnerabilities, and hands the survivors to live pentesting agents | Exhaustive parsed-code analysis: persistent Code Property Graphs, interprocedural source-to-sink and sanitizer modeling, cross-repository context, exploit-chain analysis, and business-logic invariant testing |
|
||||
| Pentesting | On-demand, source-aware white-box pentesting with proof by exploitation | Continuous white-box, black-box, and grey-box pentesting across applications and environments |
|
||||
| Additional AppSec coverage | Not included | SCA with reachability, secrets scanning, and business-logic invariant testing |
|
||||
| CI/CD and reporting | Official GitHub Action and reusable GitLab CI/CD component; staging, release, merge-request, and scheduled pentests; demonstrated-vulnerability severity gates; PDF, Markdown, JSON, SARIF, artifacts, and native security-workflow ingestion | Organization-wide policies and gating, centrally managed integrations, canonical findings, dashboards, analytics, SLA tracking, and compliance evidence |
|
||||
| Automated remediation and verification | Not included | AI-authored pull requests with targeted code and exploit verification |
|
||||
| Enterprise governance | N/A — local, single-operator CLI | SSO, SCIM, teams, ReBAC/ABAC/RBAC, audit logs, API keys, ownership, and SLA policies |
|
||||
| Deployment and AI | Self-hosted, no telemetry, BYOM, and fully air-gapped with a local model | Fully on-premises or air-gapped, BYOK/BYOM, and granular routing through customer-controlled gateways |
|
||||
| License and support | AGPL-3.0 and community support | Commercial license, enterprise support, and SOC 2 Type II controls |
|
||||
|
||||
## Talk to Keygraph
|
||||
|
||||
Visit [keygraph.io](https://keygraph.io), book a [demo](https://cal.com/team/keygraph/shannon-pro), or email [shannon@keygraph.io](mailto:shannon@keygraph.io).
|
||||
Visit [keygraph.io](https://keygraph.io), book a [Keygraph demo](https://cal.com/team/keygraph/shannon-pro), or contact [shannon@keygraph.io](mailto:shannon@keygraph.io).
|
||||
@@ -132,6 +132,6 @@ Exploit-mode scans write SARIF 2.1.0 by default, so findings land in GitHub code
|
||||
|
||||
### Conclusion
|
||||
|
||||
The complaint we hear most from CISOs about AI pentesting is the economics of continuous coverage. Doyensec paid $4,000 for each Aikido and XBOW assessment. At that benchmark price, treating 5,000 repositories as separate assessment targets would imply $20 million for one portfolio-wide pass before enterprise discounts. That may be viable for selective annual testing, but not for testing an entire portfolio at release cadence.
|
||||
The complaint we hear most from CISOs about AI pentesting isn't accuracy, it's cost. At $4,000 a scan, the tier Doyensec purchased from both XBOW and Aikido, the math works for an annual check-up. It doesn't work per release, and teams are shipping faster than ever. A large enterprise with 5,000 repositories is looking at $20 million for a single pass.
|
||||
|
||||
Shannon v3 running DeepSeek v4 Flash scanned Photoview for $6.10 and caught the same critical SQL injection the $4,000 platforms caught. At the observed DeepSeek model cost, 5,000 equivalent Shannon runs would consume about $30,500 in model tokens, before infrastructure and operational costs. The cheap model doesn't catch everything: our Claude Opus 5 run found 6 of 7 patched vulnerabilities to DeepSeek's 3, for $115. These results support a tiered testing strategy in which teams use lower-cost models for frequent scans and more capable models for periodic deeper assessments, making continuous pentesting economically practical.
|
||||
Shannon v3 running DeepSeek v4 Flash scanned Photoview for $6.10 and caught the same critical SQL injection the $4,000 platforms caught. The same enterprise would pay about $30,000 for that pass. The cheap model doesn't catch everything: our Claude Opus 5 run found 6 of 7 patched vulnerabilities to DeepSeek's 3, for $115. That's the point. Run the cheap model on every change, run the heavy one on a schedule, and continuous pentesting becomes affordable.
|
||||
+32
-20
@@ -97,7 +97,7 @@ Sample penetration test reports from intentionally vulnerable applications, prod
|
||||
|
||||
- **Docker**: required for the worker container.
|
||||
- **Node.js 18+**: required for the recommended `npx` workflow.
|
||||
- **AI provider credentials**: Shannon runs on Anthropic, OpenAI, xAI, AWS Bedrock, and [any other provider](docs/ai-providers.md#any-other-provider) in the harness catalogue — each of which you can point at a proxy or LLM gateway through a [custom base URL](docs/ai-providers.md#custom-base-url). You bring your own key, and Keygraph never proxies your model traffic. Shannon is provider-agnostic. See [AI providers](docs/ai-providers.md#suggested-models) for suggested model IDs.
|
||||
- **AI provider credentials**: Shannon runs on Anthropic, OpenAI, xAI, AWS Bedrock, [any other provider](docs/ai-providers.md#any-other-provider) in the harness catalogue, and any endpoint that speaks the Anthropic Messages API or the OpenAI Chat Completions or Responses API through a [custom base URL](docs/ai-providers.md#custom-base-url). You bring your own key, and Keygraph never proxies your model traffic. Shannon is provider-agnostic. See [AI providers](docs/ai-providers.md#suggested-models) for suggested model IDs.
|
||||
- **Cyber safeguards cleared with your provider**: Anthropic and OpenAI apply real-time safeguards to cyber-security workloads, which can interrupt a scan mid-run. Complete their guidance for legitimate security testers before your first run - see [AI providers](docs/ai-providers.md#cyber-safeguards-do-this-before-your-first-scan).
|
||||
|
||||
|
||||
@@ -141,7 +141,7 @@ For source builds, authenticated scans, provider-specific setup, and platform no
|
||||
- **Resumable workspaces**: Shannon can resume interrupted runs without re-running completed agents.
|
||||
- **Native CI/CD integrations**: Run Shannon through the official GitHub Action or reusable GitLab CI/CD component. Preserve reports, SARIF, and logs as pipeline artifacts; publish findings into native security workflows; and gate releases only on vulnerabilities Shannon actually demonstrates.
|
||||
- **Professional and machine-readable reports**: Shannon generates evidence-rich PDF and Markdown reports plus structured JSON and SARIF 2.1.0. SARIF is enabled by default on exploit-mode scans and can be disabled with `report.sarif: "false"`.
|
||||
- **Bring your own key, provider-agnostic**: Shannon runs on Anthropic, OpenAI, xAI, AWS Bedrock, and any other provider in the Pi harness catalogue, each of which you can point at a proxy or LLM gateway with a custom base URL — including self-hosted models served through Ollama, vLLM, or LM Studio and LLM gateways such as OpenRouter and LiteLLM. You supply the credentials and choose exactly where model traffic goes. Local and self-hosted models are supported.
|
||||
- **Bring your own key, provider-agnostic**: Shannon runs on Anthropic, OpenAI, xAI, AWS Bedrock, and any endpoint speaking the Anthropic Messages API or the OpenAI Chat Completions or Responses API, including self-hosted models served through Ollama, vLLM, or LM Studio and gateways such as OpenRouter and LiteLLM. You supply the credentials and choose exactly where model traffic goes. Local and self-hosted models are supported.
|
||||
- **Private by design**: Shannon runs inside your infrastructure and writes results to a local workspace. Model requests go straight to the provider or endpoint you configure, and they carry source and application context with them, so choose that endpoint deliberately. Point Shannon at a local model endpoint and nothing leaves your environment.
|
||||
|
||||
|
||||
@@ -265,7 +265,7 @@ Use these guides for operational detail:
|
||||
| --------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| [Source build and CLI commands](docs/development.md) | Cloning, building, common commands, output paths, and local development. |
|
||||
| [Configuration](docs/configuration.md) | Authenticated testing, login flows, rules of engagement, and report filters. |
|
||||
| [AI providers](docs/ai-providers.md) | Selecting the model, the supported providers (Anthropic, OpenAI, xAI, AWS Bedrock, and any other Pi-supported provider), and custom LLM gateways. |
|
||||
| [AI providers](docs/ai-providers.md) | Selecting the model, the supported providers (Anthropic, OpenAI, xAI, AWS Bedrock, and any other Pi-supported provider), and custom gateways. |
|
||||
| [Platforms and networking](docs/platforms.md) | Windows/WSL2, Linux, macOS, Docker networking, local apps, and custom hostnames. |
|
||||
| [Workspaces and resuming](docs/workspaces.md) | Naming workspaces, resuming interrupted scans, and workspace storage. |
|
||||
| [Safety and limitations](docs/safety.md) | Authorized-use requirements, non-production guidance, mutative effects, cost, and model caveats. |
|
||||
@@ -285,7 +285,7 @@ Important limitations:
|
||||
|
||||
- Shannon Open Source is tuned for fast, code-informed pentesting in everyday development and CI/CD. Exhaustive agentic SAST, broader scanner coverage, centralized governance, and full-lifecycle vulnerability management are delivered through the Keygraph Enterprise Platform.
|
||||
- Findings still require human review. LLM-generated reports can contain weakly supported or incorrect details.
|
||||
- Anthropic, OpenAI, xAI, and AWS Bedrock are built-in providers, and any other provider in the harness catalogue works too — each reachable through a custom base URL that points it at a proxy or LLM gateway. Model capability varies, and a model that does not follow Shannon's instructions or tool-use constraints reliably will produce weaker results.
|
||||
- Anthropic, OpenAI, xAI, and AWS Bedrock are built-in providers, and any Anthropic Messages API or OpenAI Chat Completions or Responses API endpoint works through a custom base URL. Model capability varies, and a model that does not follow Shannon's instructions or tool-use constraints reliably will produce weaker results.
|
||||
- A full run can take roughly 1 to 1.5 hours and may incur LLM API costs depending on model pricing and application complexity.
|
||||
- Do not scan untrusted or adversarial codebases. AI-powered tools that read source code can be exposed to prompt injection.
|
||||
|
||||
@@ -346,11 +346,11 @@ Yes. Shannon emits SARIF 2.1.0, the OASIS standard format for static analysis re
|
||||
|
||||
### Which AI providers does Shannon support?
|
||||
|
||||
Anthropic, OpenAI, xAI, and AWS Bedrock are built in and configured directly by provider ID. Beyond those, Shannon runs on any provider in the Pi harness catalogue, named the same `<provider>:<model-id>` way. Any provider can be pointed at a proxy or LLM gateway through a custom base URL, which overrides only the endpoint and keeps that provider's API dialect. Shannon uses a single unified model setting throughout a pentest.
|
||||
Anthropic, OpenAI, xAI, and AWS Bedrock are built in and configured directly by provider ID. Beyond those, Shannon runs on any endpoint that implements the Anthropic Messages API or the OpenAI Chat Completions or Responses API, reached through a custom base URL. The rule is the API format, not the vendor. Shannon uses a single unified model setting throughout a pentest.
|
||||
|
||||
### Can I run Shannon on a local or self-hosted model?
|
||||
|
||||
Shannon works with local models served through Ollama, vLLM, or LM Studio, which expose an OpenAI-compatible endpoint, as well as routers such as OpenRouter and LLM gateways such as LiteLLM. Point Shannon at the endpoint with a custom base URL. Capability varies, and a model that does not follow Shannon's instructions or tool-use constraints reliably will produce weaker pentests than a frontier model, so take this path only if you know how your chosen model behaves. See [AI providers](docs/ai-providers.md#custom-base-url).
|
||||
Shannon works with local models served through Ollama, vLLM, or LM Studio, which expose an OpenAI-compatible endpoint, as well as routers such as OpenRouter and gateways such as LiteLLM. Point Shannon at the endpoint with a custom base URL. Capability varies, and a model that does not follow Shannon's instructions or tool-use constraints reliably will produce weaker pentests than a frontier model, so take this path only if you know how your chosen model behaves. See [AI providers](docs/ai-providers.md#custom-base-url).
|
||||
|
||||
### Does Shannon actually exploit vulnerabilities, or just scan?
|
||||
|
||||
@@ -747,9 +747,8 @@ Shannon forwards only the selected provider's credential into the scan container
|
||||
Shannon accepts any provider and model present in the Pi harness catalogue. Browse them at [pi.dev/models](https://pi.dev/models).
|
||||
|
||||
```bash
|
||||
export SHANNON_AI_API_KEY=your-api-key # the provider's key — or the gateway's when a base URL is set
|
||||
export SHANNON_AI_MODEL=openrouter:moonshotai/kimi-k3 # <provider>:<model-id>
|
||||
export SHANNON_AI_BASE_URL=https://llm-gateway.example.com # optional: route through a proxy or LLM gateway
|
||||
export SHANNON_AI_API_KEY=your-api-key # the provider's API key
|
||||
export SHANNON_AI_MODEL=openrouter:moonshotai/kimi-k3 # <provider>:<model-id>
|
||||
```
|
||||
|
||||
This path covers providers whose credential is a single API key. Providers that need more than that are not currently supported.
|
||||
@@ -768,7 +767,7 @@ Review each vendor's guidance and complete the verification or enrollment they a
|
||||
- Anthropic - [Real-time cyber safeguards on Claude Opus and Sonnet](https://support.claude.com/en/articles/14604842-real-time-cyber-safeguards-on-claude-opus-and-sonnet)
|
||||
- OpenAI - [Cyber](https://chatgpt.com/cyber)
|
||||
|
||||
This applies to the Anthropic and OpenAI providers, including when either is reached through an LLM gateway. Bedrock serves Claude models and is subject to Anthropic's safeguards as well.
|
||||
This applies to the Anthropic and OpenAI providers, including when either is reached through a gateway. Bedrock serves Claude models and is subject to Anthropic's safeguards as well.
|
||||
|
||||
## Suggested models
|
||||
|
||||
@@ -824,16 +823,17 @@ Bedrock uses bearer-token authentication only. IAM access keys, session tokens,
|
||||
|
||||
## Custom base URL
|
||||
|
||||
`SHANNON_AI_BASE_URL` routes model traffic through a proxy or LLM gateway instead of the provider's default endpoint — an LLM gateway such as LiteLLM, a regional endpoint, or any other host you choose. It is a plain endpoint override: it changes only *where* requests go. The provider half of `SHANNON_AI_MODEL` still decides which credential is sent and which API dialect is spoken, and that is unchanged by the base URL.
|
||||
To route model traffic through your own infrastructure — a corporate proxy, an LLM gateway such as LiteLLM, or a regional endpoint — set a base URL alongside your normal model selection. The provider half of `SHANNON_AI_MODEL` decides which key is sent and which API Shannon speaks, so pick the one your gateway serves:
|
||||
|
||||
This works for **any** provider, curated or not. The one rule is that a provider's dialect is fixed, so the endpoint you point at must speak that provider's dialect:
|
||||
| Gateway serves | Model prefix | API key |
|
||||
| --- | --- | --- |
|
||||
| Anthropic Messages | `anthropic:` | `SHANNON_AI_API_KEY` |
|
||||
| OpenAI Chat Completions | `openai:` | `SHANNON_AI_API_KEY` |
|
||||
| OpenAI Responses | `openai:` + `SHANNON_AI_OPENAI_FORMAT=responses` | `SHANNON_AI_API_KEY` |
|
||||
|
||||
| Provider prefix | Dialect the endpoint must speak |
|
||||
| --- | --- |
|
||||
| `anthropic:` | Anthropic Messages |
|
||||
| `openai:` | OpenAI Responses |
|
||||
The model ID is whatever name your gateway serves it under; it does not have to exist in Shannon's catalogue.
|
||||
|
||||
Anthropic Messages LLM gateway:
|
||||
Anthropic Messages:
|
||||
|
||||
```bash
|
||||
export SHANNON_AI_API_KEY=sk-ant-...
|
||||
@@ -841,7 +841,7 @@ export SHANNON_AI_MODEL=anthropic:claude-sonnet-4-6
|
||||
export SHANNON_AI_BASE_URL=https://llm-gateway.example.com
|
||||
```
|
||||
|
||||
OpenAI Responses LLM gateway:
|
||||
OpenAI Chat Completions:
|
||||
|
||||
```bash
|
||||
export SHANNON_AI_API_KEY=sk-...
|
||||
@@ -849,7 +849,19 @@ export SHANNON_AI_MODEL=openai:gpt-5.6-sol
|
||||
export SHANNON_AI_BASE_URL=https://llm-gateway.example.com/v1
|
||||
```
|
||||
|
||||
`npx @keygraph/shannon setup` configures a base URL two ways: **Custom Base URL** covers the common Anthropic Messages and OpenAI Responses LLM gateways, and **Other provider** takes any provider ID plus an optional base URL of its own.
|
||||
`SHANNON_AI_MODEL` is always `<provider>:<model-id>`, gateway or not.
|
||||
|
||||
OpenAI is the one provider serving two APIs, so a gateway run picks one:
|
||||
|
||||
```bash
|
||||
export SHANNON_AI_OPENAI_FORMAT=responses # default: chat-completions
|
||||
```
|
||||
|
||||
Chat Completions is the default because that is what most gateway software exposes. Set `responses` for a gateway that passes the Responses API through — it preserves reasoning state between turns, which Chat Completions cannot. `openai:gpt-5` with no base URL always calls OpenAI's Responses API directly.
|
||||
|
||||
The variable is rejected in preflight where it cannot take effect: with a non-`openai` model, since Anthropic, xAI, and Bedrock each serve one API, and with no `SHANNON_AI_BASE_URL`, since a direct OpenAI run is always Responses.
|
||||
|
||||
`npx @keygraph/shannon setup` covers this under **Custom Base URL**, which asks which API your gateway serves and configures the matching provider for you.
|
||||
|
||||
## OpenAI Codex (ChatGPT Plus/Pro subscription)
|
||||
|
||||
@@ -916,7 +928,7 @@ These instructions apply only to `shannon-v1`.
|
||||
|
||||
Checks run before a scan starts, so mistakes fail immediately rather than partway through a run:
|
||||
|
||||
- **Provider and model ID** — validated against the Pi harness catalogue. An unknown provider or model ID fails preflight with a pointer to [pi.dev/models](https://pi.dev/models). A custom base URL exempts the model ID, since an LLM gateway may serve its own names.
|
||||
- **Provider and model ID** — validated against the Pi harness catalogue. An unknown provider or model ID fails preflight with a pointer to [pi.dev/models](https://pi.dev/models). A custom base URL exempts the model ID, since a gateway may serve its own names.
|
||||
- **Credential presence** — validated for the selected provider, or read from Pi when `SHANNON_USE_PI_AUTH=1`.
|
||||
- **Credential validity** — one minimal request against the model the scan will use, so a rejected key, an exhausted quota, or a model the account cannot reach fails before any agent runs. Bedrock included: its bearer token and region go through the same probe.
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ Use this file as the concise entry point for AI agents and LLMs reading this rep
|
||||
|
||||
- [Development](docs/development.md): Source-build workflow, common CLI commands, repository paths, and output locations.
|
||||
- [Configuration](docs/configuration.md): Authenticated testing, login flows, rules of engagement, report filters, credential precedence, and rate-limit settings.
|
||||
- [AI Providers](docs/ai-providers.md): Anthropic, OpenAI, xAI, AWS Bedrock, any other Pi-supported provider, and custom LLM gateway setup.
|
||||
- [AI Providers](docs/ai-providers.md): Anthropic, OpenAI, xAI, AWS Bedrock, any other Pi-supported provider, and custom gateway setup.
|
||||
- [Platforms and Networking](docs/platforms.md): Windows/WSL2, Linux, macOS, Docker networking, local applications, and custom hostnames.
|
||||
- [Workspaces and Resuming](docs/workspaces.md): Workspace storage, naming, resuming interrupted scans, and examples.
|
||||
- [Safety and Limitations](docs/safety.md): Authorized-use requirements, non-production guidance, mutative effects, model caveats, scope limits, cost, and performance.
|
||||
|
||||
Reference in new issue
Block a user