Skip to content

Context Awareness

hyperpolymath edited this page Jun 2, 2026 · 1 revision

v2.5.5 Context-Awareness

panic-attack v2.5.5 reduces false-positives by classifying every finding's location and letting operators opt-into known-OK findings with an inline marker. Four foundation modules + one analyzer wire-up pass landed 2026-06-02 PM via #102, #105, #106, #107, and #110.

Operator quick-start — the panic-attack: accepted marker

Most v2.5.5 use is operator-side: when you've manually reviewed a finding and decided it's a non-issue (intentional unsafe, or in a context the scanner can't see), drop a marker comment ON or DIRECTLY ABOVE the line:

let x: fn(i64) -> i64 = unsafe { std::mem::transmute(raw_ptr) };
// panic-attack: accepted - Cranelift JIT dispatch, audited 2026-06-02

let y = config.parse().unwrap(); // panic-attack: accepted - guaranteed by caller

The reason text after accepted is preserved verbatim — audit consumers can render it.

Cross-language comment leaders:

Leader Languages Position
// C / C++ / Rust / Go / Java / JS / TS / Zig / Swift / Kotlin mid-line + start-of-line
/// / //! Rust doc-comments mid-line + start-of-line
# Python / Ruby / Shell / Perl / TOML / YAML start-of-line only (mid-line uses incl. attributes)
-- Haskell / Idris / SQL / Lua / Ada / Elm start-of-line only (mid-line decrement)
; (or ;;) Lisp / Scheme / Racket / Clojure / Assembly start-of-line only (mid-line stmt terminator)
% Erlang / Prolog / MATLAB / LaTeX start-of-line only (mid-line modulo)

Why the start-of-line restriction for non-C-style: ;, %, --, # have valid non-comment uses inside expressions. Only // is unambiguous mid-line.

Recognised spellings: panic-attack: accepted, panicattack: accepted, panic_attack: accepted, and the no-space variants. Case-insensitive on the prefix.

Automatic context-aware suppression

Three categories fire automatically without operator action — the analyzer-side wire-up at assail::apply_v255_context_suppression:

What's auto-suppressed Trigger Module
PanicPath in test code test_context::classify(file) returns TestOnly or Doc test_context
UnsafeFFI in build system FfiKind::classify_by_path(file) returns BuildSystem (build.zig / build.rs) ffi_kind
UnsafeFFI in test mocks FfiKind::classify_by_path(file) returns TestMock (tests/mocks/ / _stub) ffi_kind

All other findings pass through with WeakPoint.test_context metadata populated so downstream audit consumers can render the classification regardless of suppression.

test_context

Path-based test detection across languages. The classifier (src/test_context.rs) returns one of TestContext::Production / TestContext::TestOnly / TestContext::Doc.

Recognised test paths:

Rust:        tests/foo.rs, src/foo_test.rs, src/foo_tests.rs, benches/bench.rs
Python:      tests/test_foo.py, src/test_foo.py, src/foo_test.py, tests.py
Go:          foo_test.go
JavaScript:  foo.test.ts, foo.spec.js, __tests__/foo.tsx
Julia:       test/runtests.jl, test/Foo.jl
Zig:         src/main_test.zig, tests/foo.zig
Elixir:      foo_test.exs, test/foo_test.exs
Docs:        docs/examples/foo.rs, foo.example.py    (classified as Doc, not TestOnly)

Content-based promotion: a file at a production-looking path is also classified TestOnly if its content contains any of:

  • use ExUnit.Case (Elixir)
  • class FooTest(unittest.TestCase) (Python unittest)
  • @pytest.fixture + def test_ (Python pytest)
  • using Test + @testset (Julia)

comment_marker

Inline suppression marker parser (src/comment_marker.rs). Two public functions:

  • scan_markers(content) -> Vec<AcceptedMarker> — find all markers
  • is_suppressed_at(content, line) -> Option<AcceptedMarker> — check whether a specific line is suppressed (same line or immediately preceding line)

A marker on the NEXT line does NOT suppress (avoids "the comment below is unrelated" ambiguity).

ffi_kind

UnsafeFFI (PA013) subtyped (src/ffi_kind.rs):

Kind Trigger paths Default suppression
BuildSystem build.zig, build.rs, build/cmake/, build.cargo/ Yes — build-time only
RuntimeAbi bindings/, ffi/, sys/, abi/, *.sys.rs, *.bindings.zig, cdef.zig, extern.zig No — audit-significant
TestMock tests/mocks/ + mock/stub in name, tests/stubs/, _mock., _stub. Yes — doesn't ship
Unknown (fallback) No — treat as RuntimeAbi for safety

Audit-text parser: is_audited_boundary(audit_text, file_path) parses audits/audit-ffi-unsafe.md and returns true for paths listed under ## Approved boundaries / ## Pre-approved boundaries sections (either - path or - `path` form).

jit_context

JIT-framework classifier (src/jit_context.rs):

Variant Detected via
Cranelift cranelift_jit::JITModule, cranelift_module::Module, use cranelift_jit
Llvm inkwell::execution_engine, LLVMOrcJIT, MCJIT, LLVMCreateExecutionEngine
Wasm wasmtime::Module / Instance, wasmer::Module / Instance
Javascript rusty_v8::Isolate, boa_engine::Context, rusty_jsc::JSContext, v8::Function::call
None (fallback)

JitContext::permits_fn_ptr_transmute() returns true for any framework — drives the Critical → High severity downgrade for mem::transmute to function-pointer types (the canonical JIT-dispatch idiom).

transmute_targets_fn_ptr(content) recognises:

  • transmute::<_, fn(...)> (turbofish)
  • let x: fn(...) -> R = transmute(...) (let-binding, including the unsafe { ... }-wrapped form)
  • let x: unsafe fn(...) = transmute(...)

Downstream integration

When panicbot (gitbot-fleet bots/panicbot) parses an AssailReport, it honours test_context defensively: findings with test_context: "test_only" or "doc" are dropped even when suppressed: false. See gitbot-fleet#252.

When Hypatia adds AssailReport ingestion (not yet present), the same field shape should drive a ContextSuppressed bucket distinct from rule-driven suppression.

What's NOT in v2.5.5

ROADMAP items deliberately deferred or marked partial:

  • Comment-only WeakPointCategory — semantic-mismatch with the PA-code taxonomy; suppression-by-marker covers the immediate use case.
  • Test-data fixture lexer (example.com URLs, dummy creds) — needs a separate sub-lexer; the test_context metadata is in place to drive it when implemented.
  • JIT top-level WeakPointCategory — keeping UnsafeCode + UnsafeTypeCoercion with a JitContext sidecar is cleaner than a new top-level code.
  • Block-comment markers (/* … */, {- … -}) — line comments cover the common case.

Related