Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions bin/git-credential-hive.sh
Original file line number Diff line number Diff line change
Expand Up @@ -154,9 +154,16 @@ case "${1:-}" in
if [ -n "$REQUEST_PROTOCOL" ] && [ "$REQUEST_PROTOCOL" != "https" ]; then
exit 0
fi
printf '{"ts":"%s","agent":"%s","uid":%d,"op":"git-credential","host":"%s"}\n' \
# The group wraps the append so a failed REDIRECTION is silenced too, the
# same shape gh-wrapper.sh uses (#4043): `>> f 2>/dev/null` only mutes the
# printf, and when the log cannot be opened by the agent UID β€” its
# directory is 0755 dev:node by design (#4044) and the file does not
# exist until the entrypoint pre-creates it β€” the shell's own
# "line N: .../token-access.jsonl: Permission denied" leaked into the
# agent's pane on every clone, fetch, and push.
{ printf '{"ts":"%s","agent":"%s","uid":%d,"op":"git-credential","host":"%s"}\n' \
"$(date -u +%Y-%m-%dT%H:%M:%SZ)" "${AGENT:-unknown}" "$(id -u)" "${REQUESTED_HOST:-unknown}" \
>> "$TOKEN_ACCESS_LOG" 2>/dev/null || true
>> "$TOKEN_ACCESS_LOG"; } 2>/dev/null || true
# Echo back the SAME host git asked about (github.com, github.ibm.com, or
# any other configured GitHub Enterprise host) rather than a hardcoded
# "github.com" β€” see the file header. entrypoint.sh only registers this
Expand Down
19 changes: 19 additions & 0 deletions bin/test_git_credential_hive.sh
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,25 @@ else
echo "PASS: push-capable mode has no read-only notice text"
fi

# ── the audit-log append must never leak into the agent's transcript ──
# The helper appends one line to /var/run/hive-metrics/token-access.jsonl on
# every `get`. On a per-UID hive that directory is 0755 dev:node by design
# (#4044) and the file is not pre-created, so the append's REDIRECTION fails.
# `>> f 2>/dev/null` only mutes the printf β€” the shell reports a failed
# redirection on its own stderr β€” so every clone/fetch/push showed
# "git-credential-hive.sh: line N: .../token-access.jsonl: Permission denied"
# in the agent's pane. The harness has no /var/run/hive-metrics either, so the
# same redirection fails here and this assertion reproduces the leak exactly.
LEAK_OUT="$(run_helper CONTRIBUTOR 4 "$TOKEN_CACHE" "$GET_STDIN" -- get | tail -n +2)"
if [[ "$LEAK_OUT" == *"token-access.jsonl"* ]] || [[ "$LEAK_OUT" == *"Permission denied"* ]] || [[ "$LEAK_OUT" == *"No such file"* ]]; then
FAIL=$((FAIL + 1))
echo "FAIL: audit-log append failure leaked into helper output"
echo " got: $LEAK_OUT"
else
PASS=$((PASS + 1))
echo "PASS: audit-log append failure is silent (no token-access.jsonl noise)"
fi

# ── refusals that MUST stay fail-closed (audit H3) ──
assert "missing per-agent token file refuses loudly (H3: no shared-cache fallback)" \
"$(run_helper ADVISORY 2 "${WORK}/no-such-token" "$GET_STDIN" -- get)" \
Expand Down
1 change: 1 addition & 0 deletions changelog.d/fixed-credential-helper-audit-log.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- Agents no longer see `git-credential-hive.sh: line N: /var/run/hive-metrics/token-access.jsonl: Permission denied` on every clone, fetch, and push. The credential helper appended to the token-access audit log with `>> f 2>/dev/null`, which only mutes the command, not a failed redirection β€” and the redirection always failed for per-UID agents because the metrics directory is deliberately not agent-writable and the log file was never created. The helper now wraps the append the way `gh-wrapper.sh` already does (#4043) so a failure is silent, and the entrypoint pre-creates the log as `dev:node` mode 0664 so the appends from both writers actually land and `GET /api/token-access` stops reporting an empty audit log on per-UID hives.
12 changes: 12 additions & 0 deletions src/deploy/entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -708,6 +708,18 @@ if [ "$(id -u)" = "0" ]; then
# group-writable mode would let any agent swap that file and spoof the
# identity the gate validates against. Re-asserted on every boot.
chmod 755 /var/run/hive-metrics/agent-tokens 2>/dev/null || true
# The token-access audit log (GET /api/token-access) is APPENDED by the
# per-UID agent processes β€” gh-wrapper.sh on every gh call and
# git-credential-hive.sh on every credential lookup β€” but the directory
# above is deliberately not agent-writable, so an agent can never create
# the file and every append failed silently: the audit endpoint on a
# per-UID hive stayed empty forever. Pre-create it here, owned by dev with
# group "node" (every agent UID) writable, so the appends land. The
# directory itself stays 0755: only this one file opens up, the
# bot-identity file the gh-wrapper author gate trusts is untouched.
touch /var/run/hive-metrics/token-access.jsonl 2>/dev/null || true
chown dev:node /var/run/hive-metrics/token-access.jsonl 2>/dev/null || true
chmod 664 /var/run/hive-metrics/token-access.jsonl 2>/dev/null || true

# Fix permissions on bind-mounted secret files (host may own them as
# a different UID with mode 600, making them unreadable by dev/UID 1001)
Expand Down
Loading