Skip to content

fix: comprehensive hardening across engine lifecycle, storage, replay security, and surfaces - #21

Merged
Tuanpluss02 merged 14 commits into
mainfrom
fix/comprehensive-hardening
Oct 28, 2026
Merged

Tuanpluss02 merged 14 commits into
mainfrom
fix/comprehensive-hardening

Conversation

@Tuanpluss02

Copy link
Copy Markdown
Owner

Description

Comprehensive hardening across core engine lifecycle, hybrid RAM/disk storage, replay SSRF/resource security, MCP server, and UI surfaces:

  1. Core Engine & Lifecycle (C1, C3, C4):

    • Separate manual pause intent (_enabled) from release permission check (isEnabled = _enabled && shouldEnableCapture(...)), gating background workers and storage init in release mode.
    • Accept authentic terminal responses over synthetic timeouts without permanent rejection.
    • Preserve manual pause state across engine reconfigurations.
  2. Adapters & Transport (A2, A3, Socket.IO, HTTP, Chopper):

    • Preserve authentic original request tuple (method, URL, headers, body) on Dio redirects without partial URL mutation.
    • Mutate ResponseBody.stream in place on existing object to preserve extra metadata and onClose cleanup callbacks.
    • Deduplicate repeated InterceptlySocketIo.attach calls per Socket via Expando and record connect_error frames rather than closing sessions on transient reconnects.
    • Defensive copy request/response headers via Map.of() in HTTP client and Chopper interceptor.
  3. Replay & Security (S2, S3, S4, F1):

    • Disable automatic redirect following (request.followRedirects = false;) to capture 3xx responses directly and prevent redirect SSRF bypasses.
    • Cap replay response body streams at 10 MB with a 15-second timeout and force-close client on error/timeout.
    • Normalize IPv4-mapped IPv6 (::ffff:w.x.y.z), byte-mask ULA (fc00::/7), and byte-mask Link-Local (fe80::/10) private addresses.
    • Add explicit UI confirmation when replaying requests with truncated bodies.
  4. Storage & Search (C2, C5, C6, F6, F7, F10):

    • Wire live rotation closure provider (fileRotationCountProvider) through engine, scope, and UI master search to prune expired entries.
    • Retain valid backing file path across runtime persistToDisk toggles.
    • Roll back to intact file handles on non-destructive reset failure, or enter degraded memory mode on destructive reset without crashing append().
    • Return empty page when search since_id cursor is missing from candidates.
    • Detect truncated file reads (bytes.length < length) as unavailable payloads in RealtimeStore.
  5. Surfaces, Realtime & Sharing (S1, S5, S6, S7, F2, F4, F5, F8, F9):

    • Retain staged export files across mobile share chooser intents and add purgeStaleExports for temporary files older than 1 hour.
    • Throw MultipleAppsException in MCP AppDiscovery when multiple apps run without an explicit --uri.
    • Export valid UTF-8 multipart in Postman as mode: raw with text language option; emit diagnostic warning for binary/missing bodies.
    • Deduplicate in-flight JsonViewer async flatten isolate jobs and reset loading spinner on errors.
    • Prevent search input from being wiped during active typing debounce on scope rebuilds.
    • Manage 1 Hz duration ticker lifecycle in _RealtimeRowState on pending-to-closed transitions.
    • Transmit raw Uint8List bytes when resending binary frames.
    • Complete superseded/cancelled master search completers cleanly.
    • Safely coerce and validate non-string uri arguments in MCP connect_app.

Type of Change

  • fix: A bug fix
  • test: Adding or correcting tests

Affected Packages

  • interceptly (Core package & UI overlay)
  • interceptly_dio
  • interceptly_http
  • interceptly_chopper
  • interceptly_socket_io
  • interceptly_mcp

Quality Checklist

  • My PR title follows Conventional Commits: type(scope): subject.
  • I ran melos run check locally and it passed with zero errors/warnings.
  • I added/updated unit or widget tests for my changes (895 / 895 tests passing).
  • All new and existing tests pass (melos run test:core).
  • Package health evaluated at 160/160 pub points (melos run pana).

…eam error recovery, and search/realtime bounds
…earch races, Unicode folding, and public API surface
…tream identity

- Preserve original request URL, method, headers, and body without partial redirect mutation
- Mutate responseBody.stream in place on existing ResponseBody instance to preserve extra and onClose callbacks
- Add redirect and stream identity unit and characterization regressions
…on uri input

- Deduplicate discovered apps across all DTD/DDS endpoints and throw MultipleAppsException on ambiguous targets
- Safely string-convert and validate loopback address in connect_app tool handler
- Add comprehensive discovery and input validation tests
…onnectable sessions on transient errors

- Deduplicate repeated attaches on identical Socket instances via Expando
- Record connect_error as incoming frame to preserve session continuity during auto-reconnect
- Add tracker lifecycle and attachment deduplication tests
- Prevent caller header map mutations from mutating captured records
- Use Map.of snapshot on request begin and response amend
…orage, replay security, and surfaces

- Engine & Lifecycle: separate manual pause intent from release permission check; accept authentic responses replacing synthetic timeouts; preserve manual pause across reconfigurations
- Storage & Search: live rotation closure provider wiring across engine/scope/search; retain valid backing file path across runtime persistence toggles; recover intact BodyStore file handles on reset failure and prevent invalidation on uninitialized stores; return empty list for missing search since_id cursor
- Replay & Security: block automatic redirects to capture 3xx directly; cap replay body streams at 10MB with 15s timeout and forceClose; normalize IPv4-mapped IPv6 and byte-mask ULA (fc00::/7) and Link-Local (fe80::/10); confirm replay with truncated bodies
- Surfaces & Realtime: retain staged export artifacts for async mobile shares and purge stale temp files; honest Postman multipart raw UTF-8 export with diagnostic fallback; deduplicate in-flight JsonViewer async flattener jobs; guard search debounce from rebuild wiping; manage realtime row duration ticker lifecycle; resend authentic binary Uint8List frames
- Add extensive unit, widget, and regression suites achieving 100% pass across 895 tests and 160/160 pana health score
The nested ListView.separated had no explicit padding, so Flutter applied
MediaQuery.padding.bottom inside the bordered card, leaving ~34px of dead
space under the last domain row. Opt out with EdgeInsets.zero and cover it
with a widget test asserting the card is only borders taller than its row.
Wrap the Overview tab body in SelectionArea so URL, method, status,
sizes, error and timestamp can be selected and copied, including across
rows. Search highlighting keeps working because the rows stay Text/Text.rich
instead of per-widget SelectableText. Covered by widget tests for the
selection area and for the long-press copy toolbar.
@Tuanpluss02
Tuanpluss02 merged commit 70f5960 into main Oct 28, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant