Skip to content

v0.2.0 — research workbench

Choose a tag to compare

@anasfik anasfik released this 29 Oct 22:42
· 25 commits to main since this release

On-device Flutter app research workbench. Offline, no root, no INTERNET permission.

What changed in 0.2.0

Scanning that survives real use

  • One foreground scan owner shared by the UI and the headless am start -e scan entry, so a scan
    keeps running when you leave the screen. Terminal notification when it finishes or fails.
  • Per-job identity: a timed-out or cancelled scan can never write into a newer report.
  • Cooperative cancellation at every pipeline checkpoint, staged progress, 20-minute per-app bound.
  • The installed-app inventory is cached in-process — going back from a report no longer reloads
    the whole device list.
  • Atomic report and history writes (temp file, fsync, rename) with inflight markers, so a kill
    leaves either the old report or the new one, never half of each.

A real report UI

  • Navigation is now real routes: Home → Details → Section, with one Back handler, so Back from a
    See-all list returns to the report, and Back from the report returns to the loaded inventory.
  • Three panes: Overview (grade with a stated reason, severity summary including zero rows,
    artifact, extraction/Flutter-check metadata, signing, change card), Findings (expandable
    rows, masked evidence, per-row reveal), Explore (endpoints, candidate route tree,
    dependencies with pub.dev links, recovered paths, channels, APK artifact browser).
  • Long sections show a bounded window plus See all, which opens a searchable full-screen list
    instead of an endless inline scroll.
  • Scan all Flutter apps queues every detected app behind a cost dialog, with a dedicated queue
    screen: live per-app stage, determinate bar, cancel with confirmation, honest done/cancelled
    counts.
  • Every scan is appended to a per-app, versioned, bounded scan log; change cards are computed from
    it.

Evidence you can trust

  • Sensitive values are masked by construction; full values live only in memory, are never
    serialized, never logged, and reset when you switch apps. A report loaded from disk says
    "rescan to reveal" rather than showing a dead control.
  • Revealing a value sets FLAG_SECURE on that screen and marks clipboard copies sensitive.
  • Endpoints open exactly the URL shown, or are labelled not openable. Recovered strings that look
    like concatenations are demoted, not presented as hosts. Candidate routes are grouped by prefix
    and never drawn as a navigation graph.
  • The grade legend is derived from the actual counts: an F earned on weighted severity no longer
    claims critical findings.

Exports

  • Section-selected JSON or Markdown, default-redacted, with an explicit per-export opt-in for
    sensitive values. Unique file names, and an unknown format is an error instead of a silent
    Markdown fallback.

Design

  • Semantic Material 3 tokens: one radius family, scheme-derived severity colours, one cyan accent,
    a 4/8/12/16/24/32 spacing scale, 48 dp targets, light and dark both verified on device.

Requirements

Android 8.0+ (API 26). Sideload the signed APK; no Play Services needed.

Verification

217 unit tests green. Verified on a physical Redmi Note 9 Pro (LineageOS, API 35): inventory
caching, scan continuity across navigation, queue start/cancel, stored-report loading, endpoint
honesty, masked evidence, exports, light and dark rendering.

Known limits

Candidate routes are recovered strings, not a navigation path. libapp.so is AOT machine code:
you get strings, symbols and routes, not decompiled Dart. AABs are not supported. Signature
verification is structural, not a full apksigner check. Dependencies and APK artifacts still
filter inline in Explore rather than routing to their own full-screen search.