From 397bc99032f3dab2b2d71518594175dc9577de6e Mon Sep 17 00:00:00 2001 From: David Gageot Date: Tue, 9 Jun 2026 19:52:55 +0200 Subject: [PATCH 1/2] Allow models.dev in sandbox proxy for catalog metadata resolution --- cmd/root/sandbox.go | 27 ++++++++++++++++++++------- cmd/root/sandbox_test.go | 8 ++++++++ pkg/modelsdev/store.go | 3 +++ 3 files changed, 31 insertions(+), 7 deletions(-) diff --git a/cmd/root/sandbox.go b/cmd/root/sandbox.go index 592003bc5..a4d5a5252 100644 --- a/cmd/root/sandbox.go +++ b/cmd/root/sandbox.go @@ -20,6 +20,7 @@ import ( "github.com/docker/docker-agent/pkg/config" latestcfg "github.com/docker/docker-agent/pkg/config/latest" "github.com/docker/docker-agent/pkg/environment" + "github.com/docker/docker-agent/pkg/modelsdev" "github.com/docker/docker-agent/pkg/paths" "github.com/docker/docker-agent/pkg/sandbox" "github.com/docker/docker-agent/pkg/sandbox/kit" @@ -175,6 +176,7 @@ func runInSandbox(ctx context.Context, cmd *cobra.Command, args []string, runCon userHosts := userSandboxAllowlist(ctx) printModelsGateway(cmd.OutOrStdout(), runConfig.ModelsGateway) + printModelsDevAllowance(cmd.OutOrStdout()) printToolInstallAllowance(cmd.OutOrStdout(), kitResult) printAgentNetworkAllowlist(cmd.OutOrStdout(), agentHosts) printUserSandboxAllowlist(cmd.OutOrStdout(), userHosts) @@ -272,15 +274,18 @@ func dockerAgentArgs(cmd *cobra.Command, args []string, configDir string) []stri } // allowSandboxHosts adds per-sandbox allow-network rules for every -// host the in-sandbox runtime is known to need: the configured -// models gateway (when set), the package hosts the auto-installer -// reaches for (when the kit build identified at least one -// auto-installable toolset), and any extra hosts the agent author -// declared in runtime.network_allowlist. The default sandbox proxy -// denies all of them; without this, the inner agent's first request -// returns a misleading "403 Blocked by network policy". +// host the in-sandbox runtime is known to need: the models.dev +// catalog API (always), the configured models gateway (when set), the +// package hosts the auto-installer reaches for (when the kit build +// identified at least one auto-installable toolset), and any extra +// hosts the agent author declared in runtime.network_allowlist. The +// default sandbox proxy denies all of them; without this, the inner +// agent's first request returns a misleading "403 Blocked by network +// policy". // // Holes are punched only when the corresponding feature is in play: +// - models.dev is always opened — every run resolves model +// metadata (limits, pricing, capabilities) against the catalog; // - the gateway host is added only when gatewayURL is non-empty; // - the per-agent install hosts come from the kit build, which // looks each toolset up against the aqua registry and contributes @@ -300,6 +305,7 @@ func dockerAgentArgs(cmd *cobra.Command, args []string, configDir string) []stri // inner and we surface that diagnostic verbatim. func allowSandboxHosts(ctx context.Context, backend *sandbox.Backend, name, gatewayURL string, toolInstallHosts, agentHosts, userHosts []string) { var hosts []string + hosts = append(hosts, modelsdev.APIHost) hosts = append(hosts, toolInstallHosts...) hosts = append(hosts, agentHosts...) hosts = append(hosts, userHosts...) @@ -480,6 +486,13 @@ func printModelsGateway(w io.Writer, gateway string) { fmt.Fprintf(w, "Models gateway: %s (allowlisting %s in the sandbox proxy)\n", display, host) } +// printModelsDevAllowance prints that the models.dev catalog host is +// always allowlisted in the sandbox proxy, since every run resolves +// model metadata against it. +func printModelsDevAllowance(w io.Writer) { + fmt.Fprintf(w, "Models catalog: allowlisting %s in the sandbox proxy\n", modelsdev.APIHost) +} + // printToolInstallAllowance prints a multi-line description of the // package-host allowlist opened for this sandbox: a one-liner // summary followed by every host on its own indented line so the diff --git a/cmd/root/sandbox_test.go b/cmd/root/sandbox_test.go index 9ead6b2a8..a5c184eb2 100644 --- a/cmd/root/sandbox_test.go +++ b/cmd/root/sandbox_test.go @@ -194,6 +194,14 @@ func TestPrintModelsGateway(t *testing.T) { } } +func TestPrintModelsDevAllowance(t *testing.T) { + t.Parallel() + + var buf strings.Builder + printModelsDevAllowance(&buf) + assert.Equal(t, "Models catalog: allowlisting models.dev in the sandbox proxy\n", buf.String()) +} + func TestPrintToolInstallAllowance(t *testing.T) { t.Parallel() diff --git a/pkg/modelsdev/store.go b/pkg/modelsdev/store.go index 1c7438829..1934f42d9 100644 --- a/pkg/modelsdev/store.go +++ b/pkg/modelsdev/store.go @@ -19,6 +19,9 @@ import ( const ( ModelsDevAPIURL = "https://models.dev/api.json" + // APIHost is the host portion of ModelsDevAPIURL, allowlisted by + // sandbox callers so the in-sandbox agent can reach the catalog. + APIHost = "models.dev" CacheFileName = "models_dev.json" refreshInterval = 24 * time.Hour ) From 6d7fd025b2552748fd09f45e6b6a841869d512db Mon Sep 17 00:00:00 2001 From: David Gageot Date: Tue, 9 Jun 2026 19:54:54 +0200 Subject: [PATCH 2/2] refactor: derive ModelsDevAPIURL from APIHost to prevent drift --- pkg/modelsdev/store.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/pkg/modelsdev/store.go b/pkg/modelsdev/store.go index 1934f42d9..8787e5bf8 100644 --- a/pkg/modelsdev/store.go +++ b/pkg/modelsdev/store.go @@ -18,10 +18,12 @@ import ( ) const ( - ModelsDevAPIURL = "https://models.dev/api.json" - // APIHost is the host portion of ModelsDevAPIURL, allowlisted by - // sandbox callers so the in-sandbox agent can reach the catalog. - APIHost = "models.dev" + // APIHost is the models.dev catalog host. Sandbox callers allowlist + // it so the in-sandbox agent can reach the catalog through the + // default-deny network proxy. + APIHost = "models.dev" + // ModelsDevAPIURL is derived from APIHost so the two can't drift. + ModelsDevAPIURL = "https://" + APIHost + "/api.json" CacheFileName = "models_dev.json" refreshInterval = 24 * time.Hour )