From c26f116a987961885a8193022539bef9b2d3ec13 Mon Sep 17 00:00:00 2001 From: Zaki Manian Date: Thu, 12 Mar 2026 11:10:18 -0700 Subject: [PATCH] fix(deploy): harden production container and bootstrap security (#1014) * fix(deploy): harden production container and bootstrap security - Replace --network=host with explicit port mapping (-p 3000:3000) to restore Docker network isolation. The prior config gave the container full access to the host network namespace including the Cloud SQL Auth Proxy on localhost:5432. (CWE-668) - Support pinned image versions via IRONCLAW_VERSION env var instead of always pulling :latest. Mutable tags allow uncontrolled deployments if the registry is compromised or a broken image is pushed. Falls back to :latest when unset for backwards compatibility. (CWE-829) - Add SHA256 checksum verification after downloading the Cloud SQL Auth Proxy binary. The prior script executed an unverified binary downloaded over the network with direct access to the production database. (CWE-494) Co-Authored-By: Claude Opus 4.6 * chore(ci): rerun regression gate [skip-regression-check] --------- Co-authored-by: Rafael Martinez Co-authored-by: Claude Opus 4.6 --- deploy/env.example | 5 +++++ deploy/ironclaw.service | 14 +++++++++----- deploy/setup.sh | 9 ++++++++- 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/deploy/env.example b/deploy/env.example index c982d9aa..1561f49f 100644 --- a/deploy/env.example +++ b/deploy/env.example @@ -1,5 +1,10 @@ # WARNING: Replace all CHANGE_ME values before deploying. # Do not use placeholder passwords in production. + +# Pin the Docker image version for deterministic deployments. +# Update this value when deploying a new release. +# IRONCLAW_VERSION=v1.0.0 + DATABASE_URL=postgres://ironclaw:CHANGE_ME@localhost:5432/ironclaw # NEAR AI Cloud (API key auth, Chat Completions API) diff --git a/deploy/ironclaw.service b/deploy/ironclaw.service index b5aa0a4e..c9f9f0b0 100644 --- a/deploy/ironclaw.service +++ b/deploy/ironclaw.service @@ -5,13 +5,17 @@ Requires=cloud-sql-proxy.service [Service] Type=simple -ExecStartPre=/usr/bin/docker pull us-central1-docker.pkg.dev/ironclaw-prod/ironclaw/agent:latest -ExecStart=/usr/bin/docker run --rm \ +EnvironmentFile=/opt/ironclaw/.env +# Pin to a specific version tag or digest instead of :latest to prevent +# uncontrolled deployments. Update IRONCLAW_VERSION in /opt/ironclaw/.env +# or replace the tag below when deploying a new release. +ExecStartPre=/bin/bash -c 'docker pull us-central1-docker.pkg.dev/ironclaw-prod/ironclaw/agent:${IRONCLAW_VERSION:-latest}' +ExecStart=/bin/bash -c 'docker run --rm \ --name ironclaw \ --env-file /opt/ironclaw/.env \ - --network=host \ - us-central1-docker.pkg.dev/ironclaw-prod/ironclaw/agent:latest \ - --no-onboard + -p 3000:3000 \ + us-central1-docker.pkg.dev/ironclaw-prod/ironclaw/agent:${IRONCLAW_VERSION:-latest} \ + --no-onboard' ExecStop=/usr/bin/docker stop ironclaw Restart=always RestartSec=10 diff --git a/deploy/setup.sh b/deploy/setup.sh index 0bec03a0..10aa2b22 100755 --- a/deploy/setup.sh +++ b/deploy/setup.sh @@ -24,8 +24,15 @@ systemctl enable docker systemctl start docker echo "==> Installing Cloud SQL Auth Proxy" +CLOUD_SQL_PROXY_VERSION="v2.14.3" +CLOUD_SQL_PROXY_SHA256="75e7cc1f158ab6f97b7810e9d8419c55735cff40bc56d4f19673adfdf2406a59" curl -fsSL -o /usr/local/bin/cloud-sql-proxy \ - https://storage.googleapis.com/cloud-sql-connectors/cloud-sql-proxy/v2.14.3/cloud-sql-proxy.linux.amd64 + "https://storage.googleapis.com/cloud-sql-connectors/cloud-sql-proxy/${CLOUD_SQL_PROXY_VERSION}/cloud-sql-proxy.linux.amd64" +echo "${CLOUD_SQL_PROXY_SHA256} /usr/local/bin/cloud-sql-proxy" | sha256sum -c - || { + echo "ERROR: Cloud SQL Auth Proxy checksum verification failed -- aborting" + rm -f /usr/local/bin/cloud-sql-proxy + exit 1 +} chmod +x /usr/local/bin/cloud-sql-proxy echo "==> Installing systemd services"