Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,15 @@ sha2 = "0.11"
hex = "0.4"
getrandom = "0.4"
walkdir = "2.5"
toml_edit = { version = "0.23", default-features = false, features = ["parse"], optional = true }
dirs = "7.0"
ed25519-dalek = { version = "3.0", optional = true }
ureq = { version = "3.3", optional = true }

[features]
default = []
signing = ["ed25519-dalek"]
http = ["ureq"]
http = ["ureq", "dep:toml_edit"]
sarif = []
# Native GUI viewer (eframe/egui). Opt-in because eframe raises MSRV above the
# 1.90 baseline; default builds remain pure-CLI and MSRV-clean.
Expand Down
33 changes: 31 additions & 2 deletions README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ panic-attack exists to address this by combining:
panic-attack provides:

* **49-language static analysis** across multiple families
* **Weak point detection** (25 categories)
* **Weak point detection** (30 canonical categories; see the PA rule-ID table below)
* **Attack simulation (6 axes)**: CPU, memory, disk, network, concurrency, time
* **miniKanren logic engine** for taint analysis and cross-language reasoning
* **Signature detection** (use-after-free, deadlock, etc.)
Expand Down Expand Up @@ -187,6 +187,35 @@ Consult `man/panic-attack.1` or `panic-attack help` for every command, and use `

`just test-elixir` runs the Elixir harnesses that cover the CLI surface so documentation, help text, and automation flags stay aligned.

=== Patch Bridge CLI contract (`--features http`)

Build with `cargo build --release --features http`. Global flags are placed
before the subcommand. `bridge triage` discovers supported lockfiles
recursively under the project directory (excluding `.git`, `target`, and
vendor/build caches); use repeatable `--lockfile FILE` options to select an
explicit set instead:

[source,shell]
----
panic-attack --quiet bridge triage ./project --output bridge-report.json
panic-attack --quiet bridge triage ./project --lockfile ./project/src/rust/Cargo.lock --output bridge-report.json
----

`--output FILE` writes the JSON `BridgeReport` to that file. Without it,
`--quiet` writes JSON to stdout; normal mode prints a human-readable summary
(and writes JSON only when `--output` is supplied). A valid lockfile with zero
external dependencies produces a valid empty report; no supported lockfile
is an error. An unreadable discovered lockfile fails closed rather than
being counted as a clean scan.

`--offline` skips OSV and returns **no vulnerability data**. The JSON field
`vulnerability_data` is `offline-unavailable`; an empty `cves` array in that
report is *not* evidence of zero vulnerabilities and must never be treated as
clean. Online reports use `queried`; dependency-free projects use
`no-dependencies`. See `data/canonical-rule-ids.json` for the published,
versioned PA rule-ID/CWE/semantic-class mapping used for cross-tool
verdict-grid de-duplication.

== Integration & Groove

panic-attack can emit PanLL-friendly exports (event chains, system images, temporal diffs) per `docs/panll-export.adoc`, and it also advertises its static-analysis capability via the Gossamer groove protocol. Start the discovery endpoint with `panic-attack groove --port 7600` and check the JSON manifest by curling `http://localhost:7600/.well-known/groove` (the health endpoint sits at `/health`).
Expand All @@ -206,7 +235,7 @@ Current state: **v2.5.0**
* v2.5.5 cohort landed 2026-06-02: context-aware FP suppression via `test_context` / `comment_marker` / `ffi_kind` / `jit_context` modules — `// panic-attack: accepted` inline markers, automatic PanicPath suppression in test-only code, build.zig/build.rs auto-accept, Cranelift/LLVM/Wasm/JS JIT detection. See `PROOF-PROGRAMME.md` for the formal soundness landscape
* 0 warnings
* 38 CLI subcommands
* 49 supported languages (25 canonical weak-point categories PA001–PA025; `PA001b` SARIF subvariant collapses two allocation flavors under the same canonical rule)
* 49 supported languages (30 canonical weak-point categories PA001–PA029; `PA001b` is a distinct stable rule ID grouped with PA001 under one allocation semantic class for cross-tool de-duplication)

See link:ROADMAP.adoc[ROADMAP.adoc] for full capability breakdown and milestones.

Expand Down
295 changes: 295 additions & 0 deletions data/canonical-rule-ids.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,295 @@
{
"schema_version": "1.0.0",
"title": "panic-attack canonical rule-ID table",
"description": "Public rule ID contract matching WeakPointCategory::rule_id at source commit 410a8f821ea8297833162565b50a298f787815da. CWE links are semantic associations, not assertions of exact CWE identity; [] means no direct CWE mapping is claimed. PA001 and PA001b intentionally share a semantic class and CWE and should deduplicate for class-level verdict grids.",
"cwe_catalog": "https://cwe.mitre.org/",
"source_commit": "410a8f821ea8297833162565b50a298f787815da",
"deduplication": {
"primary_key": "semantic_class",
"preserve_rule_ids": [
"PA001",
"PA001b"
],
"note": "Preserve the canonical rule ID for audit/report display; group findings by semantic_class for cross-tool verdict-grid comparison. Apply the first matching semantic_class_overrides entry (description_prefix matches the generated finding description) and use its semantic_class and cwe_ids before falling back to the rule metadata; this keeps PA011 DOM sinks separate from eval input. CWE associations are supporting metadata, not a unique deduplication key."
},
"rules": [
{
"rule_id": "PA001",
"category": "UncheckedAllocation",
"name": "unchecked-allocation",
"cwe_ids": [
"CWE-789"
],
"semantic_class": "unbounded-memory-allocation"
},
{
"rule_id": "PA001b",
"category": "UnboundedAllocation",
"name": "unbounded-allocation",
"cwe_ids": [
"CWE-789"
],
"semantic_class": "unbounded-memory-allocation"
},
{
"rule_id": "PA002",
"category": "UnboundedLoop",
"name": "unbounded-loop",
"cwe_ids": [
"CWE-834"
],
"semantic_class": "unbounded-iteration"
},
{
"rule_id": "PA003",
"category": "BlockingIO",
"name": "blocking-io",
"cwe_ids": [
"CWE-400"
],
"semantic_class": "blocking-resource-consumption"
},
{
"rule_id": "PA004",
"category": "UnsafeCode",
"name": "unsafe-code",
"cwe_ids": [],
"semantic_class": "unsafe-memory-or-type-operation"
},
{
"rule_id": "PA005",
"category": "PanicPath",
"name": "panic-path",
"cwe_ids": [
"CWE-248"
],
"semantic_class": "unhandled-runtime-panic"
},
{
"rule_id": "PA006",
"category": "RaceCondition",
"name": "race-condition",
"cwe_ids": [
"CWE-362"
],
"semantic_class": "concurrent-access-race"
},
{
"rule_id": "PA007",
"category": "DeadlockPotential",
"name": "deadlock-potential",
"cwe_ids": [
"CWE-833"
],
"semantic_class": "concurrency-deadlock"
},
{
"rule_id": "PA008",
"category": "ResourceLeak",
"name": "resource-leak",
"cwe_ids": [
"CWE-772"
],
"semantic_class": "unreleased-resource"
},
{
"rule_id": "PA009",
"category": "CommandInjection",
"name": "command-injection",
"cwe_ids": [
"CWE-78"
],
"semantic_class": "improper-neutralization-of-command-input"
},
{
"rule_id": "PA010",
"category": "UnsafeDeserialization",
"name": "unsafe-deserialization",
"cwe_ids": [
"CWE-502"
],
"semantic_class": "unsafe-deserialization"
},
{
"rule_id": "PA011",
"category": "DynamicCodeExecution",
"name": "dynamic-code-execution",
"cwe_ids": [
"CWE-95"
],
"semantic_class": "improper-neutralization-of-eval-input",
"semantic_class_overrides": [
{
"description_prefix": "DOM manipulation (innerHTML/document.write) in ",
"semantic_class": "improper-neutralization-of-html-input",
"cwe_ids": ["CWE-79"]
},
{
"description_prefix": "dangerouslySetInnerHTML (XSS risk) in ",
"semantic_class": "improper-neutralization-of-html-input",
"cwe_ids": ["CWE-79"]
}
]
},
{
"rule_id": "PA012",
"category": "UnsafeFFI",
"name": "unsafe-ffi",
"cwe_ids": [],
"semantic_class": "unsafe-foreign-function-boundary"
},
{
"rule_id": "PA013",
"category": "AtomExhaustion",
"name": "atom-exhaustion",
"cwe_ids": [
"CWE-400"
],
"semantic_class": "unbounded-resource-consumption"
},
{
"rule_id": "PA014",
"category": "InsecureProtocol",
"name": "insecure-protocol",
"cwe_ids": [
"CWE-319",
"CWE-326"
],
"semantic_class": "insecure-communications-or-cryptography"
},
{
"rule_id": "PA015",
"category": "ExcessivePermissions",
"name": "excessive-permissions",
"cwe_ids": [
"CWE-732"
],
"semantic_class": "incorrect-permission-assignment"
},
{
"rule_id": "PA016",
"category": "PathTraversal",
"name": "path-traversal",
"cwe_ids": [
"CWE-22"
],
"semantic_class": "improper-limitation-of-pathname"
},
{
"rule_id": "PA017",
"category": "HardcodedSecret",
"name": "hardcoded-secret",
"cwe_ids": [
"CWE-798"
],
"semantic_class": "hardcoded-credential"
},
{
"rule_id": "PA018",
"category": "UncheckedError",
"name": "unchecked-error",
"cwe_ids": [
"CWE-390",
"CWE-391"
],
"semantic_class": "ignored-or-unchecked-error-condition"
},
{
"rule_id": "PA019",
"category": "InfiniteRecursion",
"name": "infinite-recursion",
"cwe_ids": [
"CWE-674"
],
"semantic_class": "uncontrolled-recursion"
},
{
"rule_id": "PA020",
"category": "UnsafeTypeCoercion",
"name": "unsafe-type-coercion",
"cwe_ids": [
"CWE-704"
],
"semantic_class": "incorrect-type-conversion"
},
{
"rule_id": "PA021",
"category": "ProofDrift",
"name": "proof-drift",
"cwe_ids": [],
"semantic_class": "unverified-or-drifted-formal-proof"
},
{
"rule_id": "PA022",
"category": "CryptoMisuse",
"name": "crypto-misuse",
"cwe_ids": [
"CWE-327",
"CWE-328",
"CWE-330"
],
"semantic_class": "cryptographic-primitive-or-validation-misuse"
},
{
"rule_id": "PA023",
"category": "SupplyChain",
"name": "supply-chain",
"cwe_ids": [
"CWE-1104",
"CWE-1395"
],
"semantic_class": "untrusted-or-vulnerable-component"
},
{
"rule_id": "PA024",
"category": "InputBoundary",
"name": "input-boundary",
"cwe_ids": [
"CWE-20",
"CWE-502"
],
"semantic_class": "unvalidated-input-at-deserialization-boundary"
},
{
"rule_id": "PA025",
"category": "MutationGap",
"name": "mutation-gap",
"cwe_ids": [],
"semantic_class": "insufficient-test-or-mutation-assurance"
},
{
"rule_id": "PA026",
"category": "LicensePolicy",
"name": "license-policy",
"cwe_ids": [],
"semantic_class": "dependency-license-policy-violation"
},
{
"rule_id": "PA027",
"category": "Advisory",
"name": "advisory",
"cwe_ids": [
"CWE-1395"
],
"semantic_class": "known-vulnerable-component-version"
},
{
"rule_id": "PA028",
"category": "BannedDep",
"name": "banned-dep",
"cwe_ids": [
"CWE-1357"
],
"semantic_class": "prohibited-or-insufficiently-trustworthy-component"
},
{
"rule_id": "PA029",
"category": "UnknownSource",
"name": "unknown-source",
"cwe_ids": [
"CWE-1357"
],
"semantic_class": "unverified-component-provenance"
}
]
}
9 changes: 9 additions & 0 deletions man/panic-attack.1
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,15 @@ Shows the man-style help text for panic-attack or one of its subcommands.
.TP
.B diagnostics [--manifest PATH]
Runs self-diagnostics that check for AI manifest validity, required artifact directories, and the presence of Hypatia/gitbot-fleet watchers. This command returns non-zero if any check fails so automation can detect regressions.
.TP
.B bridge triage [DIR] [--output FILE] [--offline] [--lockfile FILE]
Requires a binary built with `--features http`. Discovers supported lockfiles recursively beneath DIR (excluding .git, target, and vendor/build caches); `--lockfile FILE` may be repeated to select exact lockfiles. Global flags such as --quiet precede the subcommand: `panic-attack --quiet bridge triage DIR --output report.json`. `--output FILE` writes the JSON BridgeReport. A valid lockfile with zero external dependencies returns a valid empty report; no supported lockfile is an error. Unreadable discovered lockfiles fail closed.
.TP
.B bridge triage --offline
Skips the OSV vulnerability query and returns NO vulnerability data. The JSON `vulnerability_data` field is `offline-unavailable`; an empty CVE list is not a clean bill of health and must not be interpreted as one.
.TP
.B bridge status [DIR]
Displays the Patch Bridge mitigation registry for DIR.
.SH EXAMPLES
.TP
.B panic-attack help amuck
Expand Down
Loading