Commit Graph
151 Commits
Author SHA1 Message Date
YsopwnableandOlorinm f611d8ce72 feat(captures): inspect recorded packets with bounded TShark delivery (#2318)
Inspect selected fields in existing captures through shared CLI/MCP Evidence.
Page matching frames without changing dissection or two-pass read coverage;
retain failed descriptor/process cleanup ownership and reject excess admission.

Verified with real TShark 4.0.17 and 4.2.2, public Wireshark recordings,
owned HTTP application traffic, real CLI/MCP workflows and schema checks.

Co-authored-by: Olorinm <59321404+Olorinm@users.noreply.github.com>
Assisted-by: Kogasa (gensokyo-skills:kogasa-surprise-testing)
2026-10-12 19:35:35 +00:00
morluto 570c40cde5 fix(cli): preserve failure semantics across full-output formats 2026-10-13 03:33:27 +08:00
morluto 2397137615 fix(setup): honor config roots and display terminal dry-run plans
Normalize empty XDG config homes once for configuration writers and registration readers. Render the resolved plan for terminal dry runs while preserving structured output. Cover registration placement and a real PTY dry run, including absence of configuration writes.
2026-10-13 03:22:53 +08:00
morlutoandLouisChen bb26622670 fix(cli): retain correction details across adjacent browser commands (#2294)
* fix(cli): retain correction details across browser commands

Fold the complementary implementation from #2247 into the earlier #2230 proposal, retaining the original contribution history.

Co-authored-by: LouisChen <3361008+chqcjq@users.noreply.github.com>

* fix(browser): retain diagnostics from the selected input branch

* fix(cli): recognize incomplete browser scenarios by their owned fields

---------

Co-authored-by: LouisChen <3361008+chqcjq@users.noreply.github.com>
2026-10-13 02:55:59 +08:00
YsopwnableandY0UW1SH aeee5074d1 feat(sqlite): inspect offline snapshots with selective evidence (#2271)
Add offline SQLite database/WAL inspection through the shared CLI/MCP.

Use compact inventory, selected-table schema, exact ordered columns and
bounded row samples while preserving source identity and lossless values.
Retain completed Evidence through late cancellation and private-root cleanup
failures, bound concurrent inspections, and recheck journal validity after
acquisition. Reuse prepared CI runtime artifacts across supported Node lines.

Co-authored-by: Y0UW1SH <29498139+Y0UW1SH@users.noreply.github.com>
Assisted-by: Kogasa (gensokyo-skills:kogasa-surprise-testing)
2026-10-12 18:33:23 +00:00
No BS AI 916ac97bf9 fix(cli): retain browser and Inspector input correction details (#2230)
Reuse the shared safe issue projection for all six CLI validation boundaries
and cover malformed inputs, credential safety, and parser diagnostics.

Fixes morluto/rea#2180

Developed with assistance from OpenAI Codex.
2026-10-13 02:29:07 +08:00
Yijie Luandmorluto 11fe5a13f8 fix(native): retain failed pwntools process and runtime cleanup (#1708)
* fix(native): retain failed pwntools process and runtime cleanup

Keep failed worker/debugger cleanup owners and their private files until
verified process shutdown and successful directory removal. Retry cleanup
before another inspection and expose shutdown through the shared services,
CLI and MCP server. Serialize acquisition without delaying cancellation of
queued callers, and preserve primary diagnostics when CLI cleanup fails.

The original decoder reproduction left a live owned Node child with its
runtime deleted and no retained cleanup owner; the regression now verifies
retention, admission blocking, retries and eventual process/file cleanup.

Validation: 10 lifecycle/public CLI/MCP tests, 20 service tests, test
discovery 814/814, build:cached and full check including architecture guards.
Actual POSIX process/filesystem boundaries used injected Node workers on
macOS; real Linux pwntools/GDB provider parsing was not exercised.

* test(native): verify retained recorded-crash cleanup lifecycle

* fix(native): finalize diagnostic cleanup before publishing results

* fix(native): retire decoder stages before reading runtime evidence

---------

Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
2026-10-13 01:37:47 +08:00
Ysopwnableandfactory-droid[bot] ad08510a11 refactor(evm): bind offline analysis through a static descriptor
Bind existing EVM CLI/MCP metadata and the legacy service factory through one static descriptor, and register the same selected service that owns cleanup. Preserve original names, schemas, inputs/full defaults, configuration, Evidence and injection identity.

Verified exact SDK catalog/fact parity across six real EVM pairs, 59 actual EVM CLI/MCP cases, six real cross-domain workflows, six actual Codex CLI fact/reference/lifecycle trials and relevant local checks. CI run 38283026233 succeeds for exact head d999d9874b. No token reduction from wiring or fully qualified resource claim; final counters remain unknown. Continues #2016.

Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
2026-10-13 01:26:43 +08:00
Kaoru0822andClaude Opus 5.5 86de439ba4 fix(frida): name the argument each Frida input error rejects (#2217)
Frida session lookups, script lookups, unreadable script files and the
instrument-with-frida PID and script checks returned invalid_request with
no issues, while the remediation told callers to correct the listed
arguments. Attach the session_id, script_id, path, target or script issue
with the reason so CLI and MCP callers can see what to fix.

Fixes #2213

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 23:00:59 +08:00
e4d3e1399d feat(flutter): identify Dart snapshot builds and inspect AOT payloads by pure APK parsing (#1582)
* feat(flutter): identify Dart snapshot builds by pure APK parsing

Add a flutter-provider family with one operation, identify_flutter_build,
that reads an APK's lib/<abi>/libapp.so and libflutter.so through the
hardened ZIP reader and reports build facts as observations:

- The Dart VM snapshot hash, read 20 bytes after every snapshot magic
  (f5f5dcdc). The vm and isolate sections are cross-checked: agreeing
  sections collapse to one snapshot_hash, disagreeing sections keep every
  candidate with snapshot_hash null and partial coverage.
- Per-ABI library digests and byte sizes, plus the engine library's GNU
  build-id note and any labeled 'Dart VM version' or Android clang/LLVM
  toolchain strings, verbatim; release builds without a version string
  report null rather than a guess.
- The APK is digested before parsing so Evidence binds the observation to
  the exact input, and a target with no libapp.so reports not-detected
  with complete coverage.

The scanner is streaming with explicit pending-magic and rescan
bookkeeping, so chunk boundaries cannot double-count or drop sections, and
magic-free streams never accumulate. No engine, no external lookups: the
hash-to-SDK mapping stays with external datasets by design.

Verified against Flutter Gallery 2.9.2 (112 MB, three ABIs): every ABI
reports the same agreeing hash 65817c30a78bb44c3dc3771876b6010a from two
sections, per-ABI build-ids, and the clang toolchain line; a plain
aapt2-built APK reports not-detected with complete coverage. Scanner
goldens come from the same libraries. READMEs carry the new 'Flutter apps'
row in every supported language.

* feat(flutter): inspect Dart AOT snapshots through the ELF symbol table

Add inspect_dart_aot to the flutter family: for one ABI's libapp.so it
locates the four _kDart*Snapshot* symbols through the ELF dynamic symbol
table (ELF32 and ELF64 little-endian, bounds-checked reads; a payload
without exported symbols is refused), reports each section's offset and
size, validates data-section headers (magic, kind, length; instructions
sections honestly report nulls for the fields their layout does not
carry), and projects a bounded string pool from the isolate data section:
distinct package: source URIs (the app's dependency inventory), dart: SDK
URIs, and identifier-shaped tokens, each with counts, bounds, and partial
coverage when truncated.

The string pool is labeled as a byte-pattern projection, not deserialized
cluster semantics: typed class and function recovery remains an
SDK-specific parser, which the snapshot hash now unlocks. The ABI is
caller-selected with a deterministic default (arm64-v8a, x86_64, then
first available).

Verified against Flutter Gallery 2.9.2: all four symbols on both ELF64
(arm64-v8a) and ELF32 (armeabi-v7a) images, header validation, hash
agreement with identify_flutter_build, and a 756 package: / 201 dart:
URI pool from the isolate data section; goldens in DartElf.test.ts come
from the same libraries.

* fix(flutter): own snapshots, bound image reads, and preserve cancellation

Mirror the ownership bar the maintainers applied across the merged JEB,
ADB, and Apktool PRs:

- Copy the admitted APK into a provider-owned, read-only snapshot (EXCL
  create, chmod 0400) before digesting and parsing; every later read uses
  the snapshot, so a concurrently modified original cannot mix into one
  observation. The result reports the snapshot's byte size and digest.
- Retain failed snapshot-root cleanup in a provider set and retry it on
  close(), throwing an aggregate error when a root is still owned; root
  removal is injectable so the retention is testable.
- Allocate the AOT image buffer at exactly the declared library size
  before reading (bounded before allocation, not concat-after-stream),
  keep the 256 MiB ceiling, and check cancellation between digest and
  stream chunks through a captured abort reason.
- Accept APK paths containing spaces (covered by a fixture test) and
  escape the ABI pattern's dash for v-mode regex compatibility.

Also add tests for cleanup retention with close retry and for
cancellation before any snapshot root is created.

* docs(flutter): cover the Italian README with the Flutter row

The Italian translation landed between the merged feature PRs; its table
now carries every merged row plus this one, keeping its documentation-link
set identical to README.md.

* fix(flutter): make the ABI pattern portable for v-mode validators

Use a hex-escaped hyphen in the ABI character class, matching the form
the ADB portability fix uses, so clients compiling advertised schemas in
unicodeSets mode accept the inspect_dart_aot input schema.

* refactor(flutter): reuse shared harnesses and deduplicate the vertical

The duplicate-detection gate (jscpd, 2.5% threshold) tipped to 2.51% with
the flutter files added. Reuse the existing machinery instead of repeating
it:

- FlutterBuildAnalysisService delegates to executeProviderOperation, the
  shared admission/Evidence composition, instead of restating its body.
- The CLI registers both commands from one table-driven spec.
- Boundary tests use the shared serveCli and assertAdvertisedMcpContracts
  harnesses rather than hand-rolled equivalents.
- The provider test consolidates the four payload-shape cases into one
  table-driven case; the service test uses one admission table and
  distinct phrasings.

Duplicate lines fall from 2.51% to 2.48%, back under the gate.

* fix(flutter): address review findings from real-app verification

CassieFox23 verified the PR against three real F-Droid Flutter apps and
a control app, and found five gaps. All are fixed and re-verified against
cone (info.tangential.cone), one of the tested apps:

- Build-id: the scanner now reads the descriptor length from the note
  header instead of assuming 20 bytes, so 8-byte ids from older
  toolchains parse; the schema accepts 8-128 hex characters. Verified
  against cone's readelf-reported ids on all three ABIs.
- Compiler line: the toolchain capture bound rises from 200 to 500
  characters, keeping cone's 262-character clang line verbatim.
- Zero-byte libapp.so: the extraction target is created before streaming,
  so an empty entry yields a clean unsupported_target refusal for
  inspect_dart_aot and elf_header_valid: false with partial coverage for
  identify_flutter_build, instead of a raw ENOENT with code UNKNOWN.
- Truncated library: identify_flutter_build marks fewer than two snapshot
  sections as partial coverage with a limitation naming the count, and a
  missing ELF magic gets its own limitation.
- Docs: the default ABI preference now matches the code exactly
  (arm64-v8a, x86_64, x86, armeabi-v7a, then the rest alphabetically).

Also: every test that read the author's /tmp/opencode goldens now builds
a self-contained synthetic ELF64 image with dynsym, four snapshot
symbols, two snapshot sections, and a string pool, so the suite runs
anywhere; the verify lane now requires a present hex build-id per ABI
instead of accepting null.

* fix(flutter): address the Codex review findings

Eight findings, all applied:

- P1: SnapshotHashScanner keeps candidates in a Set (no quadratic
  Array.includes) with a 64-distinct-hash cap, so a hostile payload of
  magic+hash records cannot stall the scan or bloat the response.
- P1: projectStringPool stops admitting new distinct entries once each
  category reaches twice its projection bound and reports
  collectionCapped; allocation and sorting now track the response, not
  the payload.
- P2: ZIP reader rejections during entry iteration or entry streaming
  map into the typed error algebra (cancellation vs input refusal)
  instead of escaping as unhandled exceptions in both operations.
- P2: magic_valid now marks coverage only for the *Data symbols; a
  complete four-symbol image with valid data magics reports complete
  coverage (the instruction symbols intentionally lack the magic).
- P2: the MCP server closes the Flutter provider during shutdown, so a
  retained snapshot root is retried and reported, not leaked.
- P2: LabeledStringScanner commits matches only when a printable run is
  delimiter-terminated; the carry grows to 600 bytes so a 500-character
  toolchain line survives any chunk boundary untruncated.
- P2: both Flutter tool effects declare writesFilesystem: true; the
  owned APK snapshot and extracted libapp.so are temporary writes.
- P2: the verify lane asserts every ABI agrees on exactly one snapshot
  hash instead of discarding the computed set.

* fix(flutter): address the second Codex review round

Nine findings on the first-round fixes:

- P1: identify_flutter_build enforces a cumulative extraction budget
  (768 MiB) across every library entry, not just per library, so an APK
  with many ABIs cannot stream an unbounded total.
- P1: a single NUL-free printable run stops materializing at 1024 bytes
  and marks the pool capped, so an adversarial one-run section cannot
  allocate unbounded strings.
- P1: ELF cString bounds the NUL-terminator scan to the name maximum
  plus one, so malformed symbol tables cannot scan the whole image per
  entry.
- P2: mapReaderFailure distinguishes ArtifactReaderFailure texts —
  budget/limit rejections map to resource constraints, integrity
  failures (CRC/overlap/signature) to their own input refusal — instead
  of collapsing all reader failures into one message.
- P2: the labeled-string carry is cleared when a delimiter commits a
  run, so consecutive toolchain lines are never concatenated.
- P2: string-pool counts are renamed *_count_at_least and documented as
  lower bounds, because capped collection discards values beyond twice
  the projection bound.
- P2: inspect_dart_aot marks hash disagreements, non-pair source counts,
  and candidate-cap saturation as partial coverage.
- P2: only valid lowercase-hex hash records count as snapshot sources;
  complete magic records with non-hex fields do not inflate agreement.
- P2: the per-entry size refusal in inspect_dart_aot moves after ABI
  selection, so an oversized unselected ABI no longer refuses a small
  request.

* fix(flutter): address the third Codex review round

Five findings:

- P2: the owned snapshot revalidates the source after the copy (size,
  mtime, inode), so an in-place replacement or swap mid-copy refuses
  the observation instead of publishing mixed bytes.
- P2: a failed ZipArtifactReader close retains the snapshot root for
  close() retry instead of silently swallowing the descriptor leak,
  in both operations.
- P2: snapshot headers are parsed within their symbol bounds and a
  symbol smaller than the 16-byte header reports magic_valid false,
  so trailing-image bytes can no longer fake a valid data section.
- P2: the verify lane counts provider.close() cleanup failures as
  lane failures instead of certifying a run with retained roots.
- P2: LabeledStringScanner reports toolchain_capped when further
  distinct matching lines are observed past the 4-line projection;
  identify marks such results partial with a naming limitation.

* fix(flutter): address rounds three and four of the Codex review

Round three (one missed finding) plus round four (five findings):

- P2: the GNU build-id note descriptor size is decoded from all four
  bytes of the little-endian field, rejecting nonzero high bytes
  instead of masking them to 16 bits.
- P1: the Flutter MCP handlers route through createContractToolHandler
  and the session's analysisAdmission, so close_binary and snapshot
  operations drain in-flight Flutter calls instead of racing them.
- P2: the owned-snapshot copy is a streamed, abort-checked write (no
  copyFile), so cancellation stops the write promptly while the
  source-identity revalidation (size, mtime, inode) still guards
  against mid-copy replacement.
- P2: identify marks any snapshot_hash_sources value other than exactly
  two as partial, matching the inspection path's pair requirement.
- P2: the verify lane refuses to run without --apk (exit 2) instead of
  printing a false-green pass, and the engine check requires every
  libapp-carrying ABI to have a present libflutter with a valid hex
  build-id rather than filtering missing engines away vacuously.

* fix(flutter): address the fifth Codex review round

Six findings plus the upstream duplication baseline:

- P2: the flutter-provider kind reports available in the capability
  inventory, so binary_session no longer lists always-registered
  Flutter tools as provider_missing.
- P2: printable runs that exceed the 1024-byte cap are discarded at
  their delimiter instead of emitting their truncated prefix as a
  fabricated observation.
- P2: ELF symbols must fit inside the file-backed portion of their
  PT_LOAD segment (p_filesz), so addresses in gaps or BSS are refused
  instead of accepting unrelated bytes.
- P2: the build-id carry spans the complete 80-byte maximum note
  (16-byte header + 64-byte descriptor) so chunk-boundary splits
  cannot drop the first byte.
- P2: the labeled-string carry is sized for the toolchain pattern's
  true 605-byte maximum, not the previous 600.
- P2: the AOT completeness predicate requires exactly two sources and
  one candidate unconditionally, so zero-source images with valid data
  magics report partial instead of complete.

Also: the shared ELF fixture builder and snapshot-section helper moved
to a dedicated FlutterTestFixtures module, eliminating cross-file test
duplication; jscpd now passes at 2.50% while main sits at 2.52%.

* fix(flutter): address the sixth Codex review round

Five findings:

- P2: snapshot-hash scanning is bounded to the exported data symbols'
  byte ranges, so decoy or stale magic/hash sequences elsewhere in the
  image cannot inflate source counts or contribute candidates.
- P2: labeled-string runs longer than the carry bound are rejected
  instead of truncated, preventing a regex prefix from being published
  as a verbatim source string.
- P2: the AOT image reread checks cancellation between file reads and
  before the synchronous parsing stage, so a cancelled caller cannot
  receive a success from a completed 256 MiB read.
- P2: the verify lane requires exactly two snapshot sources per ABI,
  matching the provider's pair requirement, instead of accepting any
  count >= 2.
- P2: ELF section and program header entry sizes are validated against
  the class-defined minimum widths before walking either table, so
  undersized entries cannot cause field reads to cross into
  neighboring bytes.

* fix(flutter): address the seventh Codex review round

Six findings:

- P2: data-symbol ranges are deduplicated by offset and size, so aliased
  symbols mapping to the same bytes are scanned once and the result
  marks partial coverage with a limitation naming the shared range.
- P2: openEntrySafely forwards return/throw to the underlying Readable's
  iterator, so an early for-await exit closes the ZIP entry stream and
  releases its producer instead of leaking a backpressured pipe.
- P2: inspect_dart_aot now reports snapshot_hash_candidates and
  snapshot_hash_sources alongside snapshot_hash, so a null hash from
  conflicting evidence is distinguishable from missing hash data.
- P2: overlong printable runs only set toolchain_capped when they begin
  with a recognized label prefix (Dart VM version: or Android (); other
  long strings such as license text are skipped without marking partial.
- P2: readElfSymbol falls back to PT_DYNAMIC/DT_SYMTAB when section
  headers are absent (e_shnum 0, ET_DYN), so stripped Flutter libraries
  with exported snapshot symbols are no longer refused; the dynamic
  table is bounded by DT_STRSZ, DT_SYMENT, and the image end.
- P2: the verify lane exercises inspect_dart_aot for every ABI carrying
  libapp.so, not just the preferred default.

* fix(flutter): address the eighth Codex review round

Five findings:

- P2: each data-symbol range gets a fresh SnapshotHashScanner so the
  carry from one noncontiguous slice cannot fabricate a record spanning
  into the next; results are aggregated after scanning.
- P2: dynsym name lookups are bounded to the linked string table —
  st_name offsets outside the table and terminators beyond it are
  rejected instead of reading unrelated payload bytes as symbol names,
  in both the section-header and PT_DYNAMIC paths.
- P2: identify_flutter_build routes its reader.entries and reader.open
  calls through the same collectEntriesSafely and openEntrySafely
  wrappers as inspect_dart_aot, so malformed ZIPs surface as input
  refusals instead of AnalysisProtocolError.
- P2: mapReaderFailure recognizes ArtifactReaderFailure texts carrying
  a cancelled reason, mapping them to AnalysisCancelledError instead
  of AnalysisInputError.
- P2: the cumulative extraction cap is enforced inside the chunk loop,
  not after each library completes, so refusal happens before the
  remaining bytes are streamed and hashed.

* fix(flutter): harden streaming, sizes, and cancellation after self-review

Four issues found in a systematic self-audit across all bug classes
from eight Codex rounds:

- createReadStream in both the digest function and the owned-snapshot
  copy now receives the AbortSignal directly, so cancellation aborts
  the filesystem read at the source instead of waiting for the next
  chunk to arrive on a slow filesystem.
- The owned snapshot enforces a 2 GiB APK-level size cap before any
  copy I/O, so a path pointing at an enormous file is refused before
  disk usage grows.
- identify_flutter_build preflights the sum of declared entry sizes
  against the 768 MiB cumulative budget, refusing before any ZIP
  extraction when the declared total already exceeds it.
- The LabeledStringScanner triple result() call is collapsed to a
  single invocation (the previous code called result() three times in
  the emission, relying on end() being idempotent).

No behavior change for valid inputs; all 36 tests, check:fast, and
the cone verify lane pass unchanged.

* fix(flutter): require structurally parseable ELF headers for complete coverage

CassieFox23's third corrupt-header case: an ELF with valid magic but
zeroed section/program header offsets passes the 4-byte magic check
and the byte scanner still finds hash patterns in the data sections,
so identify_flutter_build reports complete coverage for a structurally
broken file.

The elf_header_valid check now also verifies beyond the magic:
e_type must be a known value (ET_REL/ET_EXEC/ET_DYN), at least one
of e_shoff/e_phoff must be non-zero, and at least one of
e_shnum/e_phnum must be non-zero. A file with valid magic but zeroed
structure reports partial coverage with the existing ELF-magic
limitation.

* fix(flutter): validate ELF and snapshot coverage

Share bounded ELF header parsing between identification and inspection. Accumulate headers across ZIP chunks and validate table entry widths and extents before claiming complete identification coverage.

Bind AOT hashes to the exported VM and isolate headers, validate stored snapshot lengths including the magic bytes, and preserve partial evidence for missing, malformed, aliased, or overlapping data headers.

Preserve native stream cancellations and APK resource constraints across both operations. Bound snapshot copies while streaming and retain useful input-failure diagnostics and lower-bound count wording.

Validation: 72 focused tests; check:fast; check including formatting; docs:check; test discovery; jscpd; real cone APK and non-Flutter control on Linux. Verified CLI/MCP parity for valid and corrupted ELF headers and AOT inspection across three ABIs. Native Windows and macOS were not run.

* fix(flutter): unify artifact ownership and bound ELF evidence

* fix(flutter): preserve ELF provenance and partial coverage

Read GNU build IDs only from bounded ELF note ranges and retain conflicting candidates. Preserve source versus owned storage failures and honor cancellation through parsing and final cleanup.

Separate snapshot structure from string-pool coverage. Verify every Gallery ABI with digest-bound engine labels and URI counts, and document the supported snapshot-kind layout.

---------

Co-authored-by: REA Contributor <contributor@rea.tools>
Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
2026-10-12 22:35:55 +08:00
Daniel Gonçalves AraujoandN0zoM1z0 4a4ae9b2b9 feat: add Frida instrumentation support (#1359)
* feat: add Frida instrumentation support

* fix: resolve Frida CI checks

* test: cover Frida contract validation branches

* docs: link Frida instrumentation guide

* fix(frida): handle cancellation cleanup safely

* fix(frida): address PR review findings

* fix(frida): preserve resume and message observations

* fix(ci): use canonical registry for rolldown

* fix(frida): declare foreign code effects

* fix(frida): retain failed startup resources for cleanup retries

Keep failed startup session and spawn handles owned until detach, resume,
and remote lease cleanup complete. Serialize retries and release each
remote reference once. Await CLI provider cleanup while preserving the
primary failure and any completed observations.

Add regressions for retained startup resources, concurrent cleanup,
shared remote leases, and CLI cleanup outcomes.

Validation: 41 focused tests pass on the PR head and its latest-main
integration; serial static and docs checks pass. Real Linux Frida 17.23.2
workflows and the native spawn/controlled-failure cleanup probe pass.

Assisted-by: Kogasa (gensokyo-skills:kogasa-surprise-testing)

---------

Co-authored-by: N0zoM1z0 <1705004398@qq.com>
2026-10-12 22:01:58 +08:00
Ysopwnableandfactory-droid[bot] 58fb372071 feat(analysis): add opt-in retained inventory and WASM views (#2122)
Add opt-in retained inventory and WASM Evidence views with exact nested output contracts and a small static WASM descriptor. Preserve old complete CLI/MCP workflows, producer choices, original authenticated Evidence and cleanup ownership.

Validated with real public applications, genuine old Evidence migration, 123 focused assertions, 11 synchronized description checks and 42 installed-package WABT cases. Detailed generated experiment JSON stays outside the final tree; concise findings and reproduction inputs remain. Main-existing completion/package CI failures are separately attributed and left unchanged.

Refs #2016

Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
2026-10-12 21:17:52 +08:00
Kaoru0822andClaude Opus 5.5 60259a91d9 fix(managed): validate CLI type selections with the member contract (#2125)
`inspect-managed-members --type` accepted repeated and empty names that
the MCP contract rejects. The provider's contract parse then threw, and
the CLI reported execution_failure with advice to run `rea doctor`.
Reuse the contract's type_names schema so the CLI rejects them as a
validation error on --type.

Fixes #2121

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 19:26:32 +08:00
morluto 98d8470d36 fix(io): consolidate managed snapshots and retain cleanup ownership
Reuse managed snapshot admission and hashing in sequential path comparisons, retaining caller paths and completed inspection Evidence on later failure. Preserve exact failed-close owners alongside typed read and cancellation failures, and retry them through caller-owned resource scopes. Require canonical Hopper lease identities, remove signed offset coercion, and repair stale setup cleanup expectations that failed CI.
2026-10-12 14:46:37 +08:00
morluto d8c76b6296 fix(io): retain cleanup ownership and honor cancellation
Keep failed JSON read handles in the existing server resource scope and fail admission until cleanup succeeds. Thread cancellation through every process CLI input read and replace timer-driven cancellation checks with a shared first-read gate.

Classify authenticated standalone Evidence as wrong-kind input while preserving tampered-record integrity failures and actionable messages across ledger, CLI, and MCP consumers. Record unrelated CS_RESTRICT process neighbors as unverified without weakening related-process ownership checks. Update stale ADB fixtures for the actual shell protocol.

Validated focused CLI, MCP, filesystem, ownership, and error projection tests; static, docs, and duplication gates pass. The host-level CS_RESTRICT load reproduction was not run. Refs #2050, #2035, #2064.
2026-10-12 14:12:44 +08:00
4573e8cf35 fix(ghidra): recover stale clients on same-target reopen (#2014)
* fix(ghidra): recover stale clients on same-target reopen

* test(ghidra): allow supervised shutdown in health regression

* fix(ghidra): read process exit without diagnostic snapshots

Health and startup exit checks called the supervisor snapshot, which
concatenates retained launcher output only to read the exit code.

* test(adb): align fixtures with literal output and directory commands

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
2026-10-12 14:06:52 +08:00
morluto 48c352b6bf fix(cli): reuse firmware and web module input constraints
Derive extraction limits and web module fields from the shared contracts. Reject empty or NUL-containing local paths before CLI path resolution, preserve firmware relative-path handling, and apply the advertised extraction defaults.

Validate advertised JSON Schemas with Ajv and check the registered parser defaults; prune redundant schema-shape and description assertions.
2026-10-12 12:37:00 +08:00
You Wishandmorluto a1b5d51a8d feat(go): inspect embedded binary build metadata (#1363)
* feat(go): inspect embedded binary build metadata

* fix(go): preserve byte metadata and validate container mappings

* fix(go): support moduleless legacy build metadata

Recognize optional module string headers in declared zero-filled memory while rejecting ambiguous and unmapped pointers. Preserve the original module-pointer field as the zero-byte source anchor.

Classify initial symlink-loop and overlong-path failures as invalid input, with CLI and MCP regressions.

* fix(go): reject undersized PE optional headers

* fix(native): stabilize ELF memory checks and clean up exec wrappers

Use existing parent/group/run-token ownership for caller-selected Python launchers, which can exec through a shell or prlimit. Add cancellation regressions for the valid wrapper and wrong-parent/token cases.

Replace the timing-dependent 30,000-section memory workload with a valid 32 MiB padded ELF under a 64 MiB address-space limit. Check the same image successfully through CLI and MCP before requiring a typed memory failure, preserving the production timeout and all error assertions.

Validation: npm run check and check:fast passed; 61 focused tests passed including Go CLI/MCP and session snapshots. Real decoder probes with pinned packages passed on Python 3.12.3 and 3.12.14. The full local ELF verifier is blocked by this container's procps/process-ownership boundary; the exact pushed head requires GitHub's real-binary-layout lane.

* test: repair Electron fixtures and stabilize catalog startup checks

Declare Electron imports in option, preload override, and path-resolution fixtures after upstream began requiring proven API provenance. Retain all option and preload assertions and adjust exact source ranges for the added import line.

Use the existing bounded acceptance timeout for the cold catalog lifecycle test instead of a separate 15-second ceiling. This retains the coverage allowance and all catalog, error, and cleanup assertions without retries.

Validation: npm run check, final check:fast, formatting and diff checks passed. Source path regression and Go boundary/MCP/service checks passed. All 20 Go CLI cases and both supported-host runtime cases passed on rerun; two macOS-only cases skipped on Linux. A prior contended local run timed out once in a Go CLI diagnostic; that case passed on rerun. Electron process-boundary verification is blocked locally by procps namespace inspection and requires fresh CI.

* test(mcp): isolate nested schema references between tool contracts

Clear Ajv's non-meta schema registry after each root, including compilation failures. Disabling root registration alone leaves nested IDs available to later tools and can let a dangling reference pass the catalog gate.

Add regressions for leakage after successful and failed compilation while retaining shared meta-schema validators. The regression failed before the fix; all 11 schema cases and full npm run check pass. Reviewed independently.

* test(ci): align Go effects and source-map verification contracts

Audit the Go inspector wording as static metadata inspection. Assert retained source declaration indexes in BOM reconstruction and the compiler-derived nested-map oracle. Keep a 45,000-map admission control below the 32 MiB output budget and the 50,000-map overflow case above it with the expanded representation.

Validation: reproduced all four failing assertions, then passed 120 focused tests and the final admission suite. npm run check and real Chrome 154 / esbuild 0.25.10 source-map verification passed, including all four nested-map scenarios and verified process lineage.

---------

Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
2026-10-12 11:34:02 +08:00
DavidandDavid 87b9793c53 fix(javascript): trace wrapped Electron IPC paths in large bundles (#1874)
Co-authored-by: David <17119984+fengdwx@users.noreply.github.com>
2026-10-12 09:28:59 +08:00
a149d183ef feat(managed): select declaring types in inspect_managed_members
Select exact declaring types before managed signatures and CIL bodies are decoded, preserving caller choices in CLI/MCP Evidence. Keep unmatched names and selected coverage explicit; comparisons and graphs retain unknowns outside their observed scope. Reuse existing metadata ownership/accounting and advertise unique selections through the actual SDK Schema.

Validated with 229 focused tests across 21 files, 11 managed conformance controls, fullstatic/docs checks and real Linux CLI and fresh MCP inspection of two unchanged DLLs. All 118 selected CIL hashes matched original PE-mapped bytes; result/caller-argument parity and unmatched controls passed. Full artifact/native-boundary metadata is complete; whole-assembly members retain the unchanged 64 MiB resource constraint. No target code executes.

Refs #1878

Co-authored-by: skared <190618464+skoodster@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Ysopwnable <161784452+N0zoM1z0@users.noreply.github.com>
Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
Co-authored-by: Kaoru0822 <208281322+kaoru0822-kitauji@users.noreply.github.com>
2026-10-12 08:31:37 +08:00
morluto dcfc5d403a fix(setup): retain regular-file cleanup ownership through workflows
Thread the existing resource scope through skill and client configuration reads. Keep failed-close handles owned, wait for admitted reads, and surface unresolved cleanup alongside doctor, uninstall and update results.

Validated focused setup/doctor/update and filesystem boundary checks, temporary-file hygiene, packaged setup/update/uninstall workflows, and static checks. No external provider installation was performed.
2026-10-12 05:57:35 +08:00
morluto a82e37c806 fix(browser): retain module resolver cleanup ownership
Serialize resolution with shutdown, retain the owned browser after close failures, and retry cleanup before another launch. Wire cleanup through the shared service and CLI/MCP lifecycles, preserving primary failures and completed native reports alongside cleanup diagnostics.

Separate the browser resolution workflow from lifecycle ownership. Validation: seven resolver source tests, eleven application tests, MCP shutdown retry, public CLI parity, and full static/architecture checks passed. Real Chromium behavior remains unverified.
2026-10-12 04:44:25 +08:00
85c1d2587a feat(javascript): analyze selected application sources
Analyze exact selected sources in first-request order before unrelated
static scopes, preserving full artifact identity and byte verification.
Retain selection in CLI/MCP Evidence and summaries, with explicit unknowns
and partial coverage for unselected sources. Keep default full analysis.

Fixes #1848

Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
Co-authored-by: Kaoru0822 <208281322+kaoru0822-kitauji@users.noreply.github.com>
2026-10-12 04:07:14 +08:00
morluto bb508134ef fix(setup): verify independently selected skill destinations 2026-10-12 01:31:32 +08:00
Matt Van Hornandmorluto 7c207c7951 feat(native): admit raw binaries with caller-supplied architecture and entry (#1868)
* feat(native): admit raw binaries with caller-supplied architecture and entry

* fix(native): honor raw-binary preparation and entry identity

* fix(ghidra): stream raw snapshot attestation with cancellation

* fix(native): preserve and validate raw lifecycle entries

---------

Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
2026-10-12 00:06:29 +08:00
BaaRaiandmorluto f2150eb9a7 feat(harmony): project HarmonyOS package inventory evidence (#1447)
* feat(harmony): project HarmonyOS package inventory evidence

First HarmonyOS increment from #1431: HAP, HSP, and App Pack roots are
classified through the hardened ZIP reader and projected into an
execution-free application graph with packaging-model hints, exact
component paths and hashes, App Pack children by path, runtime-family
hints, and path-based N-API bridge hypotheses. HarmonyOS .har stays
unclassified by suffix because .har also names HTTP Archive JSON.

Adds the project_harmony_application_graph tool (CLI and MCP), synthetic
composition coverage, a pinned real-package verify lane, and docs.

* refactor(domain): share application graph projection scaffolding

The HarmonyOS projection mirrors the Android and Apple projections by
design, which pushed jscpd duplication over its 2.5 percent budget.
Extract the identical pieces (inventory input schema, projected
component schema and occurrence flattening, bridge candidate schema
factory, coverage assembly, comparator, canonical digest) into
domain/mobileApplicationGraphProjection.ts and route all three
projections plus the composition fixtures through it. Duplication drops
from 2.52 to 2.49 percent with no behavior change: projection ids,
classifications, and limitations are byte-identical.

* fix(harmony): address review, stable app-pack roots, and rotated fixture

- rebased onto main; the shared projection scaffolding now keeps main's
  nativeRuntimeConvention loop and the harmony runtime families adopt the
  same react-native/flutter/unity path conventions
- the .app App Pack suffix is now a root-input rule only (verified ZIP
  magic in classifyRootFormat and BinaryTargetResolver); nested .app ZIP
  members inside other packages keep the generic zip classification, with
  a regression test, so existing inventories do not change
- the signing limitation now states that an empty signing list does not
  mean unsigned because packaging-tool signatures live in the ZIP signing
  block, and the app-pack root rule is disclosed as suffix-based
- repinned the real-package fixture to the current VHome 2.6.14-beta asset
  after the upstream deleted v5.0.111-beta and replaced the v2.6.14-beta
  asset within hours; the pin records both observed digests

---------

Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
2026-10-11 20:09:21 +08:00
Thang Luuandmorluto ffaf2c12f1 feat(wasm): inspect local artifacts with WABT (#1533)
* feat(wasm): inspect local artifacts with WABT

* fix(wasm): preserve custom names and failed cleanup ownership

---------

Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
2026-10-11 19:49:00 +08:00
xeropresenceandmorluto d412def722 fix(setup): register a stable launcher when run through bunx (#1731)
Setup run through bunx or bun x registered the bin inside bun's temporary
package cache. Detect bun's package-runner launch from npm_command=exec
with a bun user agent and register the pinned bunx launcher, wrapped in
cmd.exe on Windows like the npx launcher. Doctor, update maintenance and
uninstall recognize it as REA-owned, and setup's printed commands name
the runner that launched it.

Read the runner variables case-insensitively on Windows, where the CLI
environment snapshot upper-cases variable names and setup run through
npx also fell back to the cache path.

Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
2026-10-11 19:17:15 +08:00
12c416005f feat(javascript): recover code-split bundles from multiple inputs (#1686)
* feat(javascript): recover code-split bundles from multiple inputs

recover_javascript_sources accepted a single path, and
validateModuleSet bound every module's provenance to that one snapshot.
A code-split app (runtime + chunks, or an Electron main/preload/renderer
set) had to be recovered one file per call, and modules recovered alone
could not resolve imports across chunks: cross-chunk require(id)
references stayed as numeric ids with property reads.

Add an optional additional_paths input. The listed files are
concatenated, in order after path, into the single engine snapshot, so
one Wakaru run sees every module and cross-chunk imports resolve.
validateModuleSet's single-snapshot binding is unchanged. Module
provenance is attributed back to the input file its first extraction
range starts in, with byte ranges rebased to that file's own offsets;
a module whose ranges cross an input boundary keeps the concatenated
snapshot identity and offsets, recorded as an explicit limitation.
Single-path behavior is byte-for-byte unchanged (one segment,
offset 0).

Fixes #1605

* fix(javascript): preserve source identity in multi-input recovery

---------

Co-authored-by: JingHao-Leon <w15909130000@gmail.com>
Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
2026-10-11 18:39:49 +08:00
morluto a4dd4e8e87 perf(cli): defer command-specific analysis implementations
Load application and Electron workflow implementations only when their commands execute. Keep command schemas and catalog registration eager, and extend the startup import boundary to cover the deferred services.
2026-10-11 17:23:41 +08:00
morluto a82d14e4db perf(cli): defer command-specific modules until dispatch 2026-10-11 13:20:15 +08:00
Kaoru0822andClaude Opus 5.5 0ecf3f2438 perf(mcp): keep Playwright and type-only imports off MCP startup (#1691)
* fix(build): emit no runtime imports for type-only bindings

Under verbatimModuleSyntax, an import whose specifiers all carry inline
`type` modifiers compiles to `import {} from "..."`, a side-effect import
that still resolves and evaluates the module. 78 compiled modules carried
one, including `import {} from "playwright-core"` in the browser scenario
session, which loaded Playwright's module graph at MCP startup.

Use top-level `import type` for these bindings and enable oxlint's
typescript/no-import-type-side-effects rule so the pattern cannot return.

Refs #1685

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

* perf(mcp): load Playwright when a scenario launches, not at startup

The browser scenario and Electron active providers are constructed before
the stdio server serves, and both bound Playwright's launchers at module
load. Resolve `chromium` and `_electron` from playwright-core when a
capture opens instead, as the web module resolver already does.

MCP startup now resolves 1,312 modules (4,902 resolutions) instead of
1,598 (6,076) before reading the first request, and no longer loads
playwright-core. Provider construction, the tool catalog, and capability
inventory are unchanged.

A boundary test spawns the stdio server, initializes, lists tools, and
asserts playwright-core and isomorphic-git were not resolved; the CLI
probe now exercises the real launch path to prove detection.

Closes #1685

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 21:04:05 -07:00
Ysopwnable 17f704050f feat(evidence): discover retained records without full payloads (#1682)
* feat(evidence): discover retained records without full payloads

* fix(evidence): guide oversized results to retained discovery

* style(tests): format retained discovery recovery assertion
2026-10-11 11:18:26 +08:00
Ysopwnable 4999e4be2c fix(javascript): isolate source analysis and retain bounded partial evidence (#1651)
* refactor(javascript): validate transferable file projections

* test(javascript): consume decoded module and static facts

* fix(javascript): isolate source analysis and retain bounded partial evidence

* test(javascript): verify cleanup retention and repeated source paths
2026-10-11 07:22:50 +08:00
morlutoandFazmin 8b4c96e6c6 fix(cli): preserve native option descriptions in help
Keep the optional address description visible to incur and describe the actual
bundle plist default and absolute-path support. Extend the existing command
help sweep instead of traversing the inventory a second time.

Refs: #1418
Co-authored-by: Fazmin <fazmin.nizam@gmail.com>
2026-10-11 06:41:46 +08:00
morluto 53e7fadbd0 fix(reference)!: retain source and metadata cleanup owners
Require a caller-owned artifact resource scope for source traversal and Git metadata reads. Preserve cancellation, filesystem reasons, partial entries and bytes, and cleanup observations through import and the CLI. Transfer exact failed file owners at regular-file admission and close boundaries, including multiple failures encountered by Git reference resolution.

Validation: 169 focused tests passed across 26 files; two Windows-only cases skipped. Build, typecheck, lint, formatting, knip, architecture guards, discovery and docs checks passed.

BREAKING CHANGE: Reference source readers and imports require an ArtifactResourceScope. VCS metadata reads return Result, and CLI import failures include observed details and partial evidence.
2026-10-11 06:10:10 +08:00
morluto be75ed5e4b fix(publication)!: retain cleanup owners across export workflows
Require an ArtifactResourceScope for web script exports and share its lifetime with CLI or MCP shutdown. Retain setup-failed output trees in firmware and Wakaru providers. Preserve completed publications when descriptor cleanup fails, returning the full result after a successful retry or as a partial observation while cleanup remains unresolved.
2026-10-11 05:17:10 +08:00
morluto ffe0574e17 fix(artifacts)!: retain cleanup owners through client shutdown
Keep failed reader, root descriptor, and output-tree cleanup with the caller. Drain admitted work before close, retry the same retained owners, and block new resource work while cleanup is incomplete. Preserve primary failures and complete inventory observations.

Thread ownership through JavaScript reconstruction, the CLI's one-shot scope, MCP server shutdown, verifier scripts, and test fixtures. Remove redundant ownership flags and the unused validated test wrapper.

Validate with 850 passing focused tests across 90 suites (two skipped), targeted classification and cleanup retries, static and unused-code checks, and real macOS CLI/MCP directory, ZIP, and DMG workflows. Native Windows and deep-analysis providers were not verified.

BREAKING CHANGE: Direct artifact inventory/extraction and JavaScript analysis APIs require an explicit caller-owned ArtifactResourceScope. CLI and MCP input contracts are unchanged.
2026-10-11 04:43:02 +08:00
morluto d1235fadc9 fix(providers): retain worker cleanup owners through shutdown
Validation: integrated changes passed formatting, typecheck, lint, resolved module-boundary verification and git diff --check. Tests and real-provider workflows were not run.
2026-10-11 00:03:21 +08:00
morluto a01148553e fix(setup): preserve recovery backups and retain installer cleanup
Validation: integrated changes passed formatting, typecheck, lint, resolved module-boundary verification and git diff --check. Tests and real-provider workflows were not run.
2026-10-11 00:03:21 +08:00
morluto cca7bf0022 fix(ci): repair option alias, pattern portability, and Italian doc links 2026-10-10 23:34:57 +08:00
96fd98cce0 feat(apktool): decode Android resource tables through a caller-supplied launcher (#1556)
* feat(apktool): decode Android resource tables through a caller-supplied launcher

Add an Apktool family with two operations over the caller's apktool
launcher (REA_APKTOOL_COMMAND, absolute, or apktool on PATH):

- inspect_apktool_client: resolved launcher, selection source, and
  version; decodes nothing.
- decode_android_resources: apktool d --no-src in a provider-owned
  workspace that is removed before the result returns. Projects the
  decoded AndroidManifest.xml (bounded at 512 KiB), apktool.yml version
  and SDK facts exactly as printed, string resources verbatim (default or
  one locale, bounded at 2000 entries, nested-markup entries counted as
  unparsed), available string locales, and the decoded file count with a
  hard cap. The target APK is digested with SHA-256 before decoding so
  Evidence binds the observation to the exact input.

Smali production is skipped by design: Java-source recovery belongs to
the JADX family. Workspace cleanup happens before results return; an
unremovable workspace is named in the limitations instead of abandoned.

Verified against apktool 2.7.0-dirty (Debian packaging) on Linux with
OpenJDK 25 against a signed aapt2-built probe APK with two resource
locales: launcher version, on-disk digest agreement, metadata projection,
manifest package agreement, and both string tables (default and de).
Parser goldens come from the same decode. READMEs carry the new
'Android resources' row in every supported language.

* fix(apktool): own snapshots and bound decoded resource reads

* docs(apktool): describe owned resources and bounded projection

---------

Co-authored-by: REA Contributor <contributor@rea.tools>
Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
2026-10-10 23:04:12 +08:00
749e58772a feat(jeb): add JEB engine provider over its MCP interface (#1536)
* feat(jeb): add JEB engine provider over its MCP interface

Add a bring-your-own JEB provider that serves project, unit, and
decompilation inspection from a caller-started JEB client speaking MCP
(streamable HTTP, selected with REA_JEB_MCP_URL). Expose four provider-neutral
operations through shared CLI/MCP workflows: inspect_jeb_client,
open_jeb_project, list_jeb_units, and decompile_jeb_item, each returning
Evidence with engine identity, endpoint, and preserved refusal reasons.

The adapter keeps JEB's envelope semantics: success fields are parsed
format-aware at the boundary, message-only refusals become unsupported-target
errors with the engine's own reason, transport failures become availability
failures with recovery guidance, and unit pagination derives coverage from the
engine's 100-item page cap. Explicit unknowns (implicitly selected unit,
omitted filters) are reported instead of guessed.

Verified against a real JEB 5.48.0 licensed build serving jeb-mcp-server 1.3.0
headless: client inspection, unit listing, and method decompilation were
exercised through the CLI, MCP boundary, and scripts/verify-jeb.mjs.
JEB 5.48.0 headless instances do not advertise open_project; the refusal is
preserved and documented.

* fix(jeb): verify against a real signed APK and fix CLI option surface

Verify the provider against a locally built, v1/v2/v3-signed probe APK
(binary manifest, classes.dex with a launcher activity) on JEB 5.48.0: the
full unit tree (apk, manifest, three certificate units, dex bytecode,
decompiler), wildcard-filtered and paginated unit listing with derived
coverage, parent-restricted listing, and launcher-activity method
decompilation through both CLI and MCP, including dexdec's inline
constant folding of the probe's obfuscated tag.

Move list-jeb-units filter/pagination and decompile-jeb-item unit selection
from positional arguments to options; the MCP schemas are unchanged.

* fix(jeb): preserve engine refusals through the real MCP boundary

Testing against the published Signal 8.30.3 universal APK exposed a boundary
bug the scripted provider tests missed: decodeJebToolResult raised a protocol
error for isError results before the provider could map JEB's
{success:false, message} envelope, so real engine refusals surfaced as
unreadable output instead of the engine's own reason. Decode refusal
envelopes like any structured result and let the provider preserve the
reason; cover the decoder directly, including contentless and unparseable
results.

Signal verification: full 109 MB R8/Kotlin/Compose APK with four signature
schemes and native arm64 ELF units parsed; MainActivity.onCreate and R8
synthetic lambdas decompiled through CLI and MCP; paginated, filtered, and
parent-restricted unit listing; refusal path confirmed on the live engine.

* docs(jeb): record Flutter Gallery verification on the real-engine lane

Verify the provider against the official Flutter Gallery 2.9.2 release APK
(112 MB): per-ABI libapp.so Dart AOT snapshot images analyzed as native code
with 75k methods on arm64, snapshot internals and wrapper methods decompiled
through both CLI and MCP with explicit unit selection, decoded manifest, and
filtered native-library unit discovery. Note that JEB 5.48.0 headless does
not expose the dedicated Dart snapshot processor or run_script; both remain
GUI-only engine surfaces.

* docs(jeb): translate the README JEB row for every supported language

The JEB row was inserted in English across all translated READMEs; each now
carries its own label, capability summary, requirements, and guide link
following that language's Android-row conventions.

* fix(jeb): enforce local endpoints and preserve cancellation

* fix(jeb): refuse redirects across the local MCP boundary

---------

Co-authored-by: REA Contributor <contributor@rea.tools>
Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
2026-10-10 23:03:27 +08:00
Thang Luuandmorluto 905e4866c4 feat(artifacts): inspect PE resource identities and payload ranges (#1482)
* feat(artifacts): inspect PE resource identities and payload ranges

* fix(artifacts): reject header payloads overlapping PE sections

---------

Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
2026-10-10 23:02:06 +08:00
曾亮andmorluto 4d8d76b253 fix(electron): support packaged app.asar pages and rewritten unpacked companions (#1400)
* fix(electron): resolve pages served from inside app.asar

Packaged Electron applications load their renderer pages from file URLs
inside app.asar. The host filesystem cannot stat those paths, so
list_electron_targets excluded every such page as unsupported_url and
inspect_electron_page could not select it.

Resolve these URLs the way Electron's file protocol does: the first .asar
path component that is a regular file is the archive, and the remainder
must name a regular file in its header. Directories, links, and missing
members stay rejected. Parsed headers are cached by archive identity.

* fix(artifacts): extract and explain rewritten ASAR unpacked companions

Packaging tools commonly sign or strip .asar.unpacked native binaries after
writing the archive header, so their declared hashes no longer match.
analyze_javascript_application already accepts integrity_policy, but
extract_artifact did not, and inspect_artifact and extract_artifact still
told callers to "get a fresh copy", which cannot help for a shipped app.

- Accept integrity_policy on extract_artifact (MCP and CLI). The default
  still fails closed; record-and-continue writes the observed bytes and
  returns the extracted files' integrity_contradictions records.
- Name the unpacked entry and the post-packaging cause in integrity
  failures, and point every operation that accepts integrity_policy at
  record-and-continue.
- Report an active unpacked entry whose companion file is absent as
  unavailable with its logical path instead of a format failure.
- Share one integrity_policy schema across the inventory, extraction, and
  JavaScript application inputs.

* fix(electron): bound ASAR headers before allocation

---------

Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
2026-10-10 23:01:54 +08:00
fef6f73064 feat(adb): complete ADB device support for Android reverse engineering (#1552)
* feat(adb): acquire installed APK sets from connected Android devices

Add a read-only ADB device-acquisition family over the caller's adb binary:
inspect_adb_client, list_adb_devices, inspect_adb_device, list_adb_packages,
and pull_adb_package, exposed through the CLI and MCP with shared admission,
Evidence provenance (binary, version, serial, transport), and fixed argv
vectors that never reach a shell.

pull_adb_package acquires the complete split set reported by pm path into a
package-named directory that must not exist, digesting every file with
SHA-256 and keeping per-file failure reasons and partial coverage. Device
kind is reported as an inference with its basis; getprop whitelisting keeps
build identity bounded. REA installs nothing and never manages devices or
emulators; the first device query may start the caller's local adb server,
recorded when observed.

Verified against adb 34.0.5 on Linux with an Android 14 (API 34) x86_64
emulator: full 224-package inventory, a real two-APK split set pulled with
byte-exact digests, and a 73.9 MB system-package pull. npm run verify:adb
records the lane; parser goldens come from the same device. READMEs carry
the new row in every supported language.

* feat(adb): complete the adb surface with observation, transfer, and lifecycle tools

Extend the ADB family from five to twenty-four operations, all through
fixed adb argument vectors with no shell exposure:

Observation: read_adb_logcat (bounded dump, count/buffer/pid), inspect_adb_package
(dumpsys package projection), list_adb_processes (ps -A), list_adb_directory
(ls -la with kinds and symlink targets), list_adb_features (hex GL versions),
list_adb_services (AIDL slash-suffixed names), inspect_adb_display (wm size and
density), inspect_adb_window (focus declarations), read_adb_setting (device-side
nulls reported as such), capture_adb_screen (exec-out screencap with PNG
dimensions), collect_adb_bugreport (digested device archive).

Transfer and search: pull_adb_file and push_adb_file (device-side sha256sum
verification, explicit overwrite authority), resolve_adb_packages (substring
package search with exact-match flag — the find step of an easy get).

Lifecycle for dynamic analysis, each declaring mutatesTarget:
install_adb_package and uninstall_adb_package preserving the device's
Success/Failure verdict, start_adb_app (resolve-activity then am start -W),
start_adb_activity (typed extras as --es/--ez/--ei/--el/--ef), and stop_adb_app
(am force-stop).

Verified end-to-end against adb 34.0.5 on Linux with an Android 14 (API 34)
x86_64 emulator: 287 services, 92 features, split-set pulls with byte-exact
digests, verified push/pull roundtrip, sized screen capture, and the full
install → resolve → start → observe-in-ps → force-stop → uninstall lifecycle.
Fixed a v-mode regex incompatibility in the settings key pattern and added
argument descriptions required by the CLI catalog audit.

* fix(adb): quote remote shell operands and protect captured output

* test(adb): cover bugreport destinations containing spaces

---------

Co-authored-by: REA Contributor <contributor@rea.tools>
Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
2026-10-10 23:01:24 +08:00
jhuang-twandN0zoM1z0 a9ee2360fd feat(native): inspect oversized retained function dossiers via bounded views
Add caller-selected native dossier facets with preserved Evidence identity, provenance, unknowns and transport recovery.

Refs #1247 and #1065.

Co-authored-by: jhuang-tw <77732008+jhuang-tw@users.noreply.github.com>
Co-authored-by: N0zoM1z0 <161784452+N0zoM1z0@users.noreply.github.com>
2026-10-10 12:18:50 +08:00
Kaoru0822andClaude Opus 5.5 ca3131b36c perf(cli): write compact JSON when output is not a terminal (#1413)
`--json` / `--format json` always indented its streamed result. Agents and
scripts read REA through pipes and redirects, where indentation carries no
information: on real application results it added 16-45% model tokens
(o200k proxy) and 25-73% bytes. The skill's CLI fallback uses `--json`.

Indent only when stdout is a TTY, as `gh --json` does; piped or redirected
JSON is compact. The JSON value, `jsonl`, `--filter-output`,
`--full-output` and the token-window paths are unchanged. `jq .` restores
indentation for files.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 20:29:48 -07:00
Kaoru0822andClaude Opus 5.5 6875d4a64c fix(cli): accept JSON files for web capture and screenshot comparisons (#1397)
compare-web-captures and compare-web-screenshots parsed their arguments as
inline JSON only, unlike every other JSON-input command. Screenshot
artifacts and scenario captures embed base64 PNG bytes, so a typical
viewport screenshot exceeds the command-line length limit (128 KiB per
argument on Linux, 1 MiB total on macOS) and could not be compared from
the CLI at all, while MCP accepts it. A file path was reported as
malformed JSON, and screenshot schema failures returned no issues.

Each argument now accepts inline JSON or a JSON file path through
parseCliJsonInput; file failures keep its path diagnostics, malformed
inline JSON keeps the field issue, and screenshot validation reports
projected schema issues. The tests share one CLI JSON process fixture.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 19:29:42 -07:00
Kaoru0822andClaude Opus 5.5 498cec042a fix(cli): stop advertising multi-letter single-dash option aliases (#1395)
Incur's `alias` map registers one-letter short flags and already accepts
kebab-case spellings of camelCase options. Twenty options registered their
kebab-case long name as an "alias", so help and completions advertised
flags such as `-case-sensitive` and `-relative-path` that the parser reads
as stacked short flags and rejects with "Unknown flag: -c".

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 19:29:20 -07:00