fix(git-tools): fail closed on unresolvable explicit --login override (#865)
Some checks failed
ci/woodpecker/pr/ci Pipeline failed

gitea_resolve_api_for_login silently fell back to the host-default identity
whenever the named login could not be resolved for ANY reason -- including when
the name came from an EXPLICIT --login override. A caller passing a dedicated
per-role credential could thus have its write attributed to the shared default
identity while being told it succeeded as requested.

Thread an "override was explicit" signal into gitea_resolve_api_for_login
(second param, "explicit" when LOGIN_OVERRIDE is non-empty). When the override
is explicit and that login's token cannot be resolved, FAIL CLOSED (return 1,
clear error naming the login, no host-default fallback). The best-effort
host-default fallback now applies ONLY on the no-override default path. Applied
symmetrically to issue-comment.sh and all three pr-review.sh dispatch sites
(approve / request-changes / comment).

Tests: both scripts' write flows now assert credential attribution via a
token->identity seam in the curl stub -- (a) resolvable --login override drives
the entire write/read-back chain under THAT login's token, nothing under the
default; (b) unresolvable --login override fails closed (nonzero, no success
line, no write, no default-identity request); (c) no-override default path still
succeeds under the host-default best-effort credential.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Hermes Agent
2026-07-21 20:07:00 -05:00
parent 9384f0bc0a
commit 6168f9ac86
4 changed files with 245 additions and 30 deletions

View File

@@ -85,17 +85,29 @@ detect_platform >/dev/null
# and read-back token are the same identity by construction (this is the
# credential-ordering fix: a --login override is no longer written under one
# credential and verified under a different default one). Falls back to the
# host-scoped credential only when the login has no token in tea's own config.
# Returns non-zero (clear stderr) on any resolution failure.
# host-scoped credential ONLY when NO --login override was supplied (the
# best-effort default path). When $2 is "explicit" the login came from a
# caller-supplied --login: that exact login's token MUST resolve, and we FAIL
# CLOSED rather than silently downgrading the write to the host default
# identity — otherwise a caller relying on a dedicated per-role credential would
# be told the write succeeded as requested while it was attributed to the shared
# default. Returns non-zero (clear stderr) on any resolution failure.
gitea_resolve_api_for_login() {
local effective_login="$1" host configured_url repo
local effective_login="$1" override_explicit="${2:-}" host configured_url repo
host=$(get_remote_host)
GITEA_API_TOKEN=$(get_gitea_token_for_login "$effective_login") \
|| GITEA_API_TOKEN=$(get_gitea_token "$host") || {
echo "Error: Gitea token not found for login '$effective_login' (comment write/read-back)" >&2
return 1
}
if [[ -n "$override_explicit" ]]; then
GITEA_API_TOKEN=$(get_gitea_token_for_login "$effective_login") || {
echo "Error: could not resolve a Gitea token for --login '$effective_login'; refusing to fall back to the host default identity (comment write/read-back)" >&2
return 1
}
else
GITEA_API_TOKEN=$(get_gitea_token_for_login "$effective_login") \
|| GITEA_API_TOKEN=$(get_gitea_token "$host") || {
echo "Error: Gitea token not found for login '$effective_login' (comment write/read-back)" >&2
return 1
}
fi
configured_url=$(get_gitea_url_for_host "$host") || {
echo "Error: Configured Gitea URL not found for comment read-back verification" >&2
return 1
@@ -379,8 +391,10 @@ elif [[ "$PLATFORM" == "gitea" ]]; then
# Bind the REST endpoint + token to the effective login, then derive the
# acting identity from that SAME credential (GET /user). The write below and
# its read-back both use this credential, so the write is verified against
# the identity that actually performed it.
gitea_resolve_api_for_login "$EFFECTIVE_LOGIN" || exit 1
# the identity that actually performed it. Passing "explicit" when --login
# was supplied forbids the host-default fallback: an unresolvable explicit
# override fails closed instead of writing under the default identity.
gitea_resolve_api_for_login "$EFFECTIVE_LOGIN" "${LOGIN_OVERRIDE:+explicit}" || exit 1
ACTING_LOGIN=$(gitea_authenticated_login) || exit 1
comment_id=$(gitea_create_comment_verified "$ISSUE_NUMBER" "$COMMENT" "$ACTING_LOGIN") || {