fix(git-wrappers): #865 round-7 addendum — conservative YAML recognizer + review/comment hardening
All checks were successful
ci/woodpecker/pr/ci Pipeline was successful
All checks were successful
ci/woodpecker/pr/ci Pipeline was successful
Fold the remaining round-7 audit items into the tea-CLI comment-invocation fix. Fallback token parser (detect-platform.sh, test-gitea-login-resolution.sh): Replace the line-by-line scalar fallback with a strict CONSERVATIVE block-YAML recognizer that reconstructs the same object PyYAML would or fails closed the instant it meets anything outside the tea-config subset. Closes 5 structural fail-open classes the old parser missed (nested-shadow logins, block-scalar shadow, duplicate root key / login name / token field, malformed-after-valid, extra-document / end-marker). Validated by a 360k-check differential fuzz vs real PyYAML (0 fail-open) plus explicit forced-PyYAML-absence fixtures. ITEM 1 (pr-review.sh) current-head TOCTOU: after the exact review-id read-back succeeds, re-read the live PR head and fail closed if it advanced past the submitted commit_id, so a review is never reported as covering a superseded tip. ITEM 2 (pr-review.sh comment action): require the returned resource be a pull_request (populated pull_request_url); reject a bare issue_url so a plain issue #N cannot masquerade as a verified PR comment. issue-comment.sh keeps its broader issue-or-PR acceptance. ITEM 3a (both wrappers): move the Authorization bearer OUT of curl argv into a private mode-0600 curl --config file (gitea_write_auth_config), removed on every exit path, so the token never appears in the process table. ITEM 3b (pr-review.sh): bind the review body with presence + string-type + exact equality instead of `(body or "")`, so a non-empty submitted body persisted as null/missing fails closed. Tests: add race, plain-issue, argv-capture (no token printed), and null-body fixtures; broaden temp-leak checks to the auth-config files. Full gate set green (bash -n, shellcheck -x -S warning, prettier, all 3 REST/resolution suites with PyYAML and forced-absent, cold TURBO_FORCE turbo 14/14). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -131,13 +131,18 @@ gitea_resolve_api_for_login() {
|
||||
# a concurrent write from a DIFFERENT identity cannot satisfy verification.
|
||||
# Prints the login on success.
|
||||
gitea_authenticated_login() {
|
||||
local response_file status
|
||||
local response_file auth_config status
|
||||
|
||||
response_file=$(mktemp "${TMPDIR:-/tmp}/mosaic-issue-comment-whoami.XXXXXX")
|
||||
trap 'rm -f "$response_file"' RETURN
|
||||
auth_config=$(gitea_write_auth_config "$GITEA_API_TOKEN") || {
|
||||
rm -f "$response_file"
|
||||
echo "Error: could not stage Gitea credential for identity read" >&2
|
||||
return 1
|
||||
}
|
||||
trap 'rm -f "$response_file" "$auth_config"' RETURN
|
||||
|
||||
if ! status=$(curl -sS -o "$response_file" -w '%{http_code}' \
|
||||
-H "Authorization: token $GITEA_API_TOKEN" \
|
||||
--config "$auth_config" \
|
||||
"$GITEA_API_ROOT/user"); then
|
||||
echo "Error: Gitea authenticated-identity read transport failed" >&2
|
||||
return 1
|
||||
@@ -179,7 +184,7 @@ PY
|
||||
# Args: $1 = issue number, $2 = comment body, $3 = acting identity login.
|
||||
gitea_create_comment_verified() {
|
||||
local issue_number="$1" comment_body="$2" acting_login="$3"
|
||||
local payload write_file readback_file write_status readback_status created_id
|
||||
local payload write_file readback_file auth_config write_status readback_status created_id
|
||||
|
||||
payload=$(COMMENT_BODY="$comment_body" python3 -c '
|
||||
import json
|
||||
@@ -189,11 +194,16 @@ print(json.dumps({"body": os.environ["COMMENT_BODY"]}))
|
||||
')
|
||||
write_file=$(mktemp "${TMPDIR:-/tmp}/mosaic-issue-comment-write.XXXXXX")
|
||||
readback_file=$(mktemp "${TMPDIR:-/tmp}/mosaic-issue-comment-getid.XXXXXX")
|
||||
trap 'rm -f "$write_file" "$readback_file"' RETURN
|
||||
auth_config=$(gitea_write_auth_config "$GITEA_API_TOKEN") || {
|
||||
rm -f "$write_file" "$readback_file"
|
||||
echo "Error: could not stage Gitea credential for comment write" >&2
|
||||
return 1
|
||||
}
|
||||
trap 'rm -f "$write_file" "$readback_file" "$auth_config"' RETURN
|
||||
|
||||
if ! write_status=$(curl -sS -o "$write_file" -w '%{http_code}' \
|
||||
-X POST \
|
||||
-H "Authorization: token $GITEA_API_TOKEN" \
|
||||
--config "$auth_config" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d "$payload" \
|
||||
"$GITEA_API_BASE/issues/$issue_number/comments"); then
|
||||
@@ -223,7 +233,7 @@ PY
|
||||
) || return 1
|
||||
|
||||
if ! readback_status=$(curl -sS -o "$readback_file" -w '%{http_code}' \
|
||||
-H "Authorization: token $GITEA_API_TOKEN" \
|
||||
--config "$auth_config" \
|
||||
"$GITEA_API_BASE/issues/comments/$created_id"); then
|
||||
echo "Error: Gitea comment read-back transport failed" >&2
|
||||
return 1
|
||||
|
||||
Reference in New Issue
Block a user