-
Notifications
You must be signed in to change notification settings - Fork 24
Expand file tree
/
Copy pathssrf-protection.html
More file actions
220 lines (206 loc) · 28.9 KB
/
Copy pathssrf-protection.html
File metadata and controls
220 lines (206 loc) · 28.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Runtime outbound URL and SSRF protection</title>
<style>
:root{--bg:#151611;--pan:#1d1f18;--pan-2:#23251d;--bd:#34372b;--tx:#d2cfbd;--dim:#9c9988;
--ink:#f5f2e8;--acc:#e09348;--blue:#6a9cf7;--green:#6ab95f;--purple:#ad82ed;--red:#ec6374;--code:#10110d}
*{box-sizing:border-box}html{scroll-behavior:smooth}
body{margin:0;background:var(--bg);color:var(--tx);font:16px/1.78 -apple-system,BlinkMacSystemFont,
"Segoe UI",sans-serif;padding:52px 30px 120px;text-rendering:optimizeLegibility}
.wrap{max-width:1240px;margin:auto}h1,h2,h3{color:var(--ink);text-wrap:balance}
h1{font-family:"Avenir Next Condensed","Arial Narrow",sans-serif;font-size:42px;line-height:1.12;
letter-spacing:.015em;margin:0 0 14px}h2{font-size:23px;line-height:1.35;margin:50px 0 14px;scroll-margin-top:92px}
h3{font-size:18px;line-height:1.45;margin:34px 0 11px;scroll-margin-top:92px}
p{margin:0 0 14px}.sub,.lead{color:var(--dim);max-width:80ch}.sub{font-size:17px;line-height:1.7}
.eyebrow{color:var(--acc);font:700 12px/1.4 Menlo,monospace;letter-spacing:.16em;margin:0 0 13px}
.toc{position:sticky;top:12px;z-index:20;display:flex;gap:8px;flex-wrap:wrap;margin:28px 0 42px;
padding:10px;background:color-mix(in srgb,var(--bg) 88%,transparent);border:1px solid var(--bd);
border-radius:14px;backdrop-filter:blur(14px)}
.toc a{color:var(--tx);text-decoration:none;border:1px solid transparent;border-radius:8px;padding:7px 12px;
font-size:14px;font-weight:600;background:var(--pan)}.toc a:hover{color:var(--ink);border-color:var(--acc)}
a:focus-visible{outline:3px solid var(--blue);outline-offset:3px}
.band{display:grid;grid-template-columns:150px minmax(0,1fr);gap:24px;align-items:start;border:1px solid var(--bd);
border-top:4px solid var(--blue);border-radius:14px;padding:24px;background:var(--pan);margin:54px 0 18px;
scroll-margin-top:92px}.band.ref{border-top-color:var(--purple)}.band.plan{border-top-color:var(--green)}
.part{color:var(--blue);font:700 13px/1.4 Menlo,monospace;letter-spacing:.12em;text-transform:uppercase}
.band.ref .part{color:var(--purple)}.band.plan .part{color:var(--green)}
.band b{display:block;color:var(--ink);font-size:21px;line-height:1.35;margin-bottom:7px}.band p{margin:0;max-width:84ch}
.num{display:inline-block;color:var(--dim);font:600 12px/1 Menlo,monospace;margin-right:10px;letter-spacing:.08em}
.note{border-left:4px solid var(--acc);padding:10px 0 10px 17px;color:var(--dim);max-width:92ch;margin:18px 0;
font-size:15.5px}.note.red{border-left-color:var(--red)}.note.green{border-left-color:var(--green)}.note b{color:var(--ink)}
code{background:var(--code);color:#efaa67;padding:2px 6px;border-radius:5px;font:13.5px/1.5 Menlo,monospace;
overflow-wrap:anywhere}.tbl{overflow:auto;border:1px solid var(--bd);border-radius:14px;background:var(--pan);
margin:16px 0 25px;scrollbar-color:var(--dim) var(--code)}
table{width:100%;border-collapse:separate;border-spacing:0;min-width:940px;font-size:14.5px;line-height:1.62}
th{text-align:left;color:#aaa795;background:var(--pan-2);font-size:12.5px;letter-spacing:.075em;padding:13px 16px;
border-bottom:1px solid var(--bd);white-space:nowrap}td{padding:14px 16px;vertical-align:top;border-bottom:1px solid #2b2d24}
th:first-child,td:first-child{position:sticky;left:0;z-index:2;background:var(--pan);box-shadow:1px 0 var(--bd)}
th:first-child{z-index:3;background:var(--pan-2)}tr:last-child td{border-bottom:0}tr:hover td{background:#22241c}
tr:hover td:first-child{background:#22241c}td b{color:var(--ink)}.yes{color:#79c970}.no{color:#f07384}.partial{color:#efa457}
.flow{display:grid;grid-template-columns:1fr 44px 1fr 44px 1fr;gap:10px;align-items:stretch;margin:20px 0 28px}
.box{border:1px solid var(--bd);border-radius:13px;background:var(--pan);padding:18px}.box h3{margin:0 0 8px}
.arrow{display:grid;place-items:center;color:var(--acc);font-size:28px}.small{font-size:13.5px;color:var(--dim)}
ul{padding-left:24px;max-width:92ch}li{margin:9px 0}a{color:#8bb2fb;text-underline-offset:3px}
@media(max-width:820px){body{padding:32px 16px 80px;font-size:16px}h1{font-size:34px}h2{font-size:21px;margin-top:42px}
.toc{position:static;margin-bottom:34px}.band{grid-template-columns:1fr;gap:8px;padding:19px;margin-top:42px}
.flow{grid-template-columns:1fr}.arrow{transform:rotate(90deg);height:26px}table{min-width:820px}}
@media(prefers-reduced-motion:reduce){html{scroll-behavior:auto}}
</style>
</head>
<body><main class="wrap">
<p class="eyebrow">SECURITY DESIGN · RUNTIME NETWORK</p>
<h1>Runtime outbound URL and SSRF protection</h1>
<p class="sub">Evidence snapshot: 2026-08-12, Runtime implementation through the Task 10 consolidated fix (Task 1–8 anchor <code>80c377fa</code>).
This document is ordered as OpenProgram current state, other projects, then the OpenProgram future plan.
Implemented behavior and future work are labeled separately.</p>
<nav class="toc">
<a href="#current">01 Current state</a><a href="#surfaces">02 Boundaries</a>
<a href="#references">03 Other projects</a><a href="#decision">04 Decisions</a>
<a href="#implementation">05 Evidence</a><a href="#future">06 Future plan</a>
</nav>
<section class="band" id="current"><span class="part">Part I · Current</span><div><b>OpenProgram current state</b>
<p>Runtime-owned HTTP requests use a registry-keyed URL policy and managed transport. The implementation validates
all DNS answers, dials only approved peers, handles redirects explicitly, confines credentials to their declared
origin, bounds response resources, and fails static verification for unclassified consumers or active unmanaged SDK transports.</p></div></section>
<h2><span class="num">01</span>Implemented boundary</h2>
<div class="tbl"><table>
<tr><th>Component</th><th>Implemented responsibility</th><th>Explicit non-responsibility</th></tr>
<tr><td><code>openprogram/security/url_policy.py</code></td><td>URL and origin normalization; scheme, userinfo, host, and port validation; full A/AAAA classification; exact owner exceptions; stable sanitized reason codes</td><td>Does not send network requests or infer a caller's trust class</td></tr>
<tr><td><code>openprogram/security/safe_http.py</code></td><td>Immutable 42-consumer registry; sync/async peer-constrained transports; Host/SNI preservation; manual redirects; credential, header, MIME, decoded-body, encoding, timeout, proxy, and atomic-download enforcement</td><td>Does not accept caller-created policy objects or expose <code>verify=False</code></td></tr>
<tr><td>Consumer adapters</td><td>Select one immutable registry key and, for configured services or callbacks, supply the exact owner-configured origin</td><td>May not implement a second private-address classifier or retry through a raw client</td></tr>
<tr><td><code>runtime_http_audit.py</code>, <code>doctor</code>, and <code>scripts/check_runtime_http.py</code></td><td>Bounded sanitized denial state, exact owner exception/proxy reporting, AST inventory, SDK disposition verification, and stale exclusion detection</td><td>Do not display userinfo, query, fragment, credentials, peer response bodies, or token-bearing paths</td></tr>
</table></div>
<h2 id="surfaces"><span class="num">02</span>Runtime consumers and separate boundaries</h2>
<div class="tbl"><table>
<tr><th>Boundary</th><th>Current treatment</th><th>Status in this feature</th></tr>
<tr><td>Arbitrary and derived Runtime URLs</td><td><code>web_fetch</code>, attachments, generated assets, image result downloads, catalogs, marketplaces, and updater metadata use managed clients with public or exact-service policy</td><td class="yes">Included</td></tr>
<tr><td>Fixed/configured APIs</td><td>Web search, image APIs, channel REST, TTS, provider listing/probes/OAuth, Web model listing, MCP HTTP/SSE, and local probes use fixed or owner-configured exact origins</td><td class="yes">Included</td></tr>
<tr><td>Third-party SDKs</td><td>Provider and MCP clients receive injected managed transports; exact-origin REST adapters remain managed; uninjectable Bedrock, Slack/Discord gateway, and edge-tts SDK paths fail closed</td><td class="yes">Included and classified</td></tr>
<tr><td>Browser navigation, popup, Service Worker, and page subresources</td><td>Governed by the browser-control design and any owner egress isolation</td><td class="no">Excluded</td></tr>
<tr><td>Sandboxed arbitrary code, plugin code, external provider CLIs, and package managers</td><td>Governed by sandbox, plugin trust, child-process, and installation boundaries</td><td class="no">Excluded</td></tr>
<tr><td>Owner control-plane liveness probes</td><td>Narrow loopback-only exclusions are inventoried with exact call kind, owner, reason, and count</td><td class="partial">Classified, not claimed as Runtime URL fetch</td></tr>
</table></div>
<div class="note"><b>Feature-matrix scope and status.</b> The implemented controls cover only Runtime-owned HTTP fetches.
The matrix records <code>◐</code> for this bounded feature after the integrated repository gate passed. Browsers, arbitrary code,
plugins, external CLIs, and package-manager child processes remain separate boundaries.</div>
<section class="band ref" id="references"><span class="part">Part II · References</span><div><b>How other projects design this boundary</b>
<p>The comparison preserves all twelve external feature-matrix columns plus OWASP. Permission prompts, hostname rules,
application URL validation, policy proxies, and operating-system network sandboxes remain distinct controls; upstream wrappers
and protocol libraries are not counted again as independent implementations.</p></div></section>
<h2><span class="num">03</span>Reference mechanisms</h2>
<div class="note"><b>Evidence boundary.</b> The matrix uses fixed snapshots. Current official documentation is linked directly
for design context, without retroactively changing the fixed-version matrix scores. Capabilities not confirmed in the audited
snapshot are described as unconfirmed, not as universally absent.</div>
<div class="tbl"><table>
<tr><th>Project</th><th>Application URL-fetch evidence</th><th>Network or permission boundary</th><th>Adopted, modified, or rejected</th></tr>
<tr><td><b>Hermes</b></td><td>Shared <code>url_safety</code> covers web, browser, vision, and gateway media. DNS failure is closed; loopback, RFC1918, link-local, CGNAT, metadata, reserved, multicast, and unspecified results are rejected; redirects are checked hop by hop; URLs are sanitized and media is streamed with limits.</td><td>A process-wide <code>allow_private_urls</code> switch relaxes multiple entries together. Application checks still do not replace OS network isolation.</td><td>Adopted shared fail-closed validation, the full address set, redirect checks, sanitization, and limits. Modified the global switch into exact consumer-scoped service-origin exceptions.</td></tr>
<tr><td><b>OpenClaw</b></td><td>Private, internal, and special-use targets are denied by default, with exact or wildcard hostname exceptions and checks before navigation, interaction-generated loads, and final URLs. Its documentation identifies speculative navigation and browser subresource risk.</td><td>Official documentation states that request interception is not a network firewall: redirects, popups, Service Workers, and background resources can still require egress isolation or a policy proxy.</td><td>Adopted strict defaults and explicit exceptions. Modified browser interception into a separate acceptance boundary; it is not Runtime-fetch evidence.</td></tr>
<tr><td><b>Claude Code</b></td><td><code>WebFetch(domain:...)</code> supports allow/deny. Before a request, the hostname is sent to the Anthropic safety blocklist; the result is cached for exactly five minutes, and the owner may disable the preflight.</td><td>The Bash sandbox uses a Seatbelt or bubblewrap HTTP/SOCKS proxy that child processes inherit. The proxy trusts the client-provided hostname and does not inspect TLS content, so broad domains and domain fronting remain risks.</td><td>Adopted layered tool authorization and child-process egress policy. Rejected hostname permission as DNS/IP/connect-time SSRF evidence.</td></tr>
<tr><td><b>Codex</b></td><td>The audited mainline does not substitute one WebFetch string check for a network boundary.</td><td><code>codex-network-proxy</code> supplies HTTP/SOCKS5 proxying, exact or restricted wildcard domains, private-resolution rejection, limited read-only methods, MITM header hooks, Unix-socket control, and structured audit; the OS sandbox constrains loopback bypass paths.</td><td>Adopted structured deny reasons, audit, and managed-policy concepts. Retained consumer-aware Runtime safe clients rather than relying only on a child-process proxy.</td></tr>
<tr><td><b>CodeBuddy 2.109.3</b></td><td><code>WebFetch</code> applies Security Center domain policy and rejects IP literals, <code>localhost</code>, and selected private ranges. WeCom media uses an official CDN allowlist with redirects disabled.</td><td>Sandbox <code>allowedDomains</code> intersects with WebFetch permission. The audited bundle's general WebFetch path checks literal hosts; the snapshot does not confirm full hostname A/AAAA validation, peer binding, or hop-by-hop redirect enforcement.</td><td>Adopted fixed channel-service allowlists and the intersection of permission and network policy. Rejected literal-IP-only protection for general fetches.</td></tr>
<tr><td><b>Gemini CLI</b></td><td>Official tool documentation warns that <code>web_fetch</code> can reach localhost and private networks; Plan Mode can require confirmation. The local 0.35.3 core contains IP classification and DNS utilities, but the warning shows they do not form a general WebFetch private-target boundary.</td><td>User confirmation is a permission decision and does not constrain the connected peer.</td><td>Adopted explicit risk documentation. Rejected confirmation as a substitute for deterministic target enforcement.</td></tr>
<tr><td><b>OpenCode</b></td><td><code>webfetch</code> permissions use the complete requested URL and support allow, ask, or deny. Current official permissions documentation does not establish private-IP classification, full DNS results, hop-by-hop redirects, or peer binding.</td><td><code>shell</code> uses the host user's network privileges; official documentation calls string rules best effort, not network isolation.</td><td>Adopted uniform resource-permission semantics. A permitted URL must still pass independent transport policy.</td></tr>
<tr><td><b>pi-mono</b></td><td>The fixed snapshot does not confirm a built-in arbitrary-URL fetch in the core product; network capability primarily comes from shell commands, installers, or user extensions.</td><td>The core snapshot does not confirm an OS egress policy. Third-party <code>pi-sandbox</code> is not counted as built-in pi-mono behavior.</td><td>Rejected it as a Runtime SSRF algorithm reference. Its extension boundary supports keeping third-party code outside safe-client completion.</td></tr>
<tr><td><b>pi-ai</b></td><td>This is protocol reference source, not a runnable product, and has no session or Runtime URL consumer.</td><td>Not applicable.</td><td>Excluded from product-level SSRF conclusions while retaining its matrix column to preserve the audited unit distinction.</td></tr>
<tr><td><b>weclaw</b></td><td>The fixed snapshot is a messaging bridge to external ACP/CLI agents and does not confirm an independent general URL fetch.</td><td>It primarily inherits the launched CLI's tools and network privileges; the delegated product's controls are not counted again for weclaw.</td><td>Retained channel-media and external-process launch as its relevant boundaries; rejected it as a general safe-HTTP reference.</td></tr>
<tr><td><b>cc-internal / cx-internal / gm-internal</b></td><td><code>cc-internal</code> and <code>cx-internal</code> wrap upstream launchers; <code>gm-internal</code> substantially reuses Gemini CLI. The audited packages do not confirm independent strengthening of general URL-fetch policy.</td><td>They inherit most Claude Code, Codex, or Gemini CLI permission and network behavior. Added authentication or endpoints do not themselves create an SSRF boundary.</td><td>Audited only their additional endpoints, credential forwarding, and configuration differences; rejected double-counting them as three independent security designs.</td></tr>
<tr><td><b>OWASP</b></td><td>Separates known-service allowlisting from arbitrary-public-target validation, restricts protocols, validates every A/AAAA result, and prefers allowlists for trusted services.</td><td>A single DNS preflight still has DNS pinning and time-of-check/time-of-use risk; network controls are also recommended.</td><td>Adopted separate trust classes and connect-time peer constraints. Rejected one preflight DNS result as the only boundary.</td></tr>
</table></div>
<p class="small">Primary sources:
<a href="https://github.com/NousResearch/hermes-agent/blob/main/tools/url_safety.py">Hermes url_safety.py</a>,
<a href="https://hermes-agent.nousresearch.com/docs/user-guide/security/">Hermes Security</a>,
<a href="https://docs.openclaw.ai/gateway/security">OpenClaw Security</a>,
<a href="https://code.claude.com/docs/en/sandboxing">Claude Code Sandboxing</a>,
<a href="https://code.claude.com/docs/en/data-usage">Claude Code WebFetch safety check</a>,
<a href="https://github.com/openai/codex/blob/main/codex-rs/network-proxy/README.md">Codex network proxy</a>,
<a href="https://opencode.ai/v2/docs/permissions">OpenCode Permissions</a>,
<a href="https://github.com/google-gemini/gemini-cli/blob/main/docs/reference/tools.md">Gemini CLI tools</a>,
and
<a href="https://cheatsheetseries.owasp.org/cheatsheets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet.html">OWASP SSRF Prevention</a>.</p>
<p class="small">Versioned local snapshot evidence: <code>@tencent-ai/codebuddy-code@2.109.3 dist/codebuddy.js,
CHANGELOG.md, dist/web-ui/docs/cn/cli/permissions.md</code>; <code>@google/gemini-cli@0.35.3 core/dist/src/utils/fetch.js</code>;
<code>references/pi-mono@3eb002766fff</code>; <code>references/weclaw@10711d0c6b7e</code>; and <code>references/pi-ai</code>.</p>
<h2 id="decision"><span class="num">04</span>Adopted, modified, and rejected choices</h2>
<div class="tbl"><table>
<tr><th>Decision</th><th>Mechanism</th><th>Reason</th></tr>
<tr><td class="yes">Adopted</td><td>One pure URL/IP policy; all DNS answers must pass; DNS failure is closed; every redirect is reevaluated; errors are origin-only; decoded bodies are bounded</td><td>These checks cover the Runtime's target, redirect, credential, and resource boundaries consistently.</td></tr>
<tr><td class="yes">Adopted</td><td>Distinct untrusted-public, fixed-public-service, configured-service, and loopback-callback trust classes</td><td>Owner-configured localhost/private services remain usable without granting arbitrary public consumers private-network access.</td></tr>
<tr><td class="yes">Adopted</td><td>Claude Code and CodeBuddy permission/network layering, Codex structured deny reasons, and CodeBuddy fixed channel-media allowlists</td><td>Permission answers who may request a resource; transport policy answers which peer receives the connection and credentials.</td></tr>
<tr><td class="partial">Modified</td><td>Hermes process-wide <code>allow_private_urls</code></td><td>Replaced by an exact consumer plus normalized origin or canonical private/local CIDR; metadata and link-local targets remain non-exceptable.</td></tr>
<tr><td class="partial">Modified</td><td>OpenClaw browser interception and Codex whole-process egress proxy</td><td>Browser controls remain a separate gate; a policy proxy is optional, owner-declared, separately peer constrained, visible in doctor output, and has no direct fallback.</td></tr>
<tr><td class="no">Rejected</td><td>URL-string-only checks, one DNS preflight, implicit redirects, environment proxy inheritance, TLS verification disablement, or raw fallback</td><td>Each leaves a target, rebinding, credential, or bypass path.</td></tr>
<tr><td class="no">Rejected</td><td>User confirmation or hostname allow/deny as target enforcement</td><td>Neither validates every resolved address nor constrains the connected peer.</td></tr>
<tr><td class="no">Rejected</td><td>Applying a public-only rule to every HTTP client</td><td>This would break explicitly configured local model endpoints, MCP servers, and intranet services.</td></tr>
<tr><td class="no">Rejected</td><td>Counting Origin/Host, CORS, owner authentication, browser checks, or sandbox networking as Runtime SSRF completion</td><td>Those controls protect different directions or execution boundaries.</td></tr>
</table></div>
<section class="band plan" id="implementation"><span class="part">Part III · Plan</span><div><b>OpenProgram plan status and future work</b>
<p>The Runtime URL-fetch implementation is complete through Task 8. This section records that implementation evidence first,
then lists separate future boundaries. The matrix remains <code>◐</code> because those separate boundaries are excluded.</p></div></section>
<h2><span class="num">05</span>Completed plan: implementation evidence</h2>
<div class="flow">
<div class="box"><h3>Registry-keyed caller</h3><div class="small">42 immutable consumers<br>four trust classes<br>exact configured or callback origin</div></div>
<div class="arrow">›</div>
<div class="box"><h3>Pure policy decision</h3><div class="small">normalized URL and origin<br>one complete DNS answer set<br>exact exception and reason code</div></div>
<div class="arrow">›</div>
<div class="box"><h3>Managed transport</h3><div class="small">approved IP peer<br>original Host, SNI, and certificate<br>manual redirect and bounded response</div></div>
</div>
<h3>05.1 Transport and policy behavior</h3>
<ul>
<li>Public requests allow only registry-declared HTTP methods, schemes, and ports; all resolved addresses must be global, with explicit rejection for metadata, loopback, private, link-local, CGNAT, multicast, reserved, unspecified, documentation/test, mapped, ambiguous, and malformed targets.</li>
<li>Sync and async <code>httpcore</code> backends dial only the approved IP tuple, verify the actual socket peer, and retain the normalized hostname for HTTP Host, TLS SNI, and certificate validation. Pool identity includes consumer, trust class, normalized origin, approved IPs, and proxy identity.</li>
<li>Redirects are manual and each hop receives a new policy decision. Cross-origin configured-service redirects fail; public credentials are stripped; URL userinfo is rejected; logs and public errors retain no query, fragment, token path, cookie, or peer-controlled body.</li>
<li>Headers, MIME, content encoding, decoded bytes, connect/read/write/pool/overall timeout, and temporary-file lifecycle are bounded. Downloads replace the destination only after full validation, flush, <code>fsync</code>, and cleanup-safe completion.</li>
</ul>
<h3>05.2 Consumer and SDK disposition evidence</h3>
<div class="tbl"><table>
<tr><th>Disposition</th><th>Consumers</th><th>Enforcement</th></tr>
<tr><td>Injected transport</td><td><code>provider.openai.sdk</code>, <code>provider.anthropic.sdk</code>, <code>provider.google.sdk</code>, <code>mcp.configured.http</code>, <code>mcp.configured.sse</code></td><td>Public SDK construction receives a scoped managed client or factory; real SDK-chain tests reach the constrained backend.</td></tr>
<tr><td>Exact origin</td><td>Telegram, WeChat, Feishu, Matrix, Slack, Discord, fixed/configured TTS, and other fixed/configured REST consumers</td><td>The normalized owner or shipped origin is frozen before credentials are attached; redirects cannot move credentials to another origin.</td></tr>
<tr><td>Derived URL extraction</td><td>Attachment, generated-asset, and image-result consumers</td><td>The SDK or upstream response yields a URL, then Runtime performs the download or upload through a dedicated managed registry consumer.</td></tr>
<tr><td>Disabled</td><td><code>provider.amazon_bedrock.sdk</code>, <code>channel.slack.gateway_sdk</code>, <code>channel.discord.gateway_sdk</code>, <code>tts.edge_sdk</code></td><td>Startup or invocation fails with <code>UNMANAGED_TRANSPORT</code> before importing or using the uninjectable network SDK. Bedrock covers both the registered stream and model-list entry before boto3/botocore credential or client activity.</td></tr>
</table></div>
<h3>05.3 Owner exceptions, policy proxy, doctor, and inventory</h3>
<p>Owner configuration accepts only a registered consumer plus exactly one normalized origin or canonical private/local CIDR.
It rejects wildcards, suffixes, credentials, unknown fields, public/default-route networks, metadata, link-local ranges, and
exception forms not allowed by the consumer. Existing owner-authenticated settings paths remain the only mutation authority.</p>
<p>A policy proxy is usable only when owner configuration sets <code>enforces_target_policy: true</code>. Runtime evaluates the
target before proxy use, constrains the proxy peer separately, reports delegation through doctor/audit state, and never retries direct.</p>
<div class="tbl"><table>
<tr><th>Inventory exclusion</th><th>Owner and narrow reason</th></tr>
<tr><td><code>security/safe_http.py</code></td><td>Runtime managed transport; the only allowed direct <code>httpcore</code> pool/proxy construction</td></tr>
<tr><td><code>programs/functions/vanilla/browser/_chrome_bootstrap.py</code></td><td>Browser control; exact browser opener construction and loopback CDP liveness dial</td></tr>
<tr><td><code>cli/commands/mcp.py</code></td><td>Owner control plane; authenticated backend opener only</td></tr>
<tr><td><code>cli/ink.py</code>, <code>cli/commands/doctor.py</code>, <code>cli/commands/rescue.py</code></td><td>Owner control plane; exact loopback worker liveness socket only</td></tr>
</table></div>
<p>The checker fails for an unregistered raw call, active unmanaged SDK transport, registry entry without a classified consumer,
or stale exclusion. Doctor exposes stable <code>runtime-http-registry</code>, <code>runtime-http-owner-exceptions</code>,
<code>runtime-http-policy-proxy</code>, <code>runtime-http-recent-denials</code>, and <code>runtime-http-unmanaged-transport</code> labels.</p>
<h3>05.4 Verification snapshot</h3>
<div class="tbl"><table>
<tr><th>Command</th><th>Recorded result</th></tr>
<tr><td><code>uv run --extra dev pytest -q tests/security</code></td><td class="yes"><code>804 passed</code></td></tr>
<tr><td><code>uv run --with pip --with boto3 pytest -q tests/meta_functions tests/providers tests/unit tests/webui tests/integration/programs/test_mcp_client.py</code></td><td class="yes"><code>3482 passed, 12 skipped, 1 xfailed</code></td></tr>
<tr><td><code>uv run --extra dev --with boto3 pytest -q</code></td><td class="yes"><code>4923 passed, 14 skipped, 2 deselected, 1 xfailed</code></td></tr>
<tr><td><code>uv run python scripts/check_runtime_http.py</code></td><td class="yes"><code>unregistered=0 active_unmanaged=0 registry_without_consumer=0 stale_exclusions=0</code></td></tr>
<tr><td><code>uv run python scripts/check_feature_matrix.py docs/reference/design/feature-matrix.html</code></td><td class="yes"><code>features=160 openprogram_score=78 openprogram_gaps=73 openprogram_only=6</code></td></tr>
</table></div>
<div class="note"><b>Publication gate.</b> Policy parsing/address tests, real sync/async socket and TLS peer tests,
DNS-rebinding prevention, redirect and credential-origin tests, response/decompression/timeout cleanup, all-consumer migration,
four-way SDK classification with zero active unmanaged transports, owner-only exact exceptions, doctor/audit/static enforcement,
and the 42-row compatibility contract are present. The complete repository command passes with the declared dev and optional
provider dependencies. The feature matrix records <code>◐</code> because the verified scope is Runtime-owned HTTP rather than the
separate browser, arbitrary-code, plugin, external-CLI, and package-manager boundaries.</div>
<h2 id="future"><span class="num">06</span>OpenProgram future plan</h2>
<div class="tbl"><table>
<tr><th>Future boundary</th><th>Required work before claiming completion</th></tr>
<tr><td>Browser navigation and page-derived traffic</td><td>Define and test navigation, popup, Service Worker, background resource, redirect, download, CDP, and browser-profile policy across every browser backend; use an enforcing egress boundary where browser interception is insufficient.</td></tr>
<tr><td>Plugin and arbitrary-code networking</td><td>Keep the trust and sandbox model separate from Runtime safe HTTP; add an OS or policy-proxy egress boundary if these processes need restricted network access.</td></tr>
<tr><td>Disabled third-party SDK network features</td><td>Enable only after the SDK supports managed transport injection or an owner-configured enforcing policy proxy has equivalent tests. Do not replace the disabled disposition with an unverified SDK guarantee.</td></tr>
</table></div>
<p class="small">Related documents: <a href="sandbox-architecture.html">Sandbox design</a>,
<a href="../providers/network-proxy.html">network proxy design</a>, and
<a href="../feature-matrix.html">feature matrix</a>.</p>
</main></body></html>