Bring in #927's merge of main (#1037 at skill version 30):
- README_ja/ar/ko/zh: keep the merged tables and count
inspect_dyld_shared_cache in application workflows (13 -> 14).
- Skill: #927 now uses version 31, so this branch moves to 32.
- Regenerate the product catalog, conformance manifest, skill digest and
package metadata (138 tools).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
main now carries #1037 (skill version 30, reworded native binary row):
- README_ja/ar/ko/zh: take main's tables and count
trace_dylib_resolution in the artifact graph row (5 -> 6).
- Skill: move to version 31.
- Regenerate the product catalog, conformance manifest, skill digest and
package metadata (137 tools).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Bring in #927's merge of main and resolve conflicts:
- README.md: main's simplified English README has no tool-family table.
- README_ja/ar/ko/zh: keep main's reworded tables and count
inspect_dyld_shared_cache in application workflows (13 -> 14).
- Skill: #927 now uses version 29, so this branch moves to 30.
- Regenerate the product catalog, conformance manifest, skill digest and
package metadata (136 tools). The MCP tool catalog is now built rather
than committed (#997), so it is removed here.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Resolve conflicts against main:
- README.md: take main's simplified English README, which no longer has
the tool-family table.
- README_ja.md: take main's reworded table and count
trace_dylib_resolution in the artifact graph row (5 -> 6).
- Skill: the references gain the trace_dylib_resolution paragraph, so
the version moves to 29 (main already uses 28).
- Regenerate the product catalog, conformance manifest, skill digest and
package metadata (135 tools). The MCP tool catalog is now built rather
than committed (#997), so it is removed here.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* docs: simplify the English README
Preserve the opening and add the official skills.sh badge. Move setup diagnostics and CLI/Evidence details into guides, add three website showcases, and check setup-client facts in the installation guide.
Refs #1017
* docs: add README workflow and FAQ
Restore the original Disclaimer verbatim, invite community showcases, reuse the website investigation figure, and answer six common questions.
* docs: clarify README updates and collapse FAQ
* docs: welcome contributions in the README
* docs: highlight website guidance before quick start
* docs: keep README capability links aligned with main
* fix(docs): preserve README backlinks and release checks
* fix(browser): preserve authorized redirect hops
* fix(browser): compare redirect semantics without event times
* fix(browser): classify missing redirect predecessors
* fix(browser): distinguish malformed redirect URLs
* fix(browser): preserve evidence on malformed redirect envelopes
* fix(browser): freeze evidence after malformed redirect
* docs: regenerate catalogs after main integration
* fix(browser): account for skipped redirect body shapes
* fix(browser): mark skipped redirect response shapes unavailable
When a malformed redirect keeps a JSON predecessor, record that its response body shape was not captured.
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Carry #952's Apple ownership into the cache work: the cache reader and
fixture move to src/artifacts/apple/, the cache facts, platforms and
resolution schema to src/domain/apple/, the cache service to
src/application/apple/, and the lane to scripts/verify/apple/.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Follow #952's Apple ownership: the Mach-O load-command reader, dylib
resolution adapter and fixture move to src/artifacts/apple/, the resolver,
dyld path semantics and findings to src/domain/apple/, and the dylib lane
helper to scripts/verify/apple/.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Carry conditional-load propagation, parsed-image digest binding, and
segment-wise root resolution into the shared-cache trace. Also:
- Make cache compatibility directional: an arm64e cache serves arm64
processes and an x86_64h cache serves x86_64 ones, not the reverse.
- Require the complete 24-byte LC_BUILD_VERSION with its declared tool
records, and the 16-byte LC_VERSION_MIN_* command, before recording a
platform.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Edges below a conditional fallback now carry loader_conditional, reuse of
a conditional image by install name is conditional, and their findings say
they apply only if that image loads.
- Hash each traced image only if it is still the file whose headers were
parsed (device, inode, size and change times), before and after hashing.
- Resolve explicit roots segment by segment, so a root below a symlinked
directory that points outside the analyzed root is rejected.
- Require a complete 16-byte LC_CODE_SIGNATURE command.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Use a supplied cache for a process only when it serves the process's CPU
family and one of its LC_BUILD_VERSION or LC_VERSION_MIN platforms matches
the cache's platform or alternate platform; slices now report platforms.
A limitation names each root the cache was not used for, and why.
- Treat an image listed in the cache but mapped in a missing or
UUID-mismatched subcache as undetermined, list it in
coverage.unverified_shared_cache_images, and mark coverage partial.
- Keep a cache hit conditional when an earlier candidate is undeterminable.
- Open a development cache's named subcaches beside its base name.
- Describe absolute paths as not evaluated only when no cache is supplied.
- Preflight dyld_info in verify:dyld-shared-cache.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Address review findings in trace_dylib_resolution:
- Resolve LC_LAZY_LOAD_DYLIB dependencies without traversing them, since
dyld loads them on first use. An unresolved one becomes
`lazy-load-unresolved`, not a launch failure.
- Accept FAT tables up to 128 records, as target opening does. A table
that names no Mach-O CPU type, such as a Java class file, is not
Mach-O.
- Require 8-byte load-command alignment in 64-bit images. 1,508 real
slices still match otool.
- Report EACCES/EPERM while probing, reading, or hashing as an
`unavailable` failure naming the code and path, rather than generic
io.
Findings and limitations move to dylibResolutionFindings.ts to keep the
resolver under the module size limit.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
macOS 11 and later ship system libraries only inside the dyld shared
cache. trace_dylib_resolution therefore left every /usr/lib and /System
load undetermined, and REA had no way to see what a cache contains.
inspect_dyld_shared_cache (CLI inspect-dyld-shared-cache) reads a cache
file set selected by path, without an open target. Its pure TypeScript
reader parses modern and legacy dyld_cache_header layouts and reports:
- UUID, architecture, platform, OS version, Mac Catalyst alternate,
cache type, shared region, max slide;
- every VM mapping;
- each subcache by file suffix, checked by UUID. A missing or
mismatched subcache makes coverage partial;
- the complete image list.
For each requested install path it reads that image's load commands
through the cache mappings with the existing Mach-O reader.
trace_dylib_resolution accepts an optional shared_cache. Absolute
candidates found in a cache that serves the process's CPU family resolve
with the new outcome and status `shared-cache`. That status also takes
precedence over later in-bundle fallbacks such as a back-deployed
libswiftCore. The result names the cache UUID and OS version it used.
verify:dyld-shared-cache checks every image in the host cache (3,649 on
macOS 26.6), with dependencies and their re-export, weak, upward and
delay-init attributes, against `dyld_info -all_dyld_cache
-linked_dylibs`. It also checks CLI/MCP parity, and that each
shared-cache edge in the fixture trace is a library dyld actually loads.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Address review findings in trace_dylib_resolution:
- Choose child slices by dyld's graded architectures, so an x86_64h
process loads a generic x86_64 slice instead of reporting
architecture-missing.
- Read FAT containers with the byte-swapped FAT_CIGAM and FAT_CIGAM_64
magics, which target opening already accepts.
- Report string-bearing load commands too short to hold their string
offset as malformed instead of failing with a RangeError.
- Keep recognized but unsupported images as an `unsupported` candidate
outcome. It is undeterminable like an outside-root path, not
malformed.
- List Mach-O files that do not parse during root enumeration as
unparsed images, so coverage is partial rather than silently complete.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Add trace_dylib_resolution (CLI trace-dylib-resolution) to the artifact
family. For the active Mach-O, or every executable in the active .app
(the main app, XPC services, extensions, login items, helpers), it
reports which file each dylib load reaches and how.
A pure TypeScript reader decodes FAT and Mach-O load commands:
LC_LOAD/WEAK/REEXPORT/LAZY/UPWARD_DYLIB, including the newer
dylib_use_command encoding with weak, re-export, upward and delayed-init
flags, plus LC_ID_DYLIB, LC_RPATH, LC_DYLD_ENVIRONMENT and code-signature
presence. Malformed tables are reported with the failing command instead
of being guessed.
Resolution follows dyld:
- @executable_path comes from each process root;
- @loader_path comes from the loading image, or from the owner of the
LC_RPATH entry being expanded;
- @rpath searches the loader's rpaths first, then up the load chain;
- dependencies load dependents-first in load-command order, once per
process, and a matching install name reuses an already loaded image;
- symlinks are followed inside the analyzed root, and escapes stop.
Every candidate path is reported with its outcome. Each edge resolves to
resolved, conditional (an outside-root candidate such as /usr/lib/swift
precedes), unresolved, or undetermined. Absolute and shared-cache system
paths are never checked against the host. Derived findings cover
unresolved required or weak loads, absent earlier @rpath candidates (with
library validation left unknown), and LC_DYLD_ENVIRONMENT.
verify:macos-bundle now also:
- checks every traced image against otool -l;
- asserts each resolution status on a clang-built fixture that adds a
missing Overrides rpath, an absolute rpath, and a delay-init library;
- compares the predicted load order of two process roots with what dyld
loads under DYLD_PRINT_LIBRARIES.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The `plist` XML decoder throws on the legal dictionary key `__proto__`
(its CVE-2022-22912 guard). An app whose XML Info.plist held such an
entry could not be opened at all ("app has no readable
CFBundleExecutable"), and entitlements, XML keyed archives, and
Interface Builder plists failed the same way. On the plutil JSON route,
validation silently dropped the key from `inspect_plist` results.
Decode XML plists through a shared reader that substitutes such keys
before the decoder runs, then omits and counts those entries.
`inspect_plist` and `inspect_keyed_archive` report the omission as a
limitation instead of failing or dropping it silently.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
otool and dyld_info print the operand path before a slice's records,
and the Mach-O parsers read that header as output. A file name holding
`Load command` blocks or `(from lib)` lines therefore added a forged
LC_MAIN entrypoint, corrupted the Mach header fields, and injected
imports and exports into `inspect_macho`.
Strip the exact echoed operand header (`<path>:`, `<path> (architecture
<arch>):`, `<path> [<arch>]:`) before parsing. Output without that
header, such as replayed captures, is parsed unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A regular plist that the host refuses to open made both plutil
conversions fail, which was reported as an undecodable property list.
Open the file before running plutil and report EACCES/EPERM as a
target access failure naming the path.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`inspect_plist` turned a missing selected plist, a directory, or a file
that is not a property list into a generic execution failure that
advised retrying and running `rea doctor`. A bare Mach-O without
Contents/Info.plist failed the same way.
Check the resolved path before running plutil and keep plutil's decode
diagnostic. A caller-selected path now fails as invalid input naming
the path and the reason; a missing default Info.plist is unavailable for
the target. The CLI no longer sends Contents/Info.plist as an explicit
selection, so its default matches the MCP default.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`swift-demangle` parsed a symbol beginning with `-` as an option, so
`-help` replaced the results with usage text and the call failed as
unreadable output. A symbol containing a line feed split into extra
output records, and the CRLF-tolerant parser stripped a carriage return
that belonged to the final symbol.
Pass the symbols after `--`, split records on the LF the demangler
emits, and reject multi-line symbols in the shared CLI/MCP input schema.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* feat(application): wire Android and Apple inventory graph tools
Expose project_android_application_graph and project_apple_application_graph
through CLI and MCP so authenticated inventory Evidence can be projected
without a provider launch.
* fix(application): use producer root occurrence IDs in graph examples
Catalog examples constructed root occurrence IDs from artifact_id +
logical_path, but inventory validation authenticates "." with
{ root: root_artifact_id }. Align the examples and regenerate catalogs
after rebasing onto main (application family count 11).
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
codesign echoes the executable path and signing identifier verbatim,
and an ad hoc identifier derives from the file name. A file name with
line breaks added forged Authority lines, a signed file named after
codesign's unsigned message was reported unsigned, and path text could
supply entitlements. Parse display fields after the exact echoed path
and identifier, classify unsigned output by exit status, and read
requirements and entitlements from stdout.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
plutil's JSON spells an integral <real> such as 9007199254740992 like an
<integer>, so the JSON path labeled it an exact integer. When the JSON
holds an unsafe integral number, read element types from plutil's XML
conversion; numbers whose origin stays ambiguous are reported as decoded
with an explicit limitation.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* feat(javascript): recover readable modules with Wakaru
Integrate pinned upstream source behind a typed optional recovery port,
preserve source identity and producer provenance, and publish verified
artifacts for existing JavaScript analysis through CLI and MCP.
Add focused real-tool CI with genuine bundler fixtures and bounded
resource, cancellation, cleanup, schema and packaged-artifact checks.
Assisted-by: Yukari (gensokyo-skills:yukari-boundary-analysis)
Assisted-by: Kogasa (gensokyo-skills:kogasa-surprise-testing)
* fix(javascript): align recovery catalog and browser verification
Share canonical Wakaru provider identity, describe CLI mode options, and
format the new workflow test. Disconnect the real page transport after
its observation readiness progress instead of a fixed delay.
Assisted-by: Yukari (gensokyo-skills:yukari-boundary-analysis)
Assisted-by: Kogasa (gensokyo-skills:kogasa-surprise-testing)
* refactor(javascript): consume the investigation evidence writer
Verify that the SDK recovery handler records complete Evidence through the newly shared investigation owner.
Assisted-by: Yukari (gensokyo-skills:yukari-boundary-analysis)
* chore(test): account for isolated recovery fixture compilers
* fix(javascript): validate recovery paths before acquiring the engine
Return field-specific invalid_format diagnostics for relative paths and verify compiled CLI/MCP parity even when the optional engine is unavailable.
Assisted-by: Yukari (gensokyo-skills:yukari-boundary-analysis)
Assisted-by: Kogasa (gensokyo-skills:kogasa-surprise-testing)
The XML fallback inferred an integer from `Number.isInteger`, so an
integral `<real>` beyond 2^53 was misreported as an unknown integer.
Read the `<integer>` and `<real>` literals from plutil's XML text instead:
an unsafe integral number that matches one `<integer>` literal and no
`<real>` gets its exact decimal; a number that could be either stays as
decoded with a limitation.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`inspect_plist` parsed plutil JSON with `JSON.parse`, silently rounding
integers outside ±(2^53 - 1): `18446744073709551615` became
`18446744073709552000` with no limitation. Keep the exact decimal text
from the JSON source as `{ "$plist_type": "integer", "decimal": "..." }`
and add a limitation. On the XML fallback path, the decoder has already
rounded such values, so they become `decimal: null` instead of a wrong
number.
Also restore the `` escape in the BOM regex, which an earlier
rewrite had turned into a raw invisible character.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`inspect_plist` converted every plist with `plutil -convert json`, which
rejects plists containing `<data>`, `<date>`, or non-finite `<real>`
values. Such valid plists (including Stocks.app's Info.plist) failed with
a cause-free `execution_failure`.
When the JSON conversion exits nonzero, decode `plutil -convert xml1`
instead. Data and dates use the `$plist_type` objects the keyed-archive
reader already emits; non-finite reals become an explicit unknown because
the XML decoder reports NaN and infinity alike. Provenance records both
conversions and limitations explain the representation. Plists that JSON
can express keep the unchanged single-conversion path.
The projection moves to `src/domain/plistValue.ts` and is shared with the
keyed-archive reader, which keeps rejecting non-finite reals.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>