fix(mosaic): harden Gitea pr merge fallback #521
Closed
jason.woltje
wants to merge 0 commits from
fix/t_301e4e3b-pr-merge-gitea-empty-uid into main
pull from: fix/t_301e4e3b-pr-merge-gitea-empty-uid
merge into: mosaicstack:main
mosaicstack:main
mosaicstack:mos-comms-live
mosaicstack:mos-comms
mosaicstack:feat/tess-interaction-agent
mosaicstack:fix/tess-docs-format
mosaicstack:next
mosaicstack:draft/mosaic-platform-prd
mosaicstack:enhance/tmux-send-buffer-race
mosaicstack:enhance/561-python-is-python3
mosaicstack:feat/federation-m3-verb-list
mosaicstack:fix/fleet-restart-tightloop-guard
mosaicstack:feat/federation-m3-scope-service
mosaicstack:feat/installer-dev-build-from-source
mosaicstack:fix/federation-tasks-prettier
mosaicstack:fix/installer-provider-gate-and-local-gateway-redis
mosaicstack:chore/fed-m3-dag-fix
mosaicstack:feat/federation-m3-verb-capabilities
mosaicstack:feat/federation-m3-query-source
mosaicstack:chore/fed-m3-backlog-sync
mosaicstack:release/mosaic-0.0.48
mosaicstack:fix/persona-class-pane-export
mosaicstack:feat/h3-fleet-provision
mosaicstack:fix/db-republish-backlog
mosaicstack:docs/north-star-per-agent-model-switch
mosaicstack:release/mosaic-0.0.46
mosaicstack:feat/a3a-agent-class-env
mosaicstack:feat/a3b-persona-contract
mosaicstack:feat/orchestrator-persona
mosaicstack:feat/h4-persona-overrides
mosaicstack:feat/h2-system-profiles
mosaicstack:feat/h1-persona-library
mosaicstack:feat/h-northstar-personas
mosaicstack:feat/a4-mosaic-backlog
mosaicstack:feat/a1-north-star
mosaicstack:feat/a2-role-registry
mosaicstack:release/mosaic-cli-0.0.45
mosaicstack:fix/h2-readiness-available
mosaicstack:release/mosaic-cli-0.0.44
mosaicstack:fix/fleet-pane-idle-activity
mosaicstack:release/mosaic-cli-0.0.43
mosaicstack:feat/h1-heartbeat-readiness
mosaicstack:release/mosaic-cli-0.0.42
mosaicstack:fix/fleet-claude-trust-gate-644
mosaicstack:fix/db-pglite-test-flake
mosaicstack:fix/framework-drift-reseed-642
mosaicstack:release/mosaic-cli-0.0.41
mosaicstack:chore/ci-base-node-24-alpine
mosaicstack:chore/ci-cache-phase1-prebaked-image
mosaicstack:feat/633-comms-block-runbook
mosaicstack:chore/ci-base-image
mosaicstack:feat/f3-m3-update-reseed
mosaicstack:feat/p6-docs-compliance-alpha
mosaicstack:release/mosaic-0.0.39
mosaicstack:feat/p5-overlay-composer
mosaicstack:release/mosaic-0.0.38
mosaicstack:feat/f3-m2-pi-harness
mosaicstack:feat/f3-watch-workdir
mosaicstack:feat/f3-hb-consistency
mosaicstack:release/mosaic-0.0.37b
mosaicstack:feat/fleet-mutable-add-remove
mosaicstack:feat/f3-pi-harness-hb
mosaicstack:feat/p4-1-comment-cleanup
mosaicstack:feat/fleet-presets-init
mosaicstack:feat/p4-upgrade-safe-migration
mosaicstack:feat/fleet-suite-prd
mosaicstack:release/mosaic-cli-0.0.37
mosaicstack:feat/fleet-ps-show-unmanaged
mosaicstack:release/mosaic-cli-0.0.36
mosaicstack:feat/fleet-heartbeat-sidecar
mosaicstack:feat/fleet-phase3-enablement
mosaicstack:release/mosaic-cli-0.0.35
mosaicstack:feat/fleet-launch-path
mosaicstack:feat/fleet-observability
mosaicstack:feat/p3-1-governance-gate-hardening
mosaicstack:feat/p3-constitution-extraction
mosaicstack:feat/p1p2-sanitization-gate
mosaicstack:feat/framework-constitution-alpha
mosaicstack:feat/p0-license-leak-sanitize
mosaicstack:docs/framework-agency-patterns
mosaicstack:fix/fleet-install-script-perms
mosaicstack:fix/fleet-preserve-agent-env
mosaicstack:release/mosaic-cli-0.0.32
mosaicstack:fix/fleet-release-hardening
mosaicstack:feat/fleet-cli-local-canary
mosaicstack:plan/tmux-fleet-durable-install
mosaicstack:fix/pi-skill-args-all-discover
mosaicstack:feat/pi-mosaic-tools-skill
mosaicstack:feat/tools-cheatsheet-salience
mosaicstack:fix/tooling-eval-injection-jq-json
mosaicstack:feat/us007-agent-registration
mosaicstack:docs/merge-authority-rule
mosaicstack:feat/mosaic-as-provisioning
mosaicstack:fix/pr-ci-wait-stdin-collision
mosaicstack:ci/publish-appservice-image
mosaicstack:feat/mosaic-as-daemon
mosaicstack:feat/mosaic-as-m4a
mosaicstack:fix/pi-token-lean-skills
mosaicstack:fix/git-wrapper-rollup-20260526
mosaicstack:fix/git-wrapper-repo-detection
mosaicstack:fix/woodpecker-wrapper-legacy-mosaic
mosaicstack:fix/t-a292e96f-gitea-pr-metadata
mosaicstack:fix/gitea-pr-metadata-login-t-a292e96f
mosaicstack:fix/t_a292e96f-pr-metadata-gitea
mosaicstack:fix/t_3a368a52-gitea-usc-login
mosaicstack:fix/bootstrap-hotfix
mosaicstack:fix/populate-known-packages-list
mosaicstack:fix/idempotent-init
No Reviewers
No Label
Milestone
No items
No Milestone
Projects
Clear projects
No project
Assignees
jason.woltje
Clear assignees
No Assignees
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: mosaicstack/stack#521
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.
Delete Branch "fix/t_301e4e3b-pr-merge-gitea-empty-uid"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Problem: pr-merge.sh preferred tea pr merge whenever a host tea login existed. On Gitea, tea identity preflight can succeed while non-interactive tea merge fails with the known empty identity error, permanently blocking a valid squash merge.
Change:
Exact fallback trigger:
Tests/evidence:
Tracking:
DO-178B Review: PR #521 — fix(mosaic): harden Gitea pr merge fallback
Software Level: C (Mosaic delivery wrapper/business-critical tooling)
Reviewer: ultron
Base:
755df9079eHead reviewed:
893dd19efbScope: packages/mosaic/framework/tools/git/pr-merge.sh, packages/mosaic/framework/tools/git/test-pr-merge-gitea-empty-uid.sh, docs/scratchpads/t_301e4e3b-pr-merge-gitea-empty-uid.md
Objective summary:
1 Requirements Traceability: PASS — PR body links t_245ad9d8/t_301e4e3b and issue #520.
2 Derived Requirements: PASS — API fallback safety behavior documented.
3 Configuration Management: PASS — branch targets main; head pinned above; scoped files only.
4 Functional Correctness: PASS for Gitea fallback — known empty uid path falls back; arbitrary tea failure blocks.
5 Structural Coverage: PASS for focused shell harness; broader coverage not applicable to shell wrapper.
6 Security Analysis: FAIL — eval injection remains in GitHub path of touched wrapper.
7 Data Integrity: PASS — merge action remains guarded by squash/main/queue checks before execution.
8 Robustness: PASS — fallback handles no-login and known tea identity failure; unknown failures fail closed.
9 Code Quality: FAIL — eval-based command construction remains in pr-merge.sh.
10 Framework Compliance: PASS — Mosaic squash/main/queue policies preserved for Gitea path.
11 Regression Protection: PASS for focused checks; full pnpm test failure documented as out-of-scope gateway DB setup.
12 Hands-Off Verification: PASS — diff is limited to declared wrapper/test/scratchpad scope.
Findings:
🔴 [BLOCKER] packages/mosaic/framework/tools/git/pr-merge.sh:193-195 — GitHub merge path still builds a command string with unvalidated PR_NUMBER and executes it via eval.
The review scope explicitly required verifying that shell quoting avoids eval-style injection risks. The Gitea path was fixed to quote arguments, but the same touched wrapper still has:
A mocked GitHub-platform probe with
-n '123; touch <sentinel> #'executed the injected command before reporting success. This is a command injection risk in a privileged delivery wrapper and fails the required shell-quoting check.Remediation:
PR_NUMBERbefore any metadata lookup/merge, e.g.[[ "$PR_NUMBER" =~ ^[0-9]+$ ]] || exit 1.cmd=(gh pr merge "$PR_NUMBER" --squash); [[ "$DELETE_BRANCH" == true ]] && cmd+=(--delete-branch); "${cmd[@]}".-n/--numberare rejected and do not execute on both GitHub and Gitea paths.Verification evidence run by reviewer:
bash -n packages/mosaic/framework/tools/git/pr-merge.shbash -n packages/mosaic/framework/tools/git/test-pr-merge-gitea-empty-uid.shshellcheck -x packages/mosaic/framework/tools/git/pr-merge.sh packages/mosaic/framework/tools/git/test-pr-merge-gitea-empty-uid.sh— PASSbash packages/mosaic/framework/tools/git/test-pr-merge-gitea-empty-uid.sh— PASS/home/hermes/.config/mosaic/tools/codex/codex-code-review.sh -b origin/main -o ...). Independent subagent review completed and agreed the Gitea-specific behavior is acceptable but GitHub eval is a material residual issue.Verdict: REQUEST CHANGES. Do not merge until the eval injection path is removed or PR_NUMBER is strictly validated before command construction. Tuesday should not proceed to CI/queue-guard/merge gate yet.
19fc6d549eto59b611ba8aClosing as superseded by #524 (rollup
821e19d, merged 2026-05-26). Verified during orchestration rebase: both commits (893dd19harden Gitea fallback,19fc6d5reject unsafe PR numbers) are already on main, which is a strict superset (adds basic_auth fallback, HTTP-code tracking, --dry-run). The api_url-unbound bug is FIXED on main (pr-merge.sh declares+assigns api_url before use). NOTE: the bug still reproduces from the installed framework copy on hosts (v0.0.30, 2026-05-06) which predates #524 — the real remaining action is upgrading the deployed framework, not merging this PR. — orchestrator (mos)Pull request closed