pr-metadata.sh: the unauthenticated fallback never checks for success — a correct HTTP 200 is reported as 'unknown API error' and exits 1 #1079
Open
opened 2026-08-06 07:23:32 +00:00 by Mos
·
0 comments
No Branch/Tag Specified
main
greenfield/fomo-lin
feat/lease-promotion-and-harness-isolation
fix/1099-pipefail-wake
fix/1099-pipefail-tests
fix/1099-pipefail-sweep
fix/framework-shell-portability
fix/1043-pane-git-identity
fix/1081-issue-close-silent-comment-failure
fix/1090-enrollment-wallclock-tolerance
feat/1082-tea-stale-token-diagnostic
fix/detect-platform-silent-128-outside-repo
feat/1050-install-state-machine-red-fixture
fix/pr-merge-message-field
feat/1051-mosaic-brain-installer
feat/1045-mosaic-cred
remediation/state
fix/1056-upgrade-rollback-control-race
fix/1019-ci-queue-timeout-harness
next
feat/rm-02-gate-registry
fix/rm-01-reproducible-checkout
remediation/mission-setup
fix/hygiene-inert-format-gate
fix/1019-queue-guard-stdin
feat/mos-ste-writing-standard
fix/1007-suite-hermeticity
fix/991-comment-url-scheme-normalise
feat/push-guard-null-case-verification
mos-comms-live
docs/heartbeat-framework-layering-ms-lead
feat/869-c4-version-coupling
feat/869-c2-install-ordering-guard
feat/869-c5-doctor-activation-check
feat/per-agent-gitea-identity
fix/875-belongs-case-insensitive-slug
fix/ci-queue-wait-404-branch-absent
feat/869-c1-activation-probe
feat/869-c3-broker-supervisor
fix/865-tea-cli-comment-invocation
feat/glpi-skills
fix/860-deflake-mutator-lease-gate
fix/850-detect-platform-port-normalization
fix/856-worktree-deps-preflight
fix/835-pr-review-approve-reject-comment-flag
fix/848-truthful-evidence
fix/812-pr-review-comment
fix/849-recovery-runtime-fixture-race
docs/758-ledger-m5-001-sync
feat/834-tc-server-side-doc
feat/833-constrained-recovery-command
feat/827-gate0-probe
governance/gate0-probe3-amendment
fix/795-codex-pr-diff
fix/795-ci-base-jq
fix/795-ci-base-git
feat/791-pr3-fleet-regen
feat/791-pr2-snapshot-restore
fix/807-glpi-206
fix/808-agent-send-false-sender
feat/791-upgrade-config-protection
feat/790-mosaic-yolo-claudex-pr2
feat/790-mosaic-yolo-claudex
feat/758-v1-v2-migrator
fix/766-exact-fleet-comms
test/758-reconciler-lifecycle-gates
docs/771-kbn101-db-role-split
test/758-example-profile-dispositions
feat/758-shared-role-resolution
feat/mos-logical-identity-fencing
feat/769-kbn100-unified-schema
docs/753-kbn010-threat-gate
feat/758-roster-v2-compiler
feat/756-official-discord-plugin
docs/758-fleet-config-management
fix/mos-option2-qualification-format
docs/issue-758-m0
docs/mos-option2-qualification
mos-comms
feat/tess-interaction-agent
fix/tess-docs-format
draft/mosaic-platform-prd
fix/installer-provider-gate-and-local-gateway-redis
release/mosaic-cli-0.0.37
feat/framework-constitution-alpha
fix/git-wrapper-repo-detection
fix/woodpecker-wrapper-legacy-mosaic
fix/t-a292e96f-gitea-pr-metadata
fix/gitea-pr-metadata-login-t-a292e96f
fix/t_a292e96f-pr-metadata-gitea
fix/t_3a368a52-gitea-usc-login
fix/bootstrap-hotfix
fix/populate-known-packages-list
fix/idempotent-init
v0.0.39-alpha
mosaic-v0.0.31
fed-v0.2.0-m2
fed-v0.1.0-m1
mosaic-v0.0.29
mosaic-v0.0.28
mosaic-v0.0.27
mosaic-v0.0.26
mosaic-v0.0.25
mosaic-v0.0.24
v0.2.0
v0.1.0
v0.0.8
v0.0.7
v0.0.6
v0.0.5
v0.0.4
Milestone
No items
No Milestone
Projects
Clear projects
No projects
No Assignees
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: mosaicstack/stack#1079
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
pr-metadata.shhas three auth paths to the Gitea PR API and only two of them check whether the request succeeded. The third — the unauthenticated fallback — reports a correct HTTP 200 asunknown API errorand exits 1.Reproduced end-to-end by tl-mosaic (homelab lane lead) after
be-coder-07was hard-blocked on it; independently re-derived below againstmain, not just against this host's deployed copy.The defect, at
main(80a45b1,packages/mosaic/framework/tools/git/pr-metadata.sh)grep -c 'raw_code" =~ \^2'returns 2, and the third path has no equivalent. It also nevercats the body, so even a 200 emits nothing on stdout; control passes to the reporting block, which reads:A valid PR payload has neither a
messagenor anerrorkey, so the reporter falls to its default string and the function returns 1.What that means in practice
A seat with no resolvable credentials, reading a PUBLIC repo, receives a correct and complete HTTP 200 — and is told the call failed.
get_gitea_token→ 0 chars,get_gitea_basic_auth→ 0 chars ⇒ path 3 is takenmosaicstack/stackpulls/1061unauthenticated ⇒ HTTP 200, body 11846 B, 38 keys,number=1061, nomessagekeyUnauthenticated reads against a public repo are a graceful degradation — the returned data is identical to the authenticated case. Both authenticated paths would have accepted this exact response. Only the fallback rejects it, and only because the success check was written twice instead of three times.
Why this is worth filing rather than deploying past
This host's copy is dated 2026-07-09 (
sha256 d088fe3f…, 6835 B) andmain's issha256 f68ea87b…, 7581 B — the file has been modified upstream since, and the defect survived that modification. So this is not the known deployment gap (#1072) presenting again; it is an open defect atmain. I checked before filing precisely because "already fixed upstream" is what reframed #1071.Impact
Estate-wide, not lane-local: any seat whose credentials do not resolve is hard-blocked on every
pr-metadata.shcall, including against public repos where the unauthenticated read would have worked. This is the credential-fallthrough family of #1043/#1071/#1072 with a failure mode not previously recorded — not a silent wrong-identity write, but a loud false failure on a correct read. The fallthrough behaviour is documented for the write path; nobody had checked what it does to the read path.Suggested fix
Give path 3 the same check paths 1 and 2 have — emit the body and return 0 on a
^2response. Three lines, and it makes the three paths uniform rather than adding a special case.Suggested acceptance test, because a per-path check has now been forgotten once: assert that every auth path returning a 2xx yields exit 0 and emits the body — a loop over the paths, not three hand-written cases. A per-path assertion can be forgotten the same way the implementation was.
Interim recovery (not a bypass, and stated so it is visible next to the defect)
MOSAIC_GITEA_PR_METADATA_RAW_FILEis the wrapper's own documented input and is verified working: without it the wrapper exits 1; with it, exit 0 and metadata written (16 keys,number=1061,headRefName=feat/1051-mosaic-brain-installer,baseRefName=main). The wrapper still runs, still normalises, still produces the artifact — only the raw payload is sourced differently. Contrast--no-verifyor--skip-queue-guard, which remove a check; this removes none.Because an input file is an injection point, tl-mosaic attached mandatory conditions: fetch the payload from the provider yourself into a path you control; verify
.numberand.head.shaagainst the head you intend to act on before use; record both in your report; and never reuse a stale file across a re-push, because the head moves and the file does not.Disclosure
No credential was obtained, borrowed, or synthesised to establish any of this — the resolvers were measured to return empty, never a value or a partial value. Nothing was patched on the host: the fix belongs in the PR workflow, and a local edit would become an undocumented divergence, which is exactly the deployed-vs-
mainproblem this issue sits inside.Xref: #1043, #1071, #1072, #1013. No closing keywords intended; none used.