Commit Graph
4834 Commits
Author SHA1 Message Date
Kaoru0822andClaude Opus 5.5 a0ec3e2016 fix(artifacts): follow dyld slice grading and report unparsed images
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>
2026-10-07 11:07:31 +00:00
Jay HemnaniandCursor Agent 37d2ebac4c fix(artifacts): accept the bundle subject when extracting an app bundle (#891)
* fix(artifacts): accept the bundle subject when extracting an app bundle

For a .app target the session target is the bundle's executable, while the
artifact provider reports the bundle itself as the subject. The subject
check exempted inventory_artifact and inspect_artifact but not
extract_artifact, so extracting any .app failed with execution_failure after
the output tree had already been written, and the output path was never
reported.

* refactor(binary): rename artifact bundle subject helper

isArtifactInventorySubject also covers extract_artifact for .app
bundles, so name it for the shared bundle-subject exemption.

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
2026-10-07 19:04:55 +08:00
Kaoru0822 63800ff5a2 Merge remote-tracking branch 'origin/main' into feat/dylib-resolution
# Conflicts:
#	docs/product-catalog.json
#	docs/verification/managed-conformance-manifest.json
#	skills/reverse-engineer-anything/SKILL.md
#	src/generatedMcpToolCatalog.ts
2026-10-07 11:04:20 +00:00
Jay HemnaniandCursor Agent 45fcd28b40 fix(javascript): resolve bare source-map and worker URLs next to the script (#890)
* fix(javascript): resolve bare source-map and worker URLs next to the script

A sourceMappingURL like `main.js.map` (the default of webpack, esbuild,
rollup, Vite and rolldown) and `new Worker("worker.js")` were resolved as
module specifiers, so the bare name was looked up as an npm package and the
map or worker script was never linked. Resolve them as URLs relative to the
declaring script.

* fix(javascript): tighten url-reference resolution edge cases

Use looksExternal for non-module contexts so protocol-relative URLs
cannot be misread as root-absolute paths, cover url-reference unit
cases, and assert bare service-worker script resolution.

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
2026-10-07 19:04:15 +08:00
Kaoru0822andClaude Opus 5.5 9226ade511 fix(apple): pair bridge hypotheses within one application root
A ZIP or DMG holding two applications produced bridge candidates from
scripts in one app to native code in the other. Candidates now pair only
components owned by the same application root; components outside every
root pair only with each other.

A versioned framework with several real version directories now keeps
its Info.plist unknown even when only one version has a plist, because
Versions/Current, which is not inventoried, decides which applies.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 11:02:47 +00:00
Kaoru0822 aa8082ea6c Merge pull request #913 from morluto/fix/uikit-runtime-connections
fix(artifacts): project UIKit runtime outlet and event connections
2026-10-07 04:00:25 -07:00
Kaoru0822 b3f013fa18 Merge pull request #899 from morluto/fix/interface-builder-plist-data
fix(artifacts): decode flat keyed-archive NIBs with data and shared references
2026-10-07 03:59:54 -07:00
Kaoru0822 2ed89e6529 Merge pull request #910 from morluto/feat/ios-app-bundles
feat(native): open iOS-style and iOS-on-Mac wrapper app bundles
2026-10-07 03:59:41 -07:00
morluto 71e5cb1640 chore: merge main and regenerate combined catalog metadata 2026-10-07 18:44:35 +08:00
morluto fd552a8c4b chore: merge main and regenerate combined catalog metadata 2026-10-07 18:44:34 +08:00
morluto be121d87eb chore: merge main and preserve keyed archive regressions 2026-10-07 18:44:01 +08:00
morluto b9292516f4 fix(process): retain provider output until streams close (#928) 2026-10-07 18:39:10 +08:00
morluto f826aa893f fix(browser): preserve evidence through deep AST analysis (#924) 2026-10-07 18:36:18 +08:00
Kaoru0822andClaude Opus 5.5 11b7f918c2 feat(artifacts): trace Mach-O dylib resolution in bundles
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>
2026-10-07 10:31:17 +00:00
Kaoru0822andClaude Opus 5.5 55249704c5 fix(apple): attribute only application-root components in macOS inventories
Directory, ZIP, and DMG inventories can hold installers, disk-image
extras, and AppleDouble sidecars beside the app. Those components were
classified as the application's frameworks, libraries, JavaScript, and
metadata, and fed runtime families and bridge candidates. For these
formats, components outside every application root are now left out,
with a limitation that counts them. IPA projection is unchanged.

A selected directory whose name ends in .app is now its own root by
identity, so an empty or partial inventory still reports it. iOS is
claimed only for shallow roots that have an Info.plist, so an empty root
reports no platform.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 10:30:47 +00:00
Kaoru0822 b956bd589f Merge branch 'fix/dmg-apfs-detach' into feat/macos-bundle-anatomy 2026-10-07 10:28:20 +00:00
Kaoru0822andClaude Opus 5.5 62634e4c01 fix(artifacts): keep the post-snapshot detach check out of provenance
The inventory snapshot captures reader provenance before close() runs,
so a `hdiutil info -plist` entry recorded during cleanup never reached
CLI or MCP results. Detach entries already share that timing. Record
neither instead of implying the query is observable.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 10:28:03 +00:00
Kaoru0822 28fd49f0f6 Merge pull request #889 from morluto/fix/managed-comparison-undecoded-signatures
fix(dotnet): compare members with undecoded signatures by exact identity
2026-10-07 03:22:54 -07:00
Kaoru0822 4f5110306d Merge pull request #895 from morluto/fix/javascript-indexeddb-open-version
fix(javascript): keep storage open versions out of XHR endpoints
2026-10-07 03:22:12 -07:00
morluto 9a15525298 perf(cli): defer unused catalog work during command startup (#920)
perf(cli): defer catalog digests and use canonical cache scope
2026-10-07 18:16:10 +08:00
Kaoru0822andClaude Opus 5.5 27c272bd9a fix(artifacts): read AppKit connectors from flat keyed-archive NIBs (#900)
* fix(artifacts): read AppKit connectors from flat keyed-archive NIBs

Flat AppKit NIBs archive NSNibOutletConnector and NSNibControlConnector
endpoints and the outlet or selector name under NSSource, NSDestination,
and NSLabel. The keyed-archive parser read only source, destination,
and label, so it skipped every such connector: XLD.app's 64 decoded NIBs
had no outlet or target-action edges. The NS-prefixed keys now follow the
same source and destination convention as compiled NIBArchive documents.

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

* fix(artifacts): read AppKit control connectors from the control to its target

NSNibControlConnector archives NSSource as the sending control and
NSDestination as the action target. The previous commit inverted them
like the unprefixed fields, so every flat AppKit action ran from the
target to the control. The action trace selects a control and follows
control -> action, and the graph keys the selector by its target, so
neither could resolve these actions. The NS-prefixed keys are now read
as source and destination for outlets and actions alike.

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

* fix(artifacts): key AppKit connector endpoints by their node identity

An NSSource or NSDestination object with an identifier field was
referenced by that identifier, but its node is keyed by its authored
object ID or archive UID. The connector then pointed at a synthetic
unknown node. NS-prefixed endpoints now use the referenced object's
node identity.

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 18:08:02 +08:00
Kaoru0822andClaude Opus 5.5 dd3e7aef0d feat(apple): project macOS bundle anatomy in application graphs
project_apple_application_graph accepted only IPA inventories. It now
also projects macOS .app directories and ZIP or DMG inventories that
contain applications. It reports application roots, platforms, and
every nested bundle with its path-convention role, layout, parent,
Info.plist path, executable candidates, and signing paths:
- roles: app extensions, XPC services (including inside frameworks),
  frameworks, login items, system and driver extensions, plug-ins,
  resource bundles, and helper or nested applications;
- privileged helpers in Contents/Library/LaunchServices and launchd
  plists in Contents/Library/LaunchAgents or LaunchDaemons;
- direct files of Contents/Helpers;
- symlinks by path. Their targets are not inventoried, so versioned
  frameworks are described through their real Versions/<version>/
  directories.

AppleDouble sidecars (._* and __MACOSX/) are excluded from roles. A DMG
whose contents could not be inventoried is reported as partial. Other
inventory formats remain input errors. The projection still reads no
plist or CMS semantics; it points callers at inspect_plist.

The result schema is additive. projection_id now covers the new fields,
so IPA projection IDs differ from earlier versions.

verify:macos-bundle compiles a source-owned app with clang (CLT only).
It packs it as a directory, a ditto ZIP, and an APFS DMG, and checks
identical anatomy through the CLI with stdio MCP parity. It runs in the
macOS CI job.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 10:06:48 +00:00
Kaoru0822andClaude Opus 5.5 b72c079a9a fix(artifacts): accept APFS image disks ejected with their container
An APFS disk image attaches as an image disk plus a synthesized APFS
container, and hdiutil reports both as whole disks. Detaching the
container also ejects the image disk, so the reverse-order detach then
failed with "No such file or directory" and every APFS DMG inventory
ended in "DMG detach or mount-root cleanup failed". APFS is the default
format of `hdiutil create` on current macOS.

When a detach fails, ask `hdiutil info -plist` whether the device is
still attached. A device that is gone counts as detached; one that is
still listed, or whose state cannot be read, remains a cleanup failure.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 10:06:37 +00:00
morluto 1d769cd261 chore: merge main and preserve UIKit and AppKit connections 2026-10-07 18:02:05 +08:00
morluto 071cfd1bb6 chore: merge main and preserve plist and AppKit regressions 2026-10-07 18:02:05 +08:00
ysopwnable f0a68dce60 refactor(artifacts): isolate JavaScript file acquisition (#916) 2026-10-07 17:57:33 +08:00
Kaoru0822 2db668f6ca fix(cli): emit empty structured filter projections (#914) 2026-10-07 17:51:10 +08:00
morluto 7a9f587c3a perf(dotnet): index declaring-type ranges once per metadata table (#918)
perf(dotnet): index ordered declaring-type ranges once per table
2026-10-07 17:48:39 +08:00
Kaoru0822andClaude Opus 5.5 900d7c8606 fix(artifacts): project compiled AppKit actions from the control to its target (#905)
* fix(artifacts): project compiled AppKit actions from the control to its target

NSNibControlConnector archives the sending control as NSSource and the
action target as NSDestination; a nil target is the first responder. The
NIBArchive projection swapped them for control connectors, so every
compiled AppKit action ran from its target to the control. The action
trace, which follows control -> action, could not find them, and the
selector node was keyed by the control instead of the target class. When
the target was nil, the swapped source was null and the action was
dropped: Chess lost 29 menu actions, KeepingYouAwake 7.

Connectors now keep NSSource -> NSDestination. The NIBArchive test
encoder moves to a fixture module so a bundle test can build compiled
NIBs.

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

* test(artifacts): report observed action routes when a compiled route is missing

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

* test(artifacts): report compiled connector records when a storyboard route is missing

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

* test(artifacts): write the storyboard fixture's action in Cocoa syntax

MacFixture.storyboard declared its button action with the iOS attribute,
<action selector="buildTapped:" destination="vc1">. Cocoa documents
name an action's receiver with target=. ibtool compiled the iOS spelling
into an NSNibControlConnector whose NSSource is the view controller
placeholder and whose NSDestination is the button. That is the reverse
of what Xcode-authored AppKit NIBs contain (Music, Chess,
KeepingYouAwake, and Transmission all archive NSSource as the control),
and it is what the old inversion had matched. With target= the compiled
fixture archives the button as NSSource. The temporary connector dump is
removed; the observed routes remain in the assertion message.

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 17:40:18 +08:00
morluto 62b37111e7 fix(javascript): handle deep AST traversal and addition without stack overflow (#915)
* fix(javascript): avoid recursion and eager ancestry copies in deep ASTs

* fix(javascript): traverse static analysis and bundler ASTs iteratively
2026-10-07 17:40:05 +08:00
morluto 5574287101 chore: merge main and resolve PR #889 conflicts 2026-10-07 17:28:56 +08:00
morluto 5b5b76a583 chore: merge main and resolve PR #895 conflicts 2026-10-07 17:28:56 +08:00
morluto 4d2faef37b chore: merge main and resolve PR #910 conflicts 2026-10-07 17:28:55 +08:00
morluto 96a9f32dc1 chore: merge main and resolve PR #899 conflicts 2026-10-07 17:28:55 +08:00
ysopwnable f6a58f1062 refactor(javascript): group domain semantics and contracts (#907) 2026-10-07 17:16:58 +08:00
Kaoru0822 d5f28fb29c Merge pull request #887 from morluto/fix/managed-native-boundaries-non-managed
fix(dotnet): inspect native boundaries of non-managed and malformed PEs
2026-10-07 02:12:48 -07:00
Kaoru0822 15ab5dbcaf Merge pull request #894 from morluto/fix/plist-prototype-key-reporting
fix(plist): report omitted __proto__ entries in signatures and Interface Builder
2026-10-07 02:12:34 -07:00
Kaoru0822andClaude Opus 5.5 8b243877c2 fix(artifacts): project UIKit runtime outlet and event connections
Compiled UIKit NIBs and storyboards archive outlets and control actions
as UIRuntimeOutletConnection and UIRuntimeEventConnection with
UISource, UIDestination, and UILabel. The NIBArchive projection
recognized only AppKit *Connector classes with NS-prefixed keys, so an
iOS app produced no outlet or action edges: Stash's 64 decoded documents
yielded none. These connections are now projected with the same
source -> destination roles, an event connection carries its
UIEventMask as ui_event_mask, UIClassSwapper reports its UIClassName,
UIProxyObject is a placeholder, and connection records are no longer
emitted as unknown objects.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 09:10:53 +00:00
Kaoru0822andClaude Opus 5.5 418a5562f6 fix(native): keep the resolved bundle plist and permission failures
- Carry the Info.plist that declared the program file on the target as
  bundleInfoPlist, so inspect_plist defaults to it even when the program
  file is a symlink into another bundle directory.
- Accept a readable Info.plist symlink, as reading the plist directly did.
- Treat only a missing path as an absent layout or wrapper; a permission
  denial now reaches the resolver's permission-denied classification.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 09:10:29 +00:00
Kaoru0822andClaude Opus 5.5 7714e763d9 fix(dotnet): name the shared key in exact-signature ambiguities
An ambiguous exact-signature group was described as sharing a
non-name identity key, but that key includes the declared type and name,
so names cannot separate it. Ambiguity limitations now name the key the
group actually shares.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 09:08:32 +00:00
morluto df7151ba30 perf(providers): assemble fragmented responses once per line (#911) 2026-10-07 17:07:00 +08:00
morluto e52fe9719f perf(call-path): prune dead ends and enumerate without recursion (#909) 2026-10-07 17:03:44 +08:00
Kaoru0822andClaude Opus 5.5 aeebba391e feat(native): open iOS-style and iOS-on-Mac wrapper app bundles
Every native command rejected an iOS app installed on an Apple silicon
Mac, such as /Applications/Stash.app, with "app has no readable
CFBundleExecutable": the resolver understood only the macOS layout,
Contents/Info.plist with Contents/MacOS/<executable>. iOS-style bundles,
including those extracted from an IPA, keep Info.plist and the program
file at the bundle root, and an iOS-on-Mac wrapper holds that bundle in
Wrapper/<Name>.app.

Bundle resolution moves to AppBundleExecutable and accepts the macOS
layout, then the flat layout, then a wrapper's single real Wrapper/*.app
directory. The WrappedBundle symlink is never followed, and the program
file must stay inside its bundle. inspect_plist defaults to the Info.plist
beside the program file when the bundle has no Contents/Info.plist.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 08:59:28 +00:00
morluto eab34a9d8c fix(android)!: preserve JVM settings and reuse metadata sessions (#908)
* perf(graph): avoid repeated traversal edge scans and copies

* fix(android)!: preserve JVM settings and reuse metadata sessions

Read class metadata without generating application source, retain immutable serialized APK sessions, and join owned cleanup on cancellation and shutdown.

BREAKING CHANGE: Android analysis now requires a full JDK 17 or newer with its compiler module for the packaged Java source bridge.
2026-10-07 16:50:41 +08:00
Kaoru0822andClaude Opus 5.5 73370e1c06 fix(dotnet): treat ambiguous undecoded members as possible counterparts
An undecoded member in an ambiguous exact-signature group stays unpaired,
like a one-sided member, but the counterpart check considered only
one-sided members. A decoded member with the same declared type and name
on the other side was therefore reported as removed or added. Ambiguous
candidates now count as possible changed counterparts too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 08:48:01 +00:00
Kaoru0822andClaude Opus 5.5 b08228d19f fix(artifacts): project compiled AppKit actions from the control to its target
NSNibControlConnector archives the sending control as NSSource and the
action target as NSDestination; a nil target is the first responder. The
NIBArchive projection swapped them for control connectors, so every
compiled AppKit action ran from its target to the control. The action
trace, which follows control -> action, could not find them, and the
selector node was keyed by the control instead of the target class. When
the target was nil, the swapped source was null and the action was
dropped: Chess lost 29 menu actions, KeepingYouAwake 7.

Connectors now keep NSSource -> NSDestination. The NIBArchive test
encoder moves to a fixture module so a bundle test can build compiled
NIBs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 08:39:27 +00:00
Kaoru0822 767c6c9a95 Merge remote-tracking branch 'origin/main' into fix/managed-comparison-undecoded-signatures
# Conflicts:
#	docs/product-catalog.json
#	docs/verification/managed-conformance-manifest.json
#	skills/reverse-engineer-anything/SKILL.md
#	src/generatedMcpToolCatalog.ts
2026-10-07 08:36:16 +00:00
ysopwnable f430c416c7 feat(browser): trace captured website source-map locations (#897)
* refactor(browser): share captured-script acquisition boundaries

Reuse stable capture/source acquisition and identity validation for module
and source-map analysis. Preserve host I/O, malformed input, unavailable
source and digest mismatch diagnostics.

Refs #851

Assisted-by: Yukari (gensokyo-skills:yukari-boundary-analysis)
Assisted-by: Kogasa (gensokyo-skills:kogasa-surprise-testing)

* feat(browser): trace captured website source-map locations

Refs #851. Preserve selected capture/map byte identity, duplicate mappings and embedded source evidence through the pinned upstream codec.

Assisted-by: Yukari (gensokyo-skills:yukari-boundary-analysis)
Assisted-by: Kogasa (gensokyo-skills:kogasa-surprise-testing)

* test(browser): verify source-map artifacts and synchronize generated contracts

Cover byte-preserving map reads and actionable filesystem constraints. Refresh generated public schemas and metadata on current main.

Assisted-by: Yukari (gensokyo-skills:yukari-boundary-analysis)
Assisted-by: Kogasa (gensokyo-skills:kogasa-surprise-testing)

* fix(browser): preserve inert source-map URL context

The selected URL is local codec context and grants no transport authority. Preserve its reported text and verify normal/userinfo contexts through real public interfaces, alongside independent manifest byte identity.

Assisted-by: Yukari (gensokyo-skills:yukari-boundary-analysis)
Assisted-by: Kogasa (gensokyo-skills:kogasa-surprise-testing)
2026-10-07 16:21:18 +08:00
Kaoru0822andClaude Opus 5.5 5afd8a850b fix(plist): keep character references beyond Unicode literal
Reserving the __proto__ placeholder decodes the whole document, so
<![CDATA[&#x110000;]]> or a comment with an out-of-range reference
threw a RangeError, and every XML plist reader failed on a valid
document. References beyond U+10FFFF now stay as written. The XML
decoder still rejects them outside comments and CDATA.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 08:12:59 +00:00
Kaoru0822andClaude Opus 5.5 9f48a76e11 fix(javascript): keep literal HTTP methods on storage-named receivers
A receiver spelled indexedDB or caches does not prove the binding, so
indexedDB.open("GET", "/api") keeps its endpoint. Such receivers
still need a standard HTTP method literal: a computed first argument or
an uppercase database name such as "APP" reads as storage, not XHR.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 08:12:14 +00:00