From 253b147a3908cf605e5d814322c09ec4cba6d738 Mon Sep 17 00:00:00 2001 From: Paul O'Reilly Date: Fri, 4 Sep 2026 13:03:07 +1200 Subject: [PATCH] =?UTF-8?q?fix(harness):=20cp-service-token/v1=20=E2=80=94?= =?UTF-8?q?=20restage=20ESO=20secret,=20fix=20unreadable-by-agent=20bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ESO-mounted secret is root-owned mode 0400 (correct — init.sh runs as root before the gosu drop to the agent user). The original version of this context pointed CP_SERVICE_TOKEN_FILE directly at that raw mount, which the agent process (uid 1000) can never read. Confirmed live 2026-09-03: a real scope-decompose-sonnet@1 dispatch against concept 7666d278-ae58-4f12-990d-c4959a3e19a9 hit exactly this — the agent correctly diagnosed 'cp_cli invocation can't proceed... token is root-owned mode 0400 so it's not readable by the agent user', wrote its decompose plan, but could never actually call cp-cli to create the child tasks. The trigger engine's new side-effect verification (finalize.py, bug 9dffc5b8) correctly caught this and refused to advance flow_state — so this was a visible, retriable failure rather than another silent false-positive. Fix: init.sh restages the secret to /run/agent/cp-service-token/token, mode 0600, owned by the agent user — mirrors anthropic-cloud-paul-oauth/v1/init.sh's existing pattern. CP_SERVICE_TOKEN_FILE now points at the restaged copy. --- .../contexts/cp-service-token/v1/harness.yaml | 19 ++++++--- .../contexts/cp-service-token/v1/init.sh | 39 +++++++++++++++++++ 2 files changed, 52 insertions(+), 6 deletions(-) create mode 100755 harnesses/contexts/cp-service-token/v1/init.sh diff --git a/harnesses/contexts/cp-service-token/v1/harness.yaml b/harnesses/contexts/cp-service-token/v1/harness.yaml index 4dfc374..116e115 100644 --- a/harnesses/contexts/cp-service-token/v1/harness.yaml +++ b/harnesses/contexts/cp-service-token/v1/harness.yaml @@ -5,16 +5,23 @@ description: "CP-internal service bearer token — authenticates agent-container requires: [] provides: [] -# AU-51b: static env pointing at the ESO-mounted secret file. No init.sh -# needed — the mount path is fixed at harness-authoring time (unlike -# anthropic-cloud-paul-oauth/v1, which transforms its secret into a -# different file format and therefore needs a staging script), and -# decompose_work_items_action reads CP_SERVICE_TOKEN_FILE directly. +# AU-51b: the ESO-mounted secret is root-owned mode 0400 (init.sh runs as +# root, before the gosu drop to the agent user, uid 1000) — unreadable by +# the agent process directly. Confirmed live 2026-09-03: a real agent +# session hit exactly this ("cp-cli invocation can't proceed... token is +# root-owned mode 0400 so it's not readable by the agent user"). Mirrors +# anthropic-cloud-paul-oauth/v1's pattern: init.sh restages a 0600 +# agent-owned copy outside the ESO mount. CP_SERVICE_TOKEN_FILE points at +# the restaged copy, not the raw mount. +# # The value at this path MUST match the CP's CP_INTERNAL_BEARER_TOKEN # (same account: cp-decompose-service-token, account_id # 1d963673-6ac9-4f85-875a-2ce5323e76ad, owner (cp, cp)). env: - CP_SERVICE_TOKEN_FILE: /run/agent/secrets/cp-service-token/value + CP_SERVICE_TOKEN_FILE: /run/agent/cp-service-token/token + +scripts: + init: "./init.sh" secrets_required: - name: cp-service-token diff --git a/harnesses/contexts/cp-service-token/v1/init.sh b/harnesses/contexts/cp-service-token/v1/init.sh new file mode 100755 index 0000000..238c69e --- /dev/null +++ b/harnesses/contexts/cp-service-token/v1/init.sh @@ -0,0 +1,39 @@ +#!/bin/bash +# cp-service-token init — restage the ESO-mounted secret to an agent-owned +# copy. +# +# Threat model: keep the ESO mount root-only (mode 0400) so the agent user +# cannot directly `cat` /run/agent/secrets/cp-service-token/*. init.sh runs +# as root (in uid-wrapper.sh, before the gosu drop) and writes a restaged +# copy at /run/agent/cp-service-token/token with mode 0600 owned by the +# agent user. This mirrors anthropic-cloud-paul-oauth/v1/init.sh's pattern. +# +# Bug discovered live 2026-09-03: without this restaging step, cp-cli +# (invoked by the agent user, uid 1000) could not read the raw 0400 +# root-owned mount at all — "cp_cli invocation can't proceed... token is +# root-owned mode 0400 so it's not readable by the agent user". The context +# originally set CP_SERVICE_TOKEN_FILE directly at the raw ESO mount path, +# which is the mistake this init.sh fixes. + +set -euo pipefail + +ESO_TOKEN="/run/agent/secrets/cp-service-token/value" + +if [ ! -r "$ESO_TOKEN" ]; then + echo "ERROR: $ESO_TOKEN not readable. Check ESO ExternalSecret acct-1d963673." >&2 + exit 1 +fi + +AGENT_USER="${AGENT_USER:-agent}" + +DEST_DIR="/run/agent/cp-service-token" +mkdir -p "$DEST_DIR" + +DEST_FILE="$DEST_DIR/token" +cp "$ESO_TOKEN" "$DEST_FILE" + +chown "$AGENT_USER:" "$DEST_DIR" "$DEST_FILE" 2>/dev/null || true +chmod 0700 "$DEST_DIR" +chmod 0600 "$DEST_FILE" + +echo "cp-service-token: restaged into $DEST_FILE (0600 $AGENT_USER:$AGENT_USER)"