[PR #2961] [CLOSED] fix(security): bound scenario retention and loopback admission #5517

Closed
opened 2026-10-31 01:07:15 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/2961
Author: @cybrking
Created: 10/13/2026
Status: ❌ Closed

Base: main ← Head: fix/security-resource-boundaries


📝 Commits (1)

  • 8cbb79e fix(security): bound scenario retention and bridge admission

📊 Changes

13 files changed (+756 additions, -119 deletions)

View changed files

📝 bridge/ghidra/ReaGhidraBridge.java (+78 -14)
📝 docs/browser-scenario-contract.md (+22 -0)
📝 docs/testing.md (+10 -0)
📝 src/browser/BrowserScenarioSecrets.ts (+22 -0)
📝 src/browser/PlaywrightScenarioEvents.test.ts (+105 -36)
📝 src/browser/PlaywrightScenarioEvents.ts (+82 -9)
📝 src/browser/network/PlaywrightNetworkContent.ts (+39 -4)
📝 src/browser/network/PlaywrightScenarioNetwork.test.ts (+83 -1)
📝 src/browser/network/PlaywrightScenarioNetwork.ts (+131 -42)
📝 src/ghidra/GhidraClient.ts (+39 -13)
📝 tests/boundary/providers/ghidra/ghidraClient.test.ts (+29 -0)
📝 tests/fixtures/fakeGhidra.mjs (+9 -0)
➕ tests/fixtures/ghidraHandshakeProbe.py (+107 -0)

📄 Description

Summary

Bound browser scenario retention and content scheduling, and reject unauthenticated loopback clients without consuming the Ghidra session. This is a draft with partial browser remediation: Playwright body acquisition still needs a separately enforced producer memory boundary. No issue is linked because this follows a requested repository security review.

Problem and expected behavior

Scenario events and selected network work previously accumulated without collection budgets. The loopback bridge also allowed its first unauthenticated connection to consume the sole session. Resource omissions must remain visible in evidence, and rejected handshake clients must leave the bridge available for its legitimate caller.

Change and scope

  • Reserve event allocation before schema cloning: 16 MiB aggregate, 4 MiB per event, 10,000 events, and 2,048 live listener owners. Check raw strings before normalization and reserve secret replacement expansion and per-match allocation. Omit whole events with dropped counts and limitations.
  • Admit at most 1,024 network transactions and 16 concurrent bounded content jobs before producer invocation; deduplicate request content scheduling. Retain source-event integrity when metadata is omitted. Report oversized headers, body copies, and excess jobs as unavailable.
  • Bound the loopback first frame to 64 KiB and an absolute one-second deadline. Close rejected clients and accept another connection. Preserve pipelined and larger authenticated requests. Retry initial loopback transport failures at most twice within the original startup deadline, detaching old socket state first.
  • Document limits and add production-boundary regressions, including an isolated JDK TCP harness.

Contract and boundary impact

  • Semantic owner: scenario event/network producers and loopback bridge admission.
  • Contribution scope: ordinary security fixes within existing boundaries; advance scope decision not applicable.
  • CLI/MCP schemas and catalog: unchanged. Existing dropped/unavailable/limitations fields now describe resource omissions. Oversized or high-volume captures retain less evidence.
  • Compatibility: UNIX admission remains unchanged. Loopback authentication and identity validation remain in force; only initial transport failures are retried.
  • Provenance/cleanup: request object identities and retained source-event links remain authoritative; existing process supervision, parent startup deadline, and cleanup ownership remain in place.
  • Target authority: no new target selection, instrumentation, mutation, or network capability. Existing browser and bridge workflows still perform their existing process/network interactions.
  • Generated metadata, package, installation: no authored package metadata or installation changes; generated artifacts are uncommitted.

Evidence and regression coverage

Executed regression coverage includes ordinary event/content controls, individual and aggregate retention budgets, count exhaustion, listener capacity reuse, producer non-invocation after admission rejection, redaction expansion, dropped metadata, loopback reconnect/retry exhaustion, and normal provider cleanup.

The JDK harness compiles the production preauthentication read and accept methods with parsing/dispatch fixture seams. It executes rejection, EOF, frame ceiling, idle and slow-trickle deadlines, acceptance of a later valid client, pipelined requests, and authenticated requests larger than the handshake ceiling. It does not compile or run the complete Ghidra engine bridge.

Base vulnerability analysis was source-derived. The new budget/retry assertions contradict the former unbounded/terminal behavior; no exploit was run against a deployed application.

  • Observed, derived, and inferred claims remain distinguishable.
  • Artifact identity, source provenance, and failed attempts remain preserved.
  • Incomplete and unavailable outcomes remain visible.

Validation performed

  • Focused browser event/network/session/provider suites — 50 distinct tests passed across focused runs.
  • npm run test:focused -- tests/boundary/providers/ghidra/ghidraClient.test.ts tests/boundary/providers/ghidra/ghidraTransport.test.ts — 41 tests passed.
  • python3 tests/fixtures/ghidraHandshakeProbe.py /path/to/java — passed with a temporary Temurin JDK 21 on macOS.
  • npm run check — passed typecheck, compiled lint, formatting, knip, metadata, module boundaries, and architecture guards.
  • npm run docs:check — passed, including five README consistency tests.
  • npm run verify:test-discovery — all 1,112 test files discovered exactly once.
  • git diff --check — passed.

Compatibility, safety, and release

Unresolved browser acquisition boundary: Response.body() still materializes the complete buffer before the 64 KiB retention check. Incoming Playwright payloads and headers are likewise acquired before adapter admission. A timeout settles a capture job but does not cancel its underlying producer operation. These limits reduce retained copies and scheduled work; they do not establish a complete host-memory bound or close the full browser finding. Preserving body semantics requires supervised producer isolation with enforced memory limits, or a separately designed bounded CDP collector with correct transaction identities and explicit provenance.

The loopback change bounds disruption by an individual rejected client. Repeated queued connections can still delay startup. A real Windows Ghidra lane and a real-browser resource-isolation lane were unavailable on this macOS host; those remain required before treating the relevant platform/containment claims as established.

Before merge

  • Concrete problem and Conventional Commit title.
  • Regression checks, owning documentation, and final diff reviewed.
  • Resolve the remaining producer acquisition boundary or explicitly accept this as a limited mitigation.
  • Complete required real Windows Ghidra/provider validation.

🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/morluto/rea/pull/2961 **Author:** [@cybrking](https://github.com/cybrking) **Created:** 10/13/2026 **Status:** ❌ Closed **Base:** `main` ← **Head:** `fix/security-resource-boundaries` --- ### 📝 Commits (1) - [`8cbb79e`](https://github.com/morluto/rea/commit/8cbb79eedb27ba196708501b143fbf8c606ce34a) fix(security): bound scenario retention and bridge admission ### 📊 Changes **13 files changed** (+756 additions, -119 deletions) <details> <summary>View changed files</summary> 📝 `bridge/ghidra/ReaGhidraBridge.java` (+78 -14) 📝 `docs/browser-scenario-contract.md` (+22 -0) 📝 `docs/testing.md` (+10 -0) 📝 `src/browser/BrowserScenarioSecrets.ts` (+22 -0) 📝 `src/browser/PlaywrightScenarioEvents.test.ts` (+105 -36) 📝 `src/browser/PlaywrightScenarioEvents.ts` (+82 -9) 📝 `src/browser/network/PlaywrightNetworkContent.ts` (+39 -4) 📝 `src/browser/network/PlaywrightScenarioNetwork.test.ts` (+83 -1) 📝 `src/browser/network/PlaywrightScenarioNetwork.ts` (+131 -42) 📝 `src/ghidra/GhidraClient.ts` (+39 -13) 📝 `tests/boundary/providers/ghidra/ghidraClient.test.ts` (+29 -0) 📝 `tests/fixtures/fakeGhidra.mjs` (+9 -0) ➕ `tests/fixtures/ghidraHandshakeProbe.py` (+107 -0) </details> ### 📄 Description ## Summary Bound browser scenario retention and content scheduling, and reject unauthenticated loopback clients without consuming the Ghidra session. This is a **draft with partial browser remediation**: Playwright body acquisition still needs a separately enforced producer memory boundary. No issue is linked because this follows a requested repository security review. ## Problem and expected behavior Scenario events and selected network work previously accumulated without collection budgets. The loopback bridge also allowed its first unauthenticated connection to consume the sole session. Resource omissions must remain visible in evidence, and rejected handshake clients must leave the bridge available for its legitimate caller. ## Change and scope - Reserve event allocation before schema cloning: 16 MiB aggregate, 4 MiB per event, 10,000 events, and 2,048 live listener owners. Check raw strings before normalization and reserve secret replacement expansion and per-match allocation. Omit whole events with dropped counts and limitations. - Admit at most 1,024 network transactions and 16 concurrent bounded content jobs before producer invocation; deduplicate request content scheduling. Retain source-event integrity when metadata is omitted. Report oversized headers, body copies, and excess jobs as unavailable. - Bound the loopback first frame to 64 KiB and an absolute one-second deadline. Close rejected clients and accept another connection. Preserve pipelined and larger authenticated requests. Retry initial loopback transport failures at most twice within the original startup deadline, detaching old socket state first. - Document limits and add production-boundary regressions, including an isolated JDK TCP harness. ## Contract and boundary impact - Semantic owner: scenario event/network producers and loopback bridge admission. - Contribution scope: ordinary security fixes within existing boundaries; advance scope decision not applicable. - CLI/MCP schemas and catalog: unchanged. Existing dropped/unavailable/limitations fields now describe resource omissions. Oversized or high-volume captures retain less evidence. - Compatibility: UNIX admission remains unchanged. Loopback authentication and identity validation remain in force; only initial transport failures are retried. - Provenance/cleanup: request object identities and retained source-event links remain authoritative; existing process supervision, parent startup deadline, and cleanup ownership remain in place. - Target authority: no new target selection, instrumentation, mutation, or network capability. Existing browser and bridge workflows still perform their existing process/network interactions. - Generated metadata, package, installation: no authored package metadata or installation changes; generated artifacts are uncommitted. ## Evidence and regression coverage Executed regression coverage includes ordinary event/content controls, individual and aggregate retention budgets, count exhaustion, listener capacity reuse, producer non-invocation after admission rejection, redaction expansion, dropped metadata, loopback reconnect/retry exhaustion, and normal provider cleanup. The JDK harness compiles the production preauthentication read and accept methods with parsing/dispatch fixture seams. It executes rejection, EOF, frame ceiling, idle and slow-trickle deadlines, acceptance of a later valid client, pipelined requests, and authenticated requests larger than the handshake ceiling. It does not compile or run the complete Ghidra engine bridge. Base vulnerability analysis was source-derived. The new budget/retry assertions contradict the former unbounded/terminal behavior; no exploit was run against a deployed application. - [x] Observed, derived, and inferred claims remain distinguishable. - [x] Artifact identity, source provenance, and failed attempts remain preserved. - [x] Incomplete and unavailable outcomes remain visible. ## Validation performed - Focused browser event/network/session/provider suites — 50 distinct tests passed across focused runs. - `npm run test:focused -- tests/boundary/providers/ghidra/ghidraClient.test.ts tests/boundary/providers/ghidra/ghidraTransport.test.ts` — 41 tests passed. - `python3 tests/fixtures/ghidraHandshakeProbe.py /path/to/java` — passed with a temporary Temurin JDK 21 on macOS. - `npm run check` — passed typecheck, compiled lint, formatting, knip, metadata, module boundaries, and architecture guards. - `npm run docs:check` — passed, including five README consistency tests. - `npm run verify:test-discovery` — all 1,112 test files discovered exactly once. - `git diff --check` — passed. ## Compatibility, safety, and release **Unresolved browser acquisition boundary:** `Response.body()` still materializes the complete buffer before the 64 KiB retention check. Incoming Playwright payloads and headers are likewise acquired before adapter admission. A timeout settles a capture job but does not cancel its underlying producer operation. These limits reduce retained copies and scheduled work; they do **not** establish a complete host-memory bound or close the full browser finding. Preserving body semantics requires supervised producer isolation with enforced memory limits, or a separately designed bounded CDP collector with correct transaction identities and explicit provenance. The loopback change bounds disruption by an individual rejected client. Repeated queued connections can still delay startup. A real Windows Ghidra lane and a real-browser resource-isolation lane were unavailable on this macOS host; those remain required before treating the relevant platform/containment claims as established. ## Before merge - [x] Concrete problem and Conventional Commit title. - [x] Regression checks, owning documentation, and final diff reviewed. - [ ] Resolve the remaining producer acquisition boundary or explicitly accept this as a limited mitigation. - [ ] Complete required real Windows Ghidra/provider validation. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
bsakaguchi 2026-10-31 01:07:15 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#5517
No description provided.