Commit Graph
78 Commits
Author SHA1 Message Date
gensokyo-devandgensokyo-dev 98c589e420 perf(tests): reuse bounded CLI workers for native matching errors (#9163)
Co-authored-by: gensokyo-dev <gensokyo-dev@users.noreply.github.com>
2026-11-07 00:08:27 +08:00
2SinceJulyand2SinceJuly 6c08320654 feat(process): add a non-executing dry run to capture_process_scenario (#8469)
* feat(process): add a non-executing dry run to capture_process_scenario

Preparation prompts asked an agent to prepare a scenario without running
it but could only suggest the tool that launches the target. Add
dry_run: true so the CLI and MCP resolve the executable, working
directory, observation paths and admission checks, then return planned
Evidence under the rea.process-scenario-plan predicate. Planned Evidence
is not capture Evidence and comparison tools refuse it as a capture.

The preparation prompt now suggests the dry-run call, and the scenario
identity commitments exclude the operation-only field.

Fixes #8398

* fix(process): redact planned sensitive input and share admission

Address review findings on the dry-run contract:

- Redact sensitive input events in planned Evidence and preserve only
  their byte length.
- Recheck cancellation after the last awaited admission step.
- Run the sensitive-matcher and filesystem-root admission checks that a
  capture performs before launch.
- Assert the prompt advertises the dry_run field without freezing
  explanatory wording.

* test(process): hold the final admission step for cancellation

Add a preparation host seam so the regression can cancel while the last
filesystem admission call is pending, then assert the returned
AnalysisCancelledError retains the caller's reason.

* refactor(process): remove the unused plan alias

Keep the plan schema as the single exported contract and satisfy the
unused-export check.

* fix(process): report admission-time aborts as planning cancellation

`prepareProcessScenarioPlan` returned the admission error verbatim, so an
abort that landed while `admitFilesystemObservationRoots` awaited its
`lstat` surfaced as a cancelled `ProcessCaptureError` with
`operation: process_capture` even though no process ran. Convert that
result through the same `cancelled()` projection the neighbouring checks
use, and pin it with a test.

* fix(contracts): keep the process result invariants on the dry-run union

The output schema for `capture_process_scenario` became a union of the
capture and plan shapes, and the union no longer carried the description
that advertised the cross-field invariants to MCP clients — the boundary
test reads `normalized_result.description`. Attach a description to the
union that names both variants and keeps the capture invariants verbatim.

* test(process): exercise the post-admission cancellation check

The previous regression aborted immediately after starting preparation and
released the held admission afterwards. Preparation awaits runtime path
resolution first, so that abort was always observed by the pre-admission
check; deleting the post-admission "if (aborted()) return cancelled();"
still left the test green.

Signal from the admitRoots seam when admission is actually entered, abort
only after that point, then let admission resolve ok. Preparation now has
to reach the check between a successful admission and the ok result, and
the assertion pins both the AnalysisCancelledError tag and the caller's
reason as its cause.

Verified red-green: removing only the post-admission check fails this test
(expected true to be false at prepared.ok) while the other two pass, and
restoring it passes all three.

* test(process): gate the admission seam on acknowledgement

Race the admission acknowledgement against planning's own settlement and a
bounded deadline, and release and join planning in `finally`, so a planning
result that arrives before admission fails the test instead of stalling it
until the suite timeout.

* fix(contracts): hold plans to the scenario refinements and redact inputs

`processScenarioPlanSchema` described the resolved dry-run response but
dropped every cross-field check the input contract applies, so a plan
could advertise out-of-order events, an event past `timeout_ms`, or a
terminal beyond the renderer cell budget while claiming it had been
validated. Extract those checks into `scenarioRefinements` and refine the
plan's scenario with them.

The plan's input event also carried `sensitive` and an optional
`input_bytes`, which accepted a sensitive event that still shipped its
data. Model the public and sensitive forms as separate exact variants:
public input forbids `input_bytes`, sensitive input requires an empty
`data` plus its byte length.

---------

Co-authored-by: 2SinceJuly <202121119+2SinceJuly@users.noreply.github.com>
2026-11-06 20:49:20 +08:00
560674e2de feat(native): report binary hardening for ELF, PE and Mach-O (#8524)
* feat(native): report binary hardening for ELF, PE and Mach-O

Documents inspect_binary_hardening and its CLI equivalent, including
per-property states, supporting evidence, read budgets, and one report
per Mach-O slice. Explains that missing protection imports remain
unknown, signature presence does not establish validity, and hardened
runtime requires inspect_signature. Adds hardening links throughout the
documentation. The supplied diff also removes the advanced CodeQL
workflow and configuration, along with snapshot-binding mismatch
guidance.

* fix(native): validate declared payloads and dynamic tables before hardening rows

Run the shared range checks for ELF, read imports from the dynamic tables
rather than section metadata, and keep an unresolved symbol count apart from
an absent table. Check every Mach-O command before building rows and retain
only the offsets the rows need.

Make the verifier's readelf output wide, check the emitted format before
parsing Mach-O, and place the sources before the libraries in the link.

* fix(native): share Mach-O segment admission with hardening reads

A segment with a section count its cmdsize cannot hold passed the hardening
reader and could enable restrict_segment. Move the size, section count and
file range checks to a shared admission that readMachoImage and the hardening
reader both use, and pin the ELF load-size case with a regression test.

* fix(hardening): reject Mach-O section payloads past the slice and empty ELF interpreters

Segment admission never checked each section's payload range, so a
file-backed section past the slice still produced rows. Decode sections with
the section header owner and mark the slice malformed when a payload leaves
it; zero-fill and empty sections own no file bytes and are exempt.

admitInterp accepted a NUL first byte in a longer extent, which counted an
empty interpreter as PIE evidence. It now requires a nonempty path.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KuWHGvzJkrhCqjtEHUwqyH

* fix(native): read CFG instrumentation from decoded GuardFlags

Use the IMAGE_GUARD_CF_INSTRUMENTED flag that guardFlagRecord already
decodes instead of masking the raw GuardFlags word a second time.

* fix(native): reject ELF table spans a second PT_LOAD remaps

The hardening reader mapped DT_STRTAB, DT_SYMTAB and hash tables through
the one PT_LOAD containing the table's first address. A second PT_LOAD
starting inside the table could map the rest of it from other file bytes
and the reader still reported parsed import evidence.

Cap each mapping at the next PT_LOAD that starts inside it, reject a
requested range that crosses that boundary, and stop hash reads at the
same limit, matching the conflicting-mapping refusal in readElfSymbols.

* fix(native): dedupe ELF note tables only on shared boundaries

The hardening reader dropped any note table whose bytes another table
already covered. A covering SHT_NOTE can hold a non-GNU note whose
descriptor is itself a complete GNU property note, while PT_NOTE names
that inner note directly. Walking only the outer stream missed the GNU
marker and reported CET disabled.

Drop an alias only when it starts and ends on boundaries of admitted
tables, which are note boundaries of the walked streams. Any other
covered alias leaves the feature rows unknown, as a partial overlap
already does.

* fix(native): admit every Mach-O symbol record after a canary match

The Mach-O stack protector scan returned as soon as it found an
undefined ___stack_chk_fail, so a later undefined symbol whose n_strx
lay outside the string table was never checked. The same damaged table
parsed or failed as malformed depending only on record order.

Keep the match and finish the bounded record walk. Records after the
match are only checked against the string table bounds, so their names
are not read or charged to the scan budget. The ELF reader already
admits its whole symbol table before matching names.

* fix(native): accept ELF load aliases with the same file translation

The hardening reader treated every PT_LOAD that starts inside a table,
or that also contains the table's address, as a conflicting mapping.
A load with the same address-to-file translation names the same file
bytes, so tables it overlaps still have one interpretation, and the
canonical ElfLoadMap already merges such spans.

Treat equivalent loads as one interpretation. A load with a different
translation, or the zero-filled tail of an equivalent load, still ends
the usable range, so a remapped table is still rejected.

* fix(native): keep same-span ELF note tables with different alignments unknown

A section and a program header that share endpoints were treated as one
note stream even when their effective note alignments differed. Walking the
same bytes at 4 and 8 can frame different notes, so dropping the second table
could hide a GNU property word and report CET or BTI as disabled.

Require matching effective alignment at both endpoints, and no alignment
change inside the covered span, before treating a table as an alias.
Otherwise mark the feature rows unknown. The fixture's .note.gnu.property
section now declares the class's note alignment, as toolchains emit it.

* refactor(native): read LC_SYMTAB through the shared fixed-word decoder

Move the Mach-O fixed uint32 command layouts out of MachoCommandNames
into domain/apple/machoLoadCommands so there is one owner of those
offsets. MachoCommandNames and the hardening reader now both decode
through it; the hardening reader keeps its own bounds and import policy.

* fix(native): skip Mach-O common definitions in canary imports

A common definition sets N_UNDF|N_EXT like an import but stores its
allocation size in n_value. An object holding only
`int __stack_chk_fail;` therefore reported stack_protector: enabled.

Require a zero n_value before an undefined external counts as an
import, for both nlist widths.

* refactor(native): read linkedit data commands through the shared fixed-word decoder

readMachoLinkeditDataCommand reproduced the dataoff/datasize offsets that
FIXED_WORD_FIELDS already owns. Take the command and decode through
decodeMachoFixedWordFields, as readMachoSymtabCommand does, keeping the
truncation and endianness behavior.

* fix(native): skip empty SHT_NOTE sections in ELF hardening

A zero-sized SHT_NOTE owns no bytes, so the section directory marks it
not file-backed and the hardening reader rejected the whole image as
malformed, while readElfImage accepted the same bytes. Skip empty note
sections before the file-backing check; they have nothing to walk.

* fix(scripts): run hardening verifier commands through the shared owner

The binary hardening verifier started its probes and compiler drivers with
raw spawnSync, which bypassed the src/process/ supervision that AGENTS.md
requires. Every launch now goes through createVerifierCommands, and the
temporary root is removed only after the owner closes cleanly.

* fix(scripts): clean up hardening verifier commands on Ctrl-C

SIGINT or SIGTERM ended Node before withVerifierCleanup ran, so detached
compiler trees and the temporary root could outlive the verifier. The
verifier now turns those signals into an abort that every owned command
receives, so cleanup closes the owner and removes the root before exit.

* fix(scripts): fail the hardening verifier when a signal lands outside a command

Only the owned commands read the interruption signal, so a SIGINT or
SIGTERM during the final cleanup or between commands was recorded and
then dropped, and the verifier exited 0. After cleanup settles, the
verifier now throws the interruption reason. A failure the operation or
its cleanup already raised still leaves first and is not replaced.

* fix(native): fail Mach-O slices with a malformed encryption command

The hardening reader turned every malformed status from the shared
encryption reader into an unknown `encrypted` row, so a short
LC_ENCRYPTION_INFO_64 or an encrypted range past the slice still left the
slice parsed with a full report.

Only two conflicting encryption commands stay an unknown row now. Any other
encryption defect fails the slice like other structural command failures.

* fix(native): ignore STB_LOCAL undefined ELF symbols as imports

A local undefined __stack_chk_fail or __memcpy_chk is never resolved
against another object, so it does not establish an external import.
Skip STB_LOCAL bindings when reading protector signs, and give the
fixture's positive symbols STB_GLOBAL binding.

---------

Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 01:07:00 +08:00
027c768f07 fix(captures): classify unresolvable capture paths as capture_path input (#7814)
* fix(captures): classify unresolvable capture paths as capture_path input

Fixes #7636

* test(captures): cover unresolvable descriptor paths

---------

Co-authored-by: Abelo9996 <Abelo9996@users.noreply.github.com>
Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
2026-11-05 18:30:07 +08:00
morlutoandCursor Agent 2b740cab36 fix(native): preserve function byte source qualifications (#8606)
* fix(native): preserve function byte source qualifications

* fix(native): recover oversized inline matching sources

* test(native): verify matching byte source recovery

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
2026-11-05 04:01:16 +08:00
星闌 b1b6cb64c2 fix(analysis-view)!: distinguish unavailable native collections (#8291) 2026-11-04 23:53:45 +08:00
Kaoru0822andClaude Opus 5.5 710fad8acf feat(evidence): discover missing Evidence links without transferring records (#8633)
* feat(evidence): discover missing Evidence links without transferring records

An agent could only learn that a retained record's source was absent by reading
complete records or by having a downstream analysis refuse. The summary said
nothing about links, and complete-record retention was easy to mistake for
source closure.

- Add detail: links to get_evidence_bundle and CLI inspect-evidence-bundle:
  paged link rows with retained or missing status and no record payloads, for
  selected records against the whole session or file.
- Add retained-closure traversal, the walk composed workflows require, reporting
  complete or incomplete. Direct reads make no closure claim.
- Count direct and missing direct links in the summary.

Fixes #8454

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(evidence): count a repeated Evidence link once in every delivery

The Evidence schema does not deduplicate evidence_links, so the summary counted
a repeated link twice while link rows and counts reported it once. Both now read
one helper for a record's distinct direct links.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test(evidence): validate link delivery against the advertised schemas

The test never called tools/list, so neither the shared validator nor the MCP
client checked its replies against what each profile advertises. A schema that
rejected the links result could have passed. Fetch the advertised definition and
validate every request and reply against it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 05:14:34 -08:00
morluto 60149282fc test: strengthen integration oracles and verification (#8295)
* test: strengthen integration oracles and verification

* test: bound lifecycle gates and strengthen workflow checks

* test: verify complete paged and extracted results

* test: preserve bytecode and cancellation evidence

* test: strengthen retained evidence and fixture cleanup

* test: require cross-projection bridge identities

* test: retain fixture owners through cleanup failures

* test: verify graph examples and project selectors

* test: tighten provider and lifecycle regressions

* test: consolidate hex coverage and bound cutter cleanup

* test: bound subprocess output waits and strengthen graph checks

* test: check mcp recovery and preserve cleanup owners

* test: verify structured mcp argument failures

* test: preserve artifact cleanup and gdb limit evidence

* test: preserve evidence identities and bound provider gates

* test: retain browser and comparison cleanup owners

* test: bound startup and strengthen fixture oracles

* test: bound lifecycle gates and verify recovered evidence

* test: verify public outcomes and lifecycle ownership

* test: assert precise evidence and release lifecycle gates

* test: verify selected facts and bound cleanup waits

* test: check retained evidence and decoded records

* test: verify final reports and retain cleanup ownership

* test: bound reviewed startup gates and retain cleanup

* test: verify PE errors and preserve MCP cleanup

* test: preserve MCP fixture cleanup ownership

* test: release provider gates before late startup
2026-11-01 00:15:28 +08:00
morlutoandCopilot Autofix powered by AI 675d4076de test: strengthen regression oracles and cleanup ownership (#8152)
* test: strengthen suite oracles and cleanup ownership

* test: reuse setup across independent scenarios (#8153)

* Potential fix for pull request finding 'CodeQL / Improper code sanitization'

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

---------

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2026-10-31 00:22:16 +08:00
gensokyo-dev f60e42a9ae fix(mcp)!: bound validation work before tool dispatch (#7905)
Reuse the pinned SDK's combined array-element and object-member admission
before canonical validation, deferred runtime loading and tool execution.
Share a configurable finite allowance across eager/deferred HTTP and stdio,
and project refusals to bounded, actionable transport resource errors.

Preserve canonical CLI/application contracts, caller-selected input values,
ordinary validation semantics and complete Evidence access. Exercise actual
transport boundaries, real artifact/TShark workflows, packaged installation,
continued service and downstream identity/capacity regressions.

Fixes #7882

BREAKING CHANGE: MCP tool arguments now default to 1,024 combined array
elements and object members per call. Select a larger positive finite
REA_MCP_MAX_INPUT_ELEMENTS allowance and restart for larger inline inputs,
or use retained/file selectors where supported. Inputs are never truncated.

Assisted-by: Reimu (gensokyo-skills:reimu-incident-triage)
Assisted-by: Kogasa (gensokyo-skills:kogasa-surprise-testing)
Assisted-by: Yukari (gensokyo-skills:yukari-boundary-analysis)
2026-10-29 05:56:38 +00:00
morluto f9acfdcf49 fix(cli): retain committed evidence receipts on output failure (#7906) 2026-10-29 05:11:02 +08:00
morluto cc5a4062ff fix(browser): preserve unknown WebMCP comparison facts (#7833) 2026-10-29 05:09:22 +08:00
morluto b0880d660f fix(qlog): exclude hidden custom events from incomplete facts (#7825) 2026-10-29 04:58:53 +08:00
morluto 0a272d5cf5 fix(capture): bound preview headlines by source format (#7832)
* fix(capture): bound preview headlines by source format

* test(capture): cover scalar HAR preview extensions
2026-10-29 01:56:07 +08:00
ShuaixinHuang 9593bc536b fix(protobuf): reject malformed descriptor field declarations (#7730) 2026-10-28 19:52:11 +08:00
gensokyo-devand555aaditya 03f17cf41d feat(android): apply caller-selected R8 mapping evidence (#7456)
Apply caller-selected R8/ProGuard mappings to shared Android inspections, preserving raw identities, exact verification, ambiguity and provenance. Add retained summaries and bounded/cached parsing, with measured real R8/Conscrypt workflows and review fixes.

Fixes #6329.

Co-authored-by: 555aaditya <107977627+555aaditya@users.noreply.github.com>
2026-10-27 15:47:08 +08:00
morluto 4191974010 fix(environment): share retained response declarations
Preserve status independently of malformed content and use one declaration reader for route grouping, state extraction and manifest eligibility. Verify the partial facts through CLI and MCP views.
2026-10-27 05:37:47 +08:00
morluto cc5a96933a test(mcp): validate selected tools without compiling the entire catalog 2026-10-26 18:26:33 +08:00
morluto eb51eb6915 fix(process): preserve selected launch paths and completed command output 2026-10-26 16:46:53 +08:00
morluto c994870f6b fix(inspector): route file locations through URL semantics 2026-10-26 16:02:14 +08:00
69a2faa120 feat: add FreeBuff agent support for REA setup (#2736)
* feat: add FreeBuff agent support for REA setup

Register FreeBuff as a supported setup client using the shared user
agents directory (~/.agents/mcp.json with mcpServers, skills in
~/.agents/skills), which matches what FreeBuff Desktop loads. Adds the
client definition, boundary tests, supported-agent docs, and the skill
reference client list.

* fix(freebuff): detect FreeBuff from its profile directory, not shared .agents

The ~/.agents marker made FreeBuff appear installed for any home where
REA had installed shared skills (the default skill destination, also
Gemini CLI's), producing false doctor failures. Detect FreeBuff from
its own fixed profile directory ~/.config/freebuff-desktop instead,
and add a regression test covering a home with only the shared agents
skill directory.

* fix(setup): require product evidence for FreeBuff discovery

Address review findings at their producing boundaries and preserve directly affected consumers. Source inspection and git diff --check completed. Tests and automated checks were not run at the user’s explicit request.

* fix(uninstall): retain unverified shared client configuration

* fix(clients): preserve scoped removal evidence

* fix(doctor): omit undefined selectedClientIds under exactOptionalPropertyTypes

Passing selectedClientIds explicitly as undefined fails typecheck on this
branch (TS2379), which blocks the focused test workflow before any test
can run. Spread the option only when defined.

* fix(update): separate ownership evidence from product applicability

rea update's maintenance scope inspected only product applicability
evidence, so when a FreeBuff profile was absent but REA already owned a
version-pinned row in the shared ~/.agents/mcp.json, the plan omitted
freebuff and left the integration stale. FreeBuff now declares its
registration storage as shared, which proves ownership of an owned row
but never product applicability, and maintenance requests ownership
evidence through that declaration instead of reinterpreting the shared
paths. Doctor and setup keep readiness evidence, foreign rows stay out
of maintenance, and the Doctor exactOptionalPropertyTypes fix makes the
focused test workflow runnable.

* test(dotnet): split oversized operand extent diagnostics describe

The describe callback reached 162 lines (max 150), failing
max-lines-per-function and blocking the pre-push check for this branch.
Move the single-case extent scenarios into their own describe; no test
content or order changes.

* fix(update): preserve ZCode's disabled shared registration during maintenance

The shared user agents file doubles as ZCode's fallback, where
`enable: false` disables the registration. Ownership-based maintenance
read that row as a FreeBuff registration, whose format does not
recognize the flag, so the row was selected and the emitted setup
command rewrote it, dropping the flag and silently re-enabling a
registration the user had disabled.

registrationActivation now honors `enable: false` for any client whose
registration storage is shared, because the activation fact binds every
reader of that storage. Maintenance leaves such rows out; doctor
reports them as stale, matching ZCode's own treatment.

* fix(doctor): let explicit client selection authorize the config read

When an ACL or an inaccessible shared parent made every access probe
fail, a client selected by name was omitted before the configuration
read could return its unreadable-config detail, so doctor reported it
as not detected with installation remediation: an unresolved selected
path collapsed to absence.

An explicit selection now authorizes the read outright and the probes
serve automatic discovery only. A selected client with an unreadable
config reports invalid with the read failure; one with no config
reports missing; automatic discovery still probes before inspecting.

* fix(uninstall): share shared-storage checks between ZCode and FreeBuff

clients() queued ~/.agents/mcp.json twice: once as zcode_fallback and once
as freebuff. ZCode has no discoveryPaths, so its strict read still blocked
uninstall on malformed shared text, despite FreeBuff's new retain-and-continue
behavior. For a valid owned entry, ZCode removed it first, so FreeBuff reported
skipped rather than removed.

Make the shared file's checks and removal one shared decision:
- Add zcodeDiscoveryPaths to ZCode so it has its own applicability evidence.
- Gate zcode_fallback push on applicable, not just zcodeFallbackPath presence.
- Report shared storage ownership as one decision for both clients:
  FreeBuff and ZCode now use clientOwnershipEvidencePaths together, so a
  recognizable REA-owned row proves ownership once for the shared storage, and
  both clients report the same result consistently.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(uninstall): merge duplicated host and prove shared ownership from owned rows

Uninstall.ts declared systemUninstallHost twice, preventing module load,
with the exported copy returning only clients and the second copy missing
clientWriteBlocker. Merge into one exported host carrying both blockers.

hasOwnershipEvidence used access() existence, so an unrelated malformed
~/.agents/mcp.json established ownership and blocked every removal.
Ownership now requires a readable, recognizable REA-owned row via the
injected filesystem, so unrelated shared data stays retained.

Also cover ZCode discoveryPaths in its path test.

* fix(uninstall): keep denied product-local configurations fail-closed

Unproven product applicability marked every configuration path of that client unverified, so a denied ZCode profile turned an unreadable product-local config into a retained item: uninstall continued and could report complete with REA still registered. The retain-and-continue exception now applies only to storage REA does not own, classified once by clientSharedRegistrationPaths (shared configuration plus another product's same-scope fallback).

Covers the Greptile P1 on Uninstall.ts. Validation: the new test fails on the pre-fix Uninstall and passes after it; freebuff/zcode/updateMaintenance/bom/dsh suites green; clientLifecycle, clientRegistrationStatus and claudeDesktop keep the same 8 host failures as the pre-merge baseline (symlink EPERM, stale-vs-aligned on Windows).

* fix(update): retain FreeBuff when ZCode reads the shared fallback

Maintenance deduplicated clients on the path each inspection read, so ZCode's fallback view of ~/.agents/mcp.json marked that file "covered" and dropped FreeBuff from the scope. ZCode setup writes ~/.zcode/cli/config.json and deliberately leaves the fallback untouched (docs/client-configuration.md), so the emitted command refreshed only ZCode while the shared row both products load stayed pinned to the old package version. Each setup action rewrites only its own configuration path and no other action rewrites the shared row, so every selected client keeps its own maintenance action; the read-path covered/deduped filter is removed.

Covers the Codex P2 on UpdateMaintenance.ts:104. Validation: the new regression fails on e2fdec384 with {clients:["zcode"]} and passes with {clients:["freebuff","zcode"]}; updateMaintenance 31/31, setupClientConfigCleanupOwnership, cliUpdateAlias, updateOutput, cliStartupImports green; tsc --noEmit, oxlint (0 errors) and oxfmt --check clean; clientRegistrationStatus keeps the same 4 symlink/stale-vs-aligned failures this Windows host has on base e2fdec384 (verified by stashing the change).

🤖 Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>

* fix(uninstall): preserve completed reads as shared ownership evidence

hasOwnershipEvidence caught every read failure and kept scanning, so a handle-close failure after a successful read — a RegularFileCleanupFailure whose completed outcome still contains the exact shared-file text — was discarded as "no proof". FreeBuff's applicability-unverified storage therefore never got its ownership fact, and once the retained handle blocked later reads, readClientConfiguration downgraded them to retained: inspection passed, removals soft-failed, and runUninstall(true) could purge REA data while the active shared registration remained. The catch now parses the completed outcome for the ownership text while missing or unreadable storage and malformed data keep their proves-nothing semantics, so ownership holds and every later read failure stays blocking.

Covers the Codex P2 on Uninstall.ts:252. Validation: the new regression fails on 4dbfdf1a9 (freebuff reports no blocking failure while the poisoned-scope error lands on claude_code) and passes after; setupClientConfigCleanupOwnership 25/25; the other 21 Uninstall-consumer suites are byte-identical to base 4dbfdf1a9 (61 pre-existing Windows-host failures: symlink EPERM, stale-vs-aligned); tsc --noEmit, oxlint (0 errors, same 6 warnings) and oxfmt --check clean.

🤖 Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>

* fix(uninstall): keep owned-row proof through removal refusals

hasOwnershipEvidence treated any clientRegistrationRemoval refusal as no ownership: an effective REA-owned rea member shadowed by an earlier foreign duplicate (shadowed_unowned_member), or an owned native row beside a foreign V1 fallback (foreign_legacy_fallback), discarded the already-parsed positive row fact. With FreeBuff unverified and close failures recurring on the preflight/removal rereads, those failures were then downgraded to retained, so runUninstall(true) removed the skill and purged REA data while the active owned row remained. The refusal now carries the owned rows that motivated it — the refusal only refuses the edit — and hasOwnershipEvidence evaluates that fact on both paths; preflight and removal keep refusing the unsafe edit exactly as before.

Covers the Codex P2 on Uninstall.ts:269. Validation: the new regression fails on 225cb214a (freebuff reports no blocking failure while the poisoned-scope error lands on claude_code) and passes after; setupClientConfigCleanupOwnership 26/26; the 21 Uninstall-consumer suites are byte-identical to the recorded 225cb214a baseline (61 pre-existing Windows-host failures: symlink EPERM, stale-vs-aligned); tsc --noEmit, oxlint (0 errors, same 6 warnings) and oxfmt --check clean.

🤖 Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>

* fix(uninstall): keep unresolved discovery probes from softening shared failures

The discovery probe swallowed every stat failure, so a FreeBuff profile denied with EACCES/EIO was indistinguishable from an absent profile: shared storage was marked applicability-unverified and, when ~/.agents/mcp.json also remained unreadable, the ownership and removal reads softened to retained. runUninstall(true) then removed the skill and purged REA data while an installed FreeBuff could still hold an active registration — the regression even reports complete. Absence (ENOENT) is now the only state that leaves shared paths unverified; any other probe failure leaves applicability unresolved, and shared-config failures stay blocking.

Covers the Codex P2 on Uninstall.ts:318. Validation: the new regression fails on 7572a7082 with status complete and purged data and passes after; freebuffClientConfiguration 13/13; the Uninstall-consumer batches are byte-identical to the recorded baselines (61 pre-existing Windows-host failures: symlink EPERM, stale-vs-aligned); tsc --noEmit, oxlint (0 errors, same warning rules) and oxfmt --check clean.

🤖 Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>

* fix(uninstall): retain completed configuration reads as removal evidence

A close failure after a completed read discarded the text that read
produced, so an owned registration row the text proves softened to
retained. The completed text now drives removal, keeping shared-config
failures blocking when ownership evidence exists.

Co-Authored-By: Anthropic <noreply@anthropic.com>

* fix(uninstall): stop removal when a cleanup retry leaves a handle unreleased

A completed reread whose handle the cleanup retry cannot release now fails
blockingly instead of serving the text: with no owned row, the soft path
let removeAll purge managed data before close() reported the incomplete
cleanup. The completed text is served only after the retry releases the
handle; an unreleased handle is REA's own failure, never applicability
uncertainty, so it bypasses the retained softening.

Co-Authored-By: Anthropic <noreply@anthropic.com>

* fix(uninstall): keep the ZCode fallback when its profile probe is unresolved

A denied or failed profile probe leaves ZCode's applicability unresolved,
never absent, but the fallback branch dropped the shared row on
applicability alone: with the native config and FreeBuff's profile both
absent, an installed ZCode kept its uninspected registration while
uninstall purged skill and data. Unresolved probes now keep the fallback
in scope with the same fail-closed treatment as other unresolved shared
paths; definitive absence still keeps ZCode out of another product's
primary storage.

Co-Authored-By: Anthropic <noreply@anthropic.com>

* fix(setup): preserve a shared row's enable:false during FreeBuff repair

The shared agents file doubles as ZCode's fallback, so its `enable: false`
binds every reader: doctor now reports the disabled row as stale for
FreeBuff, but following that remediation rebuilt the generic JSON entry
without the flag and silently re-enabled a registration ZCode disabled.
Repairs of shared storage now carry the activation fact forward, while a
client's own native storage keeps its established single-reader repair
contract; the denied-profile uninstall regression also pins the
fallback's new fail-closed inspection beside the denied read.

Co-Authored-By: Anthropic <noreply@anthropic.com>

* test(uninstall): retarget the completed-reread regression to a released retry

The concurrent-writer regression held the reread handle open forever,
which the fail-closed path now serves: it duplicated the unreleased-handle
regression while documenting the opposite contract. The fixture's close
spy gains a failure limit so the cleanup retry releases the handle, and
the test again proves the completed text drives removal of the
concurrently added owned row, with purge verified against the cache
layout purge actually removes.

Co-Authored-By: Anthropic <noreply@anthropic.com>

* fix(doctor): report a preserved shared disable as a manual conflict

Preserving a shared row's enable:false left doctor recommending a setup
run that registrationCurrent correctly treats as already current, so the
scoped doctor returned needs_human forever. The shared-enable
interpretation now has one owner, sharedEnableFlagBinds, used by both
the activation rule and the remediation: a row disabled through the
shared flag reports the manual conflict and states that rea setup will
not change it, instead of an endlessly ineffective repair.

Co-Authored-By: Anthropic <noreply@anthropic.com>

* fix(doctor): keep a native ZCode disable on the setup repair path

The manual-conflict remediation matched a native zcode row through
sharedEnableFlagBinds, but setup drops enable:false on single-reader
storage, so a native disabled registration was told setup would not
change it. The remediation now reads setup's own writer rule,
exported as setupPreservesDisabledActivation: shared storage and the
zcode fallback view keep the manual-conflict message, while a native
row keeps the working rea setup instruction. Regressions pin both
remediations.

🤖 Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>

* revert: drop the unrelated managed-CIL describe split

The split does not belong to FreeBuff client support and only widens this
PR's diff.

🤖 Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>

* fix(uninstall): remove the shared agent registration once for both clients

ZCode's ~/.agents/mcp.json fallback and FreeBuff's own configuration queued the
same physical file twice, so ZCode removed the row and FreeBuff then reported
it absent, losing the outcome for the client that owns the file.

Resolve every configuration path to one owner -- the client whose
configuration it is -- and project that single inspection and removal to each
client that loads it. A fallback reader still contributes its discovery probe,
so an installed or unresolved reader keeps the shared file fail-closed.

Discovery also accepted a dangling ~/.config/freebuff-desktop link, which setup
and doctor reject because they follow the target, so an unrelated malformed
shared file blocked every other removal. Resolve the link before treating the
profile as installation evidence, keeping lstat for removal safety.

Also date the FreeBuff release wording against the published 6.7.0 package.

* fix(uninstall): keep a row per client when two clients own one file

OPENCODE_CONFIG can point OpenCode at FreeBuff's configuration file, where
OpenCode writes `mcp.rea` and FreeBuff writes `mcpServers.rea`. Grouping by
filename gave that path a single owner, so uninstall removed only OpenCode's
row, reported that removal for FreeBuff, and could purge managed data with
FreeBuff's registration still active.

Share the decision only through a fallback view of another client's row: every
client that declares the path as its own configuration keeps its own
inspection and removal, and the fallback reader reports each of them.

* fix(clients): preserve discovery and fallback registration identity

Follow product discovery link targets without losing configuration entry
presence or explicitly selected inspections. Associate fallback readers with
the format owner's registration table and project outcomes by owner and path,
so OpenCode removal cannot be reported as a ZCode fallback removal.

All three new boundary regressions fail against the previous source and pass
with the fixes. Validation: check:fast; 217 focused tests passed; the two
changed test files were rerun with 50 passing tests. No installed FreeBuff
client was launched.

---------

Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Kaoru0822 <208281322+kaoru0822-kitauji@users.noreply.github.com>
Co-authored-by: Codebuff <noreply@codebuff.com>
2026-10-25 11:29:17 +08:00
morluto f3ed1657f8 feat(mcp): support runtime analysis limit recovery (#7049)
* feat(mcp): support runtime analysis limit recovery

* refactor(config): remove unused limit re-exports

* fix(android): keep fixture release metadata dependency-free

* fix(settings): preserve provider budgets and recovery facts

* fix(tests): resolve lint plugins from their repository owner

* refactor(mcp): verify guidance delivery without frozen wording

* fix(android): align availability with runtime timeout

* test(recovery): assert limit facts instead of frozen wording

* fix(mcp): share runtime settings with the default JADX provider

* test(mcp): bound acknowledgements and release held work on failure

* fix(catalog): declare runtime settings tools as MCP-only
2026-10-25 09:45:26 +08:00
morluto 475f09d5ca chore(lint): enforce buffer and cancellation regression guards 2026-10-25 07:31:42 +08:00
b4ba96a9a5 feat(firmware): inspect flattened devicetree blobs (#7009)
* feat(firmware): inspect flattened devicetree blobs

Adds inspect-devicetree and inspect_devicetree for FDT v16/v17 blobs
without target execution or external dependencies. Results include
validated headers, reservations, a node/property tree with bounded raw
previews, and derived standard values and selected phandle references.
Parsing enforces file, tree, and decoded representation budgets and
rejects malformed input without partial success. Summary delivery
supports retained Evidence pagination, with tests covering parsing,
service validation, CLI delivery, and MCP access after the input is
removed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016y53PdpyMAp9RSW65fatHe

* fix(firmware): reject conflicting devicetree phandles and bound page summaries

A node whose phandle and linux,phandle disagree no longer resolves under
either value; the conflict is reported as a limitation. Finalization
failures after a completed read retain the file-snapshot-hash partial
observation, matching the Go provider. Devicetree view pages carry
fixed-size context and counts instead of repeating summary strings, so a
large bootargs no longer pushes every page over the MCP response budget.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016y53PdpyMAp9RSW65fatHe

---------

Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
2026-10-24 22:45:22 +08:00
dba8a31978 feat(elf): inspect Linux kernel module metadata (#7010)
* feat(elf): inspect Linux kernel module metadata

Adds inspect-kernel-module and inspect_kernel_module for ELF32/ELF64
ET_REL Linux kernel modules, read statically without executing them.
Reports ordered .modinfo entries with duplicates preserved, __versions
symbol CRCs, the presence of .gnu.linkonce.this_module and __ksymtab,
.init.text and .exit.text sizes, and an appended module signature
trailer with its PKCS#7 byte range and SHA-256. gzip, xz and zstd
containers are reported unsupported with external decompression as the
next probe. Malformed headers and exhausted entry budgets return no
partial success.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016y53PdpyMAp9RSW65fatHe

* fix(elf): bound kernel module ksymtab listing and tighten contracts

Charge listed __ksymtab* sections against max_entries, omit section names
longer than 256 bytes with ksymtab_name_exceeds_limit, and aggregate the
non-file-backed limitation so repeated huge names cannot inflate Evidence.
Use fixedTupleSchema for the signature pad bytes with projection parity
tests, and assert the late-cancellation reason and retained observation.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016y53PdpyMAp9RSW65fatHe

* fix: resolve merge integration errors

---------

Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
2026-10-24 22:35:20 +08:00
c6a2576aba fix(contracts): reject NUL bytes in objdump and rizin local path inputs (#3600)
Co-authored-by: qorvr <330186599+qorvr@users.noreply.github.com>
Co-authored-by: Kaoru0822 <208281322+kaoru0822-kitauji@users.noreply.github.com>
2026-10-24 23:13:34 +09:00
3d84215bb2 feat(pe): inspect TLS callbacks and load configuration (#7008)
* feat(pe): inspect TLS callbacks and load configuration

Adds inspect-pe-load-config and inspect_pe_load_config for PE32 and
PE32+ images, with artifact hashes and file ranges in the returned
evidence. Reports callback addresses and mappings, plus size-covered
security-cookie, SafeSEH, CFG, EH-continuation and XFG fields;
flag-derived mitigation claims are explicitly labeled inferred. Missing
directories remain null, and malformed storage or exhausted read budgets
return errors without partial success. Adds documentation and tests for
service validation, CLI/MCP access, malformed inputs and stable-file
handling.

x86 images that declare the legacy 64-byte load-config directory are
read to the structure's own Size when those bytes are file-backed, as
the Windows loader does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016y53PdpyMAp9RSW65fatHe

* fix(pe): retain snapshot facts and bound load-config section lookup

Keep the completed stable-read path, SHA-256 and byte count as a
file-snapshot-hash partial observation when descriptor close fails or is
cancelled. Report the checked Size span as structure_location and add it
to Evidence locations beside the declared directory range. Resolve
callback sections through a sorted segment index built once per image,
keeping the ambiguity failure. Pin every load-config field to offsets
transcribed from the PE/COFF spec and llvm COFF.h at its exact Size
boundary for PE32 and PE32+.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016y53PdpyMAp9RSW65fatHe

---------

Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 22:06:41 +08:00
781760a195 feat(apple): inspect IPS crash reports (#6511)
* feat(apple): inspect IPS crash reports

Add inspect_apple_ips for caller-selected Apple .ips files. Parse the
first-line metadata object and, when bug_type is the string 309, the
crash body: process identity, exception and termination facts, threads,
usedImages, lossless integer registers, and documented classification
rules. Other bug types including 288 stackshots return no crash result.
Opened Mach-O and dSYM UUID joins remain unobserved.

Related to #4297

* fix(apple): keep IPS register literals exact

Use the arm64e fixture integer that matches 0x8527000193ed4944 instead
of an IEEE-754-rounded decimal, and count the lossless JSON example
length from the source text.

* fix(apple): budget IPS parsing and keep typed presence

Parse the IPS metadata and crash body through a projection of the
documented members. Members the report does not interpret are
syntax-checked without being materialized, and thread, frame, image and
the new max_registers budgets run before each row is parsed, so a large
selected file fails with a typed resource error instead of first
expanding every row. Fixed allowances bound JSON nesting, unlisted key
names and termination reasons.

Present values whose JSON type differs from the documented one are no
longer read as absence: they are listed in coverage.type_mismatches and
coverage becomes partial, including wrong-type or missing threads and
usedImages collections. osVersion keeps the producer dictionary or the
string form. Frame roles follow physical frame depth, so the top frame
of a non-faulting thread is current_instruction and inlined rows share
the following frame's role. SIGKILL classes compare the canonical hex
once, so 0xdeadd0cc no longer matches dead10cc. Invalid UTF-8 is refused
instead of being replaced, and JSON strings are decoded by copying
unescaped spans.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ra7LM2NyQ7DumdssxbUq5g

* fix(apple): bound integer text expansion and reconcile coverage

* refactor(apple): retain image metadata at its owning row

* refactor(apple): validate row capacity through reconciled coverage

* test(apple): verify resource recovery at the public error boundary

* docs(apple): record complete IPS task and corpus measurements

* docs(apple): record integrated checks and stdio corpus evidence

* docs(apple): record PE integration and baseline cleanup controls

* fix(native): bound IPS string decoding and preserve invalid identities

* refactor(native): use exact optional IPS source evidence

* docs(native): verify IPS escape capacity and complete-task costs

* test(native): verify IPS through production stdio MCP

* style(tests): format IPS advertised schema bindings

* fix(native): preserve unresolved IPS references and recorded frame semantics

* docs(native): record IPS reference review evidence

* fix(apple-ips): enforce JSON and report consistency

* docs(apple-ips): record final consistency verification

---------

Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
2026-10-24 16:02:59 +08:00
4ef916da03 feat(pe): inspect import and delay-load tables (#6509)
* feat(pe): inspect import and delay-load tables

Add inspect_pe_imports / inspect-pe-imports to read PE32/PE32+ import
and delay-load directories without executing the image. The report keeps
DLL names, named and ordinal functions, ILT/IAT RVAs, and a pefile
import hash of the standard import table. A missing directory is
observed absence, not proof the image never imported APIs.

* fix(pe): default PE import fixture options

Allow peImportImage() without an argument so CLI and filesystem tests
can use the KERNEL32 sample without repeating an empty options object.

* test(pe): keep import path cases on the dedicated MCP contract

inspect_pe_imports already rejects relative MCP paths in its own
boundary test. Leave the shared absolute-path matrix to tools whose
handler issue projection matches that suite's expected shape.

* fix(native): index virtual-to-file mapping lookups

mappedFileOffset scans every mapping twice per span, so a parser that
translates one span per table entry costs sections x entries. Add
fileMappingLookup, which builds an O(n log n) interval index once and
answers each span in O(log n) with the same accept, reject and
translation results. A differential test checks it against
mappedFileOffset over randomized overlapping mappings and zero fills.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ra7LM2NyQ7DumdssxbUq5g

* fix(pe): report partial import evidence and exact pefile hashes

- Withhold imphash with an explicit reason whenever the standard import
  table is partial (unreadable names or thunks, missing tables), or when
  pefile 2024.8.26 would hash a different row sequence: invalid or
  truncated names, ordinal 0, descriptors without functions, tables its
  bounds or repeat/spread heuristics discard, and its 8192-thunk import
  symbol cap. Delay-load issues do not withhold it.
- Hash ordinal imports with pefile's complete ordlookup tables and its
  ord<decimal> fallback instead of declining unmapped ordinals.
- Report a nonterminal descriptor whose FirstThunk is zero, and a
  delay-load descriptor whose IAT or INT RVA is zero, as malformed_entry
  partial coverage instead of a complete empty inventory.
- Directory evidence lists the file spans actually consumed for the
  descriptor array and terminator; discontiguous mappings produce
  separate spans and separate Evidence ranges.
- Carry exhausted limits as PeImportLimitFailure.limit and derive
  recovery from it; the fixed 16 MiB retained-text ceiling reports a
  fixed allowance instead of max_file_bytes advice.
- Translate RVAs through the indexed mapping lookup and yield with a
  cancellation check every 1024 table entries.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ra7LM2NyQ7DumdssxbUq5g

* fix(pe): read only own ordinal tables for DLL names

DLL names such as constructor and __proto__ pass pefile's name rule but
resolved inherited object members, throwing before the ord<n> fallback.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ra7LM2NyQ7DumdssxbUq5g

* fix(native): preserve PE import facts and prove hash compatibility

* test(native): verify PE import workflows and measured costs

* refactor(native): narrow PE facts across the container union

* docs(native): record integrated PE import validation

* fix(native): bound every PE import RVA span

* docs(native): measure RVA guard completed workflows

* fix(pe): reconcile import coverage with retained rows

* fix(pe): retain partial imports at descriptor mapping gaps

---------

Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
2026-10-24 11:44:12 +08:00
morluto 0b1af48a37 fix(protobuf): preserve MIME admission and transport facts
Parse MIME parameters once with strict quoted-value and duplicate handling,
and compare equivalent default binary profiles. Keep excluded HAR MIME
unknown, explicit framing independent, and nominal gRPC sanitization intact
across malformed or repeated declarations.

Add public CLI/MCP and native-header regressions with source identity and
partial-coverage assertions. Preserve upstream wire and schema admission.

Fixes #6836
2026-10-24 06:24:55 +08:00
morluto 53601d0bdf merge: consolidate upstream identity and representation owners 2026-10-24 05:13:41 +08:00
morluto a8fc3307cd fix(protobuf): own descriptor file identity before registry admission
Coalesce equal parsed file definitions and reject conflicting same-name definitions before registry import resolution. Preserve field presence, known and opaque facts through one budgeted SDK parse while retaining original descriptor bytes and digest.

Keep unique files in their original order, reuse the existing admission traversal, and cover public CLI/MCP import, ordering, presence and source-provenance controls. Document REA ambiguity policy separately from protoc precedence.
2026-10-24 05:05:22 +08:00
morluto d13a036e34 fix(reconstruction): retain scoped unknowns in overall claims
Select active constituent-dimension unknowns for an overall comparison claim while preserving comparison identity and exact scope for individual claims. Use the same selected facts for classification, citations, limitations and recommended probes; remove redundant aliases.

Cover stdio MCP registration, aggregate and independent claims, resolved latest revisions, source provenance and foreign comparison scopes.

Fixes #6879
2026-10-24 05:05:22 +08:00
morluto 3e3c9eadb5 fix(protobuf): reject ambiguous descriptor identities
Validate message-local field numbers and fully qualified registry identities during existing descriptor admission before constructing the schema registry. Preserve repeated wire occurrences, enum aliases and independent scopes, with bounded name allocation and retained capture provenance through CLI/MCP refusals.

Fixes #6834
2026-10-24 04:42:09 +08:00
morluto 62f7b5e4cd fix(native): require observed symbol origin for named identity 2026-10-24 04:14:17 +08:00
morluto 8b7de17833 merge: reconcile upstream boundary and format fixes 2026-10-24 03:59:44 +08:00
morluto 254a8e7018 fix(capture): own HAR schema and response interpretation
Correct the pinned HAR schema's missing object types and duration constraints at the shared decoder boundary. Preserve optional omission and the -1 sentinel without repairing producer measurements, and identify the owned corrections in decoder provenance.

Keep unsupported or redacted response encodings unavailable to replay and state extraction. Empty-response classification now uses the same body owner, preserving known empty content separately from unavailable content. Regenerate contract examples from decoded fixture bytes and the shared view service.

Validation: focused decoder, replay/state, CLI and MCP regressions, including unselected malformed records and confirmed write responses. Contract examples reproduce through MCP. Authored capture controls do not establish real-browser producer coverage.

Fixes #6890
Fixes #6889
2026-10-24 03:06:58 +08:00
morluto 65e423eba6 fix(browser): compare script and tool facts without metadata identity churn 2026-10-24 02:50:16 +08:00
morluto f8876e5405 fix(native): attribute deferred Evidence input failures 2026-10-24 02:45:14 +08:00
morluto b3c3b21e43 fix(protobuf): preserve wire grammar and schema admission facts 2026-10-24 02:35:58 +08:00
morluto a0c22ff012 fix(browser): preserve correspondence and uncertainty in capture comparisons 2026-10-24 01:47:31 +08:00
morluto 99d2d7ad22 fix(parsers): retain independent facts and boundary identity
Share bounded ELF section-name decoding across native and note readers; retain read-only ranges and coverage reasons when names are unknown. Preserve ELF symbol-version bytes, dyld-bound method uncertainty, partial gRPC-Web trailers, and per-parent model identity checks. Compare GPU signatures as bytes and require a PTX module header. Share selected-path errno classification across EVM and BEAM.

Validation: 397 shared-parser tests passed (one existing skip), 5 MCP schema tests passed, 14 EVM error-mapping tests passed, and 23 protobuf CLI/MCP matrix cases passed across focused runs. Build, typecheck/lint, docs, formatting, and 2134-file discovery passed. Full EVM provider workflow remains locally unverified on Darwin arm64; format controls are synthetic.

Fixes #6738
Fixes #6737
Fixes #6745
Fixes #6740
Fixes #6749
Fixes #6747
Fixes #6739
2026-10-23 22:18:43 +08:00
morluto 4524bbd8df fix(qlog): mark records with unknown STREAM FIN incomplete
Keep known STREAM ranges and the unknown FIN value, while listing the source event among incomplete fact records so summary and retained views agree.

Fixes #6598
2026-10-23 19:07:46 +08:00
morluto 6b7aa124ed fix(native): own matching source validation and admission
Separate source corruption and selected-role errors from unexpected derivation failures. Normalize coordinates before body membership and conflict checks, reuse parsed requests, and account for outer observation arrays before validation copies.
2026-10-23 07:27:15 +08:00
morluto 0281d10130 fix(mobile): share authenticated inventory projection sources
Authenticate inventory requests once before family projection, remove obsolete schema aliases and raw facades, and preserve unresolved occurrence references from partial pages without fabricating content identities.
2026-10-23 06:40:25 +08:00
bea6b98e84 test: prefer structured assertions over recovery prose (#6379)
* test: prefer structured assertions over recovery prose

Lock regex, IDA, Hopper/Kuna, MCP budget, capture-heap, and pcap
failures on error codes and reported limits instead of full recovery
sentences.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* test: keep decoder heap negatives off the Windows reserve

"512 MiB" also appears in the Bun Windows reserve sentence. The
negative check stays on "512 MiB (source setting)", which is the other
adapter's heap.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* test: keep the one-retry cap and deadline recovery tokens

The lost-connection guidance must say once only, so an unlimited
"whenever it is safe" rewrite fails. Deadline recovery still has to
name set, restart, the floor, and the maximum constant.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* test: keep heap, MCP, pcap, and preload recovery tokens

Codex still wanted the set/restart/floor/maximum heap guidance, MCP
default/floor/maximum bounds, Wireshark install guidance, and the
dropped-preload attribution limit as separate tokens.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* test: keep shared-context and transport recovery tokens

Shared-context capture must still exclude requests without a known root
or descendant frame. Shutdown must end the REA process before starting
again, and a failed HTTP listen must offer another port or stopping the
process that holds it.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* test: keep handoff, input-check, and budget format tokens

Skill and server guidance must still tell the user to restart the MCP
client. Process failures must still say to check the input files. Invalid
MCP phase budgets must still say positive decimal integer and ms.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* test: bind budget floors and active deadline sources

The phase-budget minimum is the start of "from N to M ms", so a digit
inside the maximum no longer satisfies it. Capability text must contain
the active "N ms (source ...)" pair, not the default number and a heap
source mentioned apart.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* test: bind heap MiB sources and pcap host tokens

A configured 256 MiB request must appear as "256 MiB (source setting)",
so a byte-sized 256 no longer passes. Unsupported pcap hosts must still
name Linux, util-linux, Windows, and owned Job Objects as separate tokens.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* test: bind the selected decoder heap to MiB and source

The two-adapter limitation must contain "256 MiB (source setting)".
The exhaustion message binds that capacity as "256 MiB V8 old-generation
heap (source setting)", so a byte-sized 256 no longer passes.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* test: bind doctor client seconds and prlimit absolute guidance

Doctor recovery must name startup_timeout_sec of the policy's seconds,
so a hardcoded 60 no longer passes while the policy stays 30. A relative
prlimit must say the value must be absolute and tell the user to check
REA_TSHARK_PRLIMIT_COMMAND.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* test: assert integrity codes for rehashed evidence and coverage

Independently rehashed process Evidence and a tampered digest project
evidence_integrity_mismatch. An unsupported comparison operation stays
invalid_request. Unsupported inventory coverage status is an integrity
failure whose reason carries the coverage.status schema issue.

Co-authored-by: morluto <morluto@users.noreply.github.com>

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: morluto <morluto@users.noreply.github.com>
2026-10-23 04:47:39 +08:00
306ed79932 feat(captures): make the HAR/SAZ/qlog decoder heap configurable (#6299)
* feat(captures): make the HAR/SAZ/qlog decoder heap configurable

REA_CAPTURE_DECODER_OLD_GENERATION_MIB keeps the 192 MiB default and
refuses values outside 8 to 16384 MiB instead of falling back.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(captures): defer decoder startup and share one parsed heap

Invalid REA_CAPTURE_DECODER_OLD_GENERATION_MIB threw while CLI commands
were registered, so doctor and help never ran. Build the capture service
only when inspect-web-network-capture runs.

Resolve the heap once in composition and pass that fact to each Node
adapter. Limitation and memory-failure reports use the selected adapter's
heap, so a decoder built with a different environment does not describe
another limit.

Mock captureDecoderProcessMemoryLimitBytes in the Node adapter test so a
Windows Bun host still exercises the unavailable-bound refusal.

Co-authored-by: morluto <morluto@users.noreply.github.com>

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: morluto <morluto@users.noreply.github.com>
2026-10-22 23:52:21 +08:00
2c3dd946d5 feat(python): inspect CPython pyc headers and marshal code objects (#4826)
* feat(python): inspect CPython pyc headers and marshal code objects

Add inspect_python_pyc / inspect-python-pyc to read one explicit local
CPython 3.7–3.13 .pyc without executing bytecode or recovering source.

* chore(python): drop unused PythonPycHeader export

Knip reported the type as unused after inspect_python_pyc landed.

* fix(python): bound pyc expansion and decode marshal like CPython

- Count a nested code object reached through TYPE_REF once per copy the
  report carries, against max_objects and max_file_bytes, before counting
  or validating the tree
- Charge long digits to max_string_bytes, reject out-of-range and
  unnormalized digits, build the value in one pass, and report integers
  above 256 bits by bit length only
- Decode TYPE_UNICODE with surrogatepass semantics and reject other
  ill-formed UTF-8
- Map only 3.11 magics 3494-3495 to the py311 layout
- Report non-finite float and complex parts as inf, -inf or nan
- Allow an empty co_filename
- Require bytes for co_linetable and co_exceptiontable
- Bind cleanup-failure errors to their retained descriptor leases

* fix(python): list pyc code objects once instead of a recursive tree

Report each distinct code object once in code_objects, top-level first,
with nested_code as indexes. A child shared through TYPE_REF is no longer
copied per reference, and the MCP output schema is no longer recursive.
Names repeated through TYPE_REF still count against max_file_bytes for
each copy the report carries.

* fix(python): bound shared pyc constants and reject malformed tables

- Cache byte-string digests so a buffer shared through TYPE_REF is
  hashed once instead of on every reference.
- Charge every reported co_consts entry, including tables shared
  through TYPE_REF, against max_objects before summaries are built.
- Resolve the inspect-python-pyc path with absoluteCallerPath so
  link/../file.pyc reads the file the filesystem selects.
- Reject TYPE_NULL inside marshal sequences, as CPython does.
- Reject a co_localspluskinds length that does not match
  co_localsplusnames in the parser and the report schema.

* fix(python): bound shared pyc names and read CPython marshal graphs

Charge each reported code-constant name, keep integer bit lengths on the
decoded value, and list code objects nested inside constant containers.
Accept self-referential lists and dicts, marshal version 0 text floats,
empty code names, the original string byte count, and Python set and dict
lengths. Pass the CLI cancellation signal into command cleanup.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(python): bound pyc key expansion and shared nested code

Charge set and dictionary keys before a shared tuple doubles them, list each
nested code object once per owner, and accept code objects as CPython keys.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(python): correct pyc equality, counts, and nested walks

Summarize code objects only after the marshal graph is complete, and
collect nested code with an iterative walk that shares wrapper results
instead of copying every descendant list. Keep tuple boundaries and the
original string bytes in equality keys, and reject negative CPython counts.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(python): bound shared pyc names and keep the first dict key

Charge every copied name-table entry against the object budget before
building the report array, including empty strings that add no bytes.
When dictionary keys compare equal, keep the first key object and
replace only its value, matching CPython.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(python): walk each pyc dictionary child list once

Keep a container's child array on the nested-code frame so a wide
dictionary is not copied on every step of the synchronous marshal walk.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(python): reuse stored pyc dictionary children when combining

The nested walk keeps each container's child list on its frame.
Combining nested code rebuilt that list, and the 8,000-key regression
still accepted the old per-key copy. Use the stored list, and require
that dictionary to finish well under the copy's runtime while still
reporting a nested code object.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(python): keep distinct pyc code objects and reject corrupt ones

Encode each name table's length and entry boundaries in the equality
key so a different name list cannot share a memo key. Walk tuple and
frozenset keys on an explicit stack so a long TYPE_REF chain does not
overflow. Treat code objects CPython rejects for an odd co_code or an
undersized local table as malformed instead of complete coverage.

Co-authored-by: morluto <morluto@users.noreply.github.com>

---------

Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: morluto <morluto@users.noreply.github.com>
2026-10-22 19:00:08 +08:00
bfba99827e feat(erlang): inspect BEAM IFF chunks and tables (#4833)
* feat(erlang): inspect BEAM IFF chunks and tables

Replay the Erlang BEAM inspection workflow, including table bounds,
OTP 28+ atom layouts, the shared absolute-path policy, and empty-path
CLI coverage, without carrying GitHub workflow edits.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(erlang): use publicInputStrictObject for BEAM tool input

inspect_erlang_beam advertised a public input built with bare
z.strictObject, so later shared input-policy changes would miss it.
Result and internal objects stay on their own constructors.

Co-authored-by: morluto <morluto@users.noreply.github.com>

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: morluto <morluto@users.noreply.github.com>
2026-10-22 17:46:15 +08:00
ca4ca65c5e feat(pe): inspect Authenticode certificate tables (#4830)
* feat(pe): inspect Authenticode certificate tables

Add inspect_pe_certificates for IMAGE_DIRECTORY_ENTRY_SECURITY
WIN_CERTIFICATE entries and structurally decoded PKCS#7 signer
and X.509 identity fields. The workflow reads a stable PE image
without executing it or verifying signatures, chains, timestamps,
or Authenticode digest coverage.

* fix(pe): bound and validate certificate DER decoding

- Cap decoded DER values with a shared node budget so sibling fan-out
  cannot exhaust memory before the PKCS#7 check
- Require SignedData version, encapContentInfo and a final signerInfos
  SET in RFC 5652 order, and a signature OCTET STRING in each SignerInfo
- Decode OBJECT IDENTIFIER arcs as unbounded base-128 values, including
  a multi-byte first combined arc
- Decode UniversalString names as UTF-32BE and reject invalid values
- Share PE header admission with the resource layout so a section table
  that does not fit SizeOfHeaders is rejected

* docs: list PE certificates in the translated READMEs

* fix(pe): cap OBJECT IDENTIFIER length and arc size

A crafted type-2 certificate with a 262,144-byte contentType OID stalled
decodeOid for about 20 seconds, because one arc kept growing a BigInt
before the signedData check ran. decodeOid now rejects an OID longer than
256 bytes and an arc longer than 32 bytes before decoding it. Certificate
OIDs, including 2.25 UUID arcs, fit under both caps.

* fix(pe): reject truncated certificate tables and PKCS#7

SignedData now requires one SignerInfo with a non-empty signature and a
complete issuerAndSerialNumber. Certificate names share a 64 KiB decoded-byte
budget and are copied once. A security directory that ends in a short
WIN_CERTIFICATE header fails instead of reporting a complete table. The
certificate CLI forwards the caller abort signal into cleanup.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* chore(ci): keep fork workflow files unchanged

The certificate restack follows current main. Workflow files stay at the
fork tip so this branch update does not rewrite .github/workflows.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(pe): charge serial and validity text to the decoded budget

Certificate and signer serial numbers and validity times now count against
the shared decoded-text budget before they are converted, so a crafted
certificate cannot push megabytes of text into the hashed evidence. The
budget error now names certificate text rather than only names.

Restore the CI workflow to match main: the CI_TIMING_TIER input, the
tier-named timing artifacts and their publication conditions, the Windows
typecheck, and the path and snapshot suites in the curated Windows lane.

* fix(pe): require certificate fields and preserve signer key ids

Reject X.509 records that omit subjectPublicKeyInfo or signatureValue,
return subjectKeyIdentifier bytes as bounded hex, and advertise an absolute
path in the PE certificate input schema.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(pe): reject extra PKCS#7 wrappers and invalid UTF-8 names

ContentInfo and its signedData wrapper no longer ignore trailing values, and
directory strings must round-trip as UTF-8 instead of becoming U+FFFD.

Co-authored-by: morluto <morluto@users.noreply.github.com>

---------

Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: morluto <morluto@users.noreply.github.com>
Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
2026-10-22 17:20:07 +08:00