feat: exploitability reasoning (--exploit) + LLM-ready output (-o llm) - #348
Open
slimm609 wants to merge 32 commits into
Open
feat: exploitability reasoning (--exploit) + LLM-ready output (-o llm)#348slimm609 wants to merge 32 commits into
slimm609 wants to merge 32 commits into
Conversation
- Tier.String() now returns REQUIRES-INPUT-CONTROL / REQUIRES-LEAK (hyphens, not underscores), matching the task brief. - hasControlFlowHijackPrimitive checks only CatUnboundedCopy, dropping the extra CatCommandExec check that wasn't in spec; restored its Phase-A doc comment. - Restored dropped Phase B/C comments on CanaryPartial, FieldFunctions, FieldTaint.
Adds FileReport.Exploitability (omitempty), utils.Option/WithExploit, and threads opts through RunFileChecks, RunListChecks(Parallel), and the file/dir/listfile commands so exploit.Assess only runs when --exploit or --chain is passed. Default output is unchanged.
Add RenderExploitTable to print verdicts (tier, rule, technique, citations) plus the attacker's-bar summary, and wire it into writeTable's report loop so `--exploit` table output shows the exploitability section right after each binary's name line.
Tier is an int enum, so encoding/json and yaml previously emitted raw integers (e.g. "Tier": 0) instead of readable names. Add MarshalText so Tier round-trips through JSON/YAML as VIABLE, BLOCKED, etc.
RenderChain synthesizes a labeled hypothesis chain from a VIABLE stack-bof-overwrite hijack plus the first VIABLE payload technique (ret2plt, got-overwrite, shellcode-injection, or ret2libc), falling back to a "no consistent chain" line when either step is missing. Wired into writeTable via PrintOptions.Chain, set from the existing --chain flag across file/dir/listfile commands.
EvaluateFailIf now recognizes two special --fail-if keys evaluated against FileReport.Exploitability instead of Checks: - exploit.viable: fails when any verdict reaches TierViable. - exploit.technique=<rule id>: fails when a verdict for that rule reaches TierRequiresLeak or above. Both keys are accepted in the known-key validation step; a nil Exploitability report never matches. Existing check-key behavior is unchanged. Tests added in failif_exploit_test.go (pre-commit hook enforces a green suite, so the RED test and its GREEN implementation land in one commit rather than two).
… in ret2libc/ret2dlresolve
Maps checksec.Status to compact glyphs (ok/~/!/i) for LLM-oriented output.
writeLLMTarget prints a "## Target: <name>" header followed by one terse row per present FileFields check, in canonical field order.
Wires the LLM-oriented output format end to end: writeLLM assembles the grounding preamble, shared knowledge block, and per-target sections (with inline exploitability when present) built in earlier tasks. Registers "llm" in FilePrinter and threads --llm-no-preamble through file/dir/listfile.
…eamble to proc/kernel The LLM renderer ignored PrintOptions.Fields and always iterated the global FileFields registry, so -o llm never rendered the seccomp column in proc/procAll mode even though ProcFields was passed through. LLMNoPreamble was also not wired into proc/procAll/kernel, so --llm-no-preamble had no effect for those commands.
…tes in full usage
🤖 Augment PR SummarySummary: This PR extends checksec with two research features: (1) static exploitability mitigation-obstruction reasoning via Changes:
Technical Notes: Exploitability analysis is explicitly framed as evidence-cited posture reasoning (never “exploitable”), tiers serialize by name in machine formats, and 🤖 Was this summary useful? React with 👍 or 👎 |
…validation, drop dead WithExploit arg - postureFromChecks: treat indeterminate posture (NX 'No GNU_STACK'/Warn, PIE 'DSO'/Info, RELRO N/A) as protected so uncertain evidence never yields a false VIABLE verdict (honesty invariant). - --fail-if exploit.technique=<id>: reject unknown/empty ids (via exploit.IsKnownRuleID) so a typo'd predicate can't silently no-op a CI gate. - WithExploit(): drop the unused chain arg; chain is render-only via PrintOptions.Chain.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Two stacked, independently-designed research features that push checksec beyond reporting raw mitigation posture. Both were built spec-first (design docs), executed task-by-task under strict red/green TDD, and passed a final whole-branch review.
1. Exploitability reasoning (
--exploit/--chain)A "so-what" layer over the existing checks: instead of only reporting the mitigation posture, it reasons about which memory-corruption techniques that posture fails to obstruct, citing the evidence (imports, relocations, segment permissions) behind each verdict.
pkg/exploit/package: anEvidencecollector → a rule engine that abstains on missing evidence → 7 technique rules (stack-bof-overwrite,ret2plt,ret2libc,got-overwrite,shellcode-injection,format-string,ret2dlresolve) → renderers.VIABLE/LIKELY/REQUIRES-LEAK/REQUIRES-INPUT-CONTROL/ENABLER/BLOCKED); everyVIABLEverdict must cite a present primitive (enforced by an invariant test).exploitabilitykey in JSON/YAML (tiers serialize as their names).--chainemits a labelled hypothesis exploit chain (never presented as fact).--fail-if exploit.viableand--fail-if exploit.technique=<id>.2. LLM-ready output (
-o llm)A self-grounding Markdown format meant to be pasted into an LLM assistant so it reasons from the tool, not from stale training data.
pkg/knowledge/semantic layer: each check id → meaning + authoritative fix (covers everyFileFieldskey; enforced by a coverage test).--exploitverdicts.--llm-no-preamblestrips the directive; works acrossfile/dir/proc/procAll/kernelmodes.--exploit; default output for existing formats is unchanged.Testing
go build ./...andgo vet ./...clean.ret2libc/ret2dlresolvenow cite the gating import (not posture alone).Fieldsoverride soprocmode rendersseccomp;--llm-no-preamblethreaded to proc/kernel.table/json/yaml/xml/csvis byte-identical when the new flags are absent.Docs
Full usage documented in
docs/:usage.md(all new flags, exploitability + LLM sections,exploit.*fail-if predicates), newdocs/checks/exploitability.mdanddocs/llm.mdreference pages with worked examples, andindex.mdupdated. mkdocs nav updated.Deferred (intentional follow-ups, non-blocking)
Flagged by the final reviews and logged for a follow-up PR: XML format doesn't embed exploitability yet;
--exploitno-ops onproccommands;collectGOThandles 64-bit.rela.pltonly; the--fail-ifflag help string doesn't yet list theexploit.*predicates.Notes for reviewers
This branch is stacked — it contains both features. Phases B (disassembly-enriched evidence) and C (taint/reachability) of the exploitability design are specified but intentionally not built here.