{"id":369,"date":"2026-04-13T00:00:00","date_gmt":"2026-04-13T00:00:00","guid":{"rendered":"https:\/\/wordpress.securinsight.ca\/index.php\/2026\/04\/13\/containers-agents-secure-credential-injection-and-dynamic-egress-policies-for-sandboxes\/"},"modified":"2026-04-13T00:00:00","modified_gmt":"2026-04-13T00:00:00","slug":"containers-agents-secure-credential-injection-and-dynamic-egress-policies-for-sandboxes","status":"publish","type":"post","link":"https:\/\/wordpress.securinsight.ca\/index.php\/2026\/04\/13\/containers-agents-secure-credential-injection-and-dynamic-egress-policies-for-sandboxes\/","title":{"rendered":"Containers, Agents &#8211; Secure credential injection and dynamic egress policies for Sandboxes"},"content":{"rendered":"<p>Outbound Workers for <a href=\"https:\/\/developers.cloudflare.com\/sandbox\/\">Sandboxes<\/a> and <a href=\"https:\/\/developers.cloudflare.com\/containers\/\">Containers<\/a> now support zero-trust credential injection, TLS interception, allow\/deny lists, and dynamic per-instance egress policies. These features give platforms running agentic workloads full control over what leaves the sandbox, without exposing secrets to untrusted workloads, like user-generated code or coding agents.<\/p>\n<h4>Credential injection<\/h4>\n<p>Because outbound handlers run in the Workers runtime, outside the sandbox, they can hold secrets the sandbox never sees. A sandboxed workload can make a plain request, and credentials are transparently attached before a request is forwarded upstream.<\/p>\n<p>For instance, you could run an agent in a sandbox and ensure that any requests it makes to Github are authenticated.<br \/>\nBut it will never be able to accesss the credentials:<\/p>\n<div>\n<figure>\n<pre data-language=\"ts\"><code class=\"language-ts\"><div><div><span>export<\/span><span> <\/span><span>class<\/span><span> <\/span><span>MySandbox<\/span><span> <\/span><span>extends<\/span><span> <\/span><span>Sandbox<\/span><span> <\/span><span>{}<\/span><\/div><\/div><div><div>\n<\/div><\/div><div><div><span>MySandbox<\/span><span>.<\/span><span>outboundByHost<\/span><span> <\/span><span>=<\/span><span> <\/span><span>{<\/span><\/div><\/div><div><div><span>  <\/span><span>\"github.com\"<\/span><span>:<\/span><span> <\/span><span>(<\/span><span>request<\/span><span>:<\/span><span> <\/span><span>Request<\/span><span>,<\/span><span> <\/span><span>env<\/span><span>:<\/span><span> <\/span><span>Env<\/span><span>,<\/span><span> <\/span><span>ctx<\/span><span>:<\/span><span> <\/span><span>OutboundHandlerContext<\/span><span>)<\/span><span> <\/span><span>=&gt;<\/span><span> <\/span><span>{<\/span><\/div><\/div><div><div><span>    <\/span><span>const<\/span><span> <\/span><span>requestWithAuth<\/span><span> <\/span><span>=<\/span><span> <\/span><span>new<\/span><span> <\/span><span>Request<\/span><span>(<\/span><span>request<\/span><span>)<\/span><span>;<\/span><\/div><\/div><div><div><span><span>    <\/span><\/span><span>requestWithAuth<\/span><span>.<\/span><span>headers<\/span><span>.<\/span><span>set<\/span><span>(<\/span><span>\"x-auth-token\"<\/span><span>,<\/span><span> <\/span><span>env<\/span><span>.<\/span><span>SECRET<\/span><span>)<\/span><span>;<\/span><\/div><\/div><div><div><span>    <\/span><span>return<\/span><span> <\/span><span>fetch<\/span><span>(<\/span><span>requestWithAuth<\/span><span>)<\/span><span>;<\/span><\/div><\/div><div><div><span>  <\/span><span>},<\/span><\/div><\/div><div><div><span>};<\/span><\/div><\/div><\/code><\/pre>\n<div>\n<div><\/div>\n<\/div>\n<\/figure>\n<\/div>\n<p>You can easily inject unique credentials for different instances<br \/>\nby using <code>ctx.containerId<\/code>:<\/p>\n<div>\n<figure>\n<pre data-language=\"ts\"><code class=\"language-ts\"><div><div><span>MySandbox<\/span><span>.<\/span><span>outboundByHost<\/span><span> <\/span><span>=<\/span><span> <\/span><span>{<\/span><\/div><\/div><div><div><span>  <\/span><span>\"my-internal-vcs.dev\"<\/span><span>:<\/span><span> <\/span><span>async<\/span><span> (<\/span><\/div><\/div><div><div><span>    <\/span><span>request<\/span><span>:<\/span><span> <\/span><span>Request<\/span><span>,<\/span><\/div><\/div><div><div><span>    <\/span><span>env<\/span><span>:<\/span><span> <\/span><span>Env<\/span><span>,<\/span><\/div><\/div><div><div><span>    <\/span><span>ctx<\/span><span>:<\/span><span> <\/span><span>OutboundHandlerContext<\/span><span>,<\/span><\/div><\/div><div><div><span><span>  <\/span><\/span><span>) <\/span><span>=&gt;<\/span><span> <\/span><span>{<\/span><\/div><\/div><div><div><span>    <\/span><span>const<\/span><span> <\/span><span>authKey<\/span><span> <\/span><span>=<\/span><span> <\/span><span>await<\/span><span> <\/span><span>env<\/span><span>.<\/span><span>KEYS<\/span><span>.<\/span><span>get<\/span><span>(<\/span><span>ctx<\/span><span>.<\/span><span>containerId<\/span><span>)<\/span><span>;<\/span><\/div><\/div><div><div>\n<\/div><\/div><div><div><span>    <\/span><span>const<\/span><span> <\/span><span>requestWithAuth<\/span><span> <\/span><span>=<\/span><span> <\/span><span>new<\/span><span> <\/span><span>Request<\/span><span>(<\/span><span>request<\/span><span>)<\/span><span>;<\/span><\/div><\/div><div><div><span><span>    <\/span><\/span><span>requestWithAuth<\/span><span>.<\/span><span>headers<\/span><span>.<\/span><span>set<\/span><span>(<\/span><span>\"x-auth-token\"<\/span><span>,<\/span><span> <\/span><span>authKey<\/span><span>)<\/span><span>;<\/span><\/div><\/div><div><div><span>    <\/span><span>return<\/span><span> <\/span><span>fetch<\/span><span>(<\/span><span>requestWithAuth<\/span><span>)<\/span><span>;<\/span><\/div><\/div><div><div><span>  <\/span><span>},<\/span><\/div><\/div><div><div><span>};<\/span><\/div><\/div><\/code><\/pre>\n<div>\n<div><\/div>\n<\/div>\n<div><\/div>\n<\/figure>\n<\/div>\n<p>No token is ever passed into the sandbox. You can rotate secrets in the Worker environment<br \/>\nand every request will pick them up immediately.<\/p>\n<h4>TLS interception<\/h4>\n<p>Outbound Workers now intercept HTTPS traffic. A unique ephemeral certificate authority (CA) and private key are created for each sandbox instance. The CA is placed into the sandbox and trusted by default. The ephemeral private key never leaves the container runtime sidecar process and is never shared across instances.<\/p>\n<p>With TLS interception active, outbound Workers can act as a transparent proxy for both HTTP and HTTPS traffic.<\/p>\n<h4>Allow and deny hosts<\/h4>\n<p>Easily filter outbound traffic with <code>allowedHosts<\/code> and <code>deniedHosts<\/code>. When <code>allowedHosts<\/code> is set, it becomes a deny-by-default allowlist. Both properties support glob patterns.<\/p>\n<div>\n<figure>\n<pre data-language=\"ts\"><code class=\"language-ts\"><div><div><span>export<\/span><span> <\/span><span>class<\/span><span> <\/span><span>MySandbox<\/span><span> <\/span><span>extends<\/span><span> <\/span><span>Sandbox<\/span><span> <\/span><span>{<\/span><\/div><\/div><div><div><span><span>  <\/span><\/span><span>allowedHosts <\/span><span>=<\/span><span> [<\/span><span>\"github.com\"<\/span><span>,<\/span><span> <\/span><span>\"npmjs.org\"<\/span><span>]<\/span><span>;<\/span><\/div><\/div><div><div><span>}<\/span><\/div><\/div><\/code><\/pre>\n<div>\n<div><\/div>\n<\/div>\n<\/figure>\n<\/div>\n<h4>Dynamic outbound handlers<\/h4>\n<p>Define named outbound handlers then apply or remove them at runtime using <code>setOutboundHandler()<\/code> or <code>setOutboundByHost()<\/code>. This lets you change egress policy for a running sandbox without restarting it.<\/p>\n<div>\n<figure>\n<pre data-language=\"ts\"><code class=\"language-ts\"><div><div><span>export<\/span><span> <\/span><span>class<\/span><span> <\/span><span>MySandbox<\/span><span> <\/span><span>extends<\/span><span> <\/span><span>Sandbox<\/span><span> <\/span><span>{}<\/span><\/div><\/div><div><div>\n<\/div><\/div><div><div><span>MySandbox<\/span><span>.<\/span><span>outboundHandlers<\/span><span> <\/span><span>=<\/span><span> <\/span><span>{<\/span><\/div><\/div><div><div><span>  <\/span><span>allowHosts<\/span><span>:<\/span><span> <\/span><span>async<\/span><span> <\/span><span>(<\/span><span>req<\/span><span>:<\/span><span> <\/span><span>Request<\/span><span>,<\/span><span> <\/span><span>env<\/span><span>:<\/span><span> <\/span><span>Env<\/span><span>,<\/span><span> <\/span><span>ctx<\/span><span>:<\/span><span> <\/span><span>OutboundHandlerContext<\/span><span><span> <\/span><span>)<\/span><\/span><span> <\/span><span>=&gt;<\/span><span> <\/span><span>{<\/span><\/div><\/div><div><div><span>    <\/span><span>const<\/span><span> <\/span><span>url<\/span><span> <\/span><span>=<\/span><span> <\/span><span>new<\/span><span> <\/span><span>URL<\/span><span>(<\/span><span>req<\/span><span>.<\/span><span>url<\/span><span>)<\/span><span>;<\/span><\/div><\/div><div><div><span>    <\/span><span>if<\/span><span> (<\/span><span>ctx<\/span><span>.<\/span><span>params<\/span><span>.<\/span><span>allowedHostnames<\/span><span>.<\/span><span>includes<\/span><span>(<\/span><span>url<\/span><span>.<\/span><span>hostname<\/span><span>)) <\/span><span>{<\/span><\/div><\/div><div><div><span>      <\/span><span>return<\/span><span> <\/span><span>fetch<\/span><span>(<\/span><span>req<\/span><span>)<\/span><span>;<\/span><\/div><\/div><div><div><span>    <\/span><span>}<\/span><\/div><\/div><div><div><span>    <\/span><span>return<\/span><span> <\/span><span>new<\/span><span> <\/span><span>Response<\/span><span>(<\/span><span>null<\/span><span>,<\/span><span> <\/span><span>{<\/span><span> status<\/span><span>:<\/span><span> <\/span><span>403<\/span><span> <\/span><span>}<\/span><span>)<\/span><span>;<\/span><\/div><\/div><div><div><span>  <\/span><span>},<\/span><\/div><\/div><div><div>\n<\/div><\/div><div><div><span>  <\/span><span>noHttp<\/span><span>:<\/span><span> <\/span><span>async<\/span><span> <\/span><span>()<\/span><span> <\/span><span>=&gt;<\/span><span> <\/span><span>{<\/span><\/div><\/div><div><div><span>    <\/span><span>return<\/span><span> <\/span><span>new<\/span><span> <\/span><span>Response<\/span><span>(<\/span><span>null<\/span><span>,<\/span><span> <\/span><span>{<\/span><span> status<\/span><span>:<\/span><span> <\/span><span>403<\/span><span> <\/span><span>}<\/span><span>)<\/span><span>;<\/span><\/div><\/div><div><div><span>  <\/span><span>},<\/span><\/div><\/div><div><div><span>};<\/span><\/div><\/div><\/code><\/pre>\n<div>\n<div><\/div>\n<\/div>\n<div><\/div>\n<\/figure>\n<\/div>\n<p>Apply handlers programmatically from your Worker:<\/p>\n<div>\n<figure>\n<pre data-language=\"ts\"><code class=\"language-ts\"><div><div><span>const<\/span><span> <\/span><span>sandbox<\/span><span> <\/span><span>=<\/span><span> <\/span><span>getSandbox<\/span><span>(<\/span><span>env<\/span><span>.<\/span><span>Sandbox<\/span><span>,<\/span><span> <\/span><span>userId<\/span><span>)<\/span><span>;<\/span><\/div><\/div><div><div>\n<\/div><\/div><div><div><span>\/\/ Open network for setup<\/span><\/div><\/div><div><div><span>await<\/span><span> <\/span><span>sandbox<\/span><span>.<\/span><span>setOutboundHandler<\/span><span>(<\/span><span>\"allowHosts\"<\/span><span>,<\/span><span> <\/span><span>{<\/span><\/div><\/div><div><div><span><span>  <\/span><\/span><span>allowedHostnames<\/span><span>:<\/span><span> [<\/span><span>\"github.com\"<\/span><span>,<\/span><span> <\/span><span>\"npmjs.org\"<\/span><span>]<\/span><span>,<\/span><\/div><\/div><div><div><span>}<\/span><span>)<\/span><span>;<\/span><\/div><\/div><div><div><span>await<\/span><span> <\/span><span>sandbox<\/span><span>.<\/span><span>exec<\/span><span>(<\/span><span>\"npm install\"<\/span><span>)<\/span><span>;<\/span><\/div><\/div><div><div>\n<\/div><\/div><div><div><span>\/\/ Lock down after setup<\/span><\/div><\/div><div><div><span>await<\/span><span> <\/span><span>sandbox<\/span><span>.<\/span><span>setOutboundHandler<\/span><span>(<\/span><span>\"noHttp\"<\/span><span>)<\/span><span>;<\/span><\/div><\/div><\/code><\/pre>\n<div>\n<div><\/div>\n<\/div>\n<div><\/div>\n<\/figure>\n<\/div>\n<p>Handlers accept <code>params<\/code>, so you can customize behavior per instance without defining separate handler functions.<\/p>\n<h4>Get started<\/h4>\n<p>Upgrade to <code>@cloudflare\/containers@0.3.0<\/code> or <code>@cloudflare\/sandbox@0.8.9<\/code> to use these features.<\/p>\n<p>For more details, refer to <a href=\"https:\/\/developers.cloudflare.com\/sandbox\/guides\/outbound-traffic\/\">Sandbox outbound traffic<\/a> and <a href=\"https:\/\/developers.cloudflare.com\/containers\/platform-details\/outbound-traffic\/\">Container outbound traffic<\/a>.<\/p>","protected":false},"excerpt":{"rendered":"<p>Outbound Workers for Sandboxes and Containers now support zero-trust credential injection, TLS interception, allow\/deny lists, and dynamic per-instance egress policies. These features give platforms running agentic workloads full control over what leaves the sandbox, without exposing secrets to untrusted workloads, like user-generated code or coding agents. Credential injection Because outbound handlers run in the Workers [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-369","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/wordpress.securinsight.ca\/index.php\/wp-json\/wp\/v2\/posts\/369","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.securinsight.ca\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wordpress.securinsight.ca\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.securinsight.ca\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.securinsight.ca\/index.php\/wp-json\/wp\/v2\/comments?post=369"}],"version-history":[{"count":0,"href":"https:\/\/wordpress.securinsight.ca\/index.php\/wp-json\/wp\/v2\/posts\/369\/revisions"}],"wp:attachment":[{"href":"https:\/\/wordpress.securinsight.ca\/index.php\/wp-json\/wp\/v2\/media?parent=369"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wordpress.securinsight.ca\/index.php\/wp-json\/wp\/v2\/categories?post=369"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wordpress.securinsight.ca\/index.php\/wp-json\/wp\/v2\/tags?post=369"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}