You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Follow-up to #338 / PR #339. That PR attributes subprocess egress-proxy audit events (egress_allowed / egress_blocked with "source":"proxy") to their task_id + correlation_id by stamping the IDs into the HTTP_PROXY userinfo, which HTTP clients replay as a Basic Proxy-Authorization header. This covers the two HTTP_PROXY-injecting executors (SkillCommandExecutor, CLIExecuteTool).
The browser is the one remaining subprocess egress path and it is not covered: browser egress proxy events still emit with no task_id / correlation_id.
No userinfo replay. Chrome does not turn proxy-URL userinfo into a preemptive Proxy-Authorization header the way curl/Go/Python do. It waits for a 407 challenge and handles auth through the CDP Fetch domain (Fetch.authRequired → Fetch.continueWithAuth), so the identityFromRequest decode on the proxy side never sees credentials.
Shared proxy, many sessions. A single EgressProxy serves every browser session, so even a static credential couldn't distinguish which task a given request belongs to without per-request or per-session identity.
Options
CDP Fetch auth injection — enable Fetch in the browser session and answer authRequired with Basic base64(b64url(task):b64url(corr)) per session, so Chrome sends the same Proxy-Authorization the exec path stamps. Reuses the proxy-side decode unchanged. Most consistent with Egress: subprocess proxy audit events missing task_id / correlation_id #338.
Per-invocation proxy listener — bind a dedicated proxy port per task with the identity baked in; Chrome points at that. Heavier (one listener per active browser task) but tamper-proof and needs no CDP auth dance.
CDP request interception — attribute via Network/Fetch request metadata inside the browser manager rather than at the proxy, emitting the audit event from the manager (which has the task ctx) instead of the proxy OnAttempt.
Problem
Follow-up to #338 / PR #339. That PR attributes subprocess egress-proxy audit events (
egress_allowed/egress_blockedwith"source":"proxy") to theirtask_id+correlation_idby stamping the IDs into theHTTP_PROXYuserinfo, which HTTP clients replay as a BasicProxy-Authorizationheader. This covers the twoHTTP_PROXY-injecting executors (SkillCommandExecutor,CLIExecuteTool).The browser is the one remaining subprocess egress path and it is not covered: browser egress proxy events still emit with no
task_id/correlation_id.Why the #338 mechanism doesn't apply
The browser doesn't use the
HTTP_PROXYenv var. Chrome is pointed at the egress proxy via chromedp's--proxy-serverflag:Two blockers:
Proxy-Authorizationheader the way curl/Go/Python do. It waits for a407challenge and handles auth through the CDPFetchdomain (Fetch.authRequired→Fetch.continueWithAuth), so theidentityFromRequestdecode on the proxy side never sees credentials.EgressProxyserves every browser session, so even a static credential couldn't distinguish which task a given request belongs to without per-request or per-session identity.Options
Fetchin the browser session and answerauthRequiredwithBasic base64(b64url(task):b64url(corr))per session, so Chrome sends the sameProxy-Authorizationthe exec path stamps. Reuses the proxy-side decode unchanged. Most consistent with Egress: subprocess proxy audit events missing task_id / correlation_id #338.Network/Fetchrequest metadata inside the browser manager rather than at the proxy, emitting the audit event from the manager (which has the task ctx) instead of the proxyOnAttempt.Acceptance criteria
egress_allowed/egress_blocked("source":"proxy") carrytask_id+correlation_id.Files
forge-cli/tools/browser/manager.go— chromedp proxy wiring (ProxyServer)forge-core/security/egress_proxy.go—identityFromRequest(reused if the CDP-auth option is chosen)