diff --git a/REVIEW.md b/REVIEW.md index 98968bc..3c80ed5 100644 --- a/REVIEW.md +++ b/REVIEW.md @@ -85,3 +85,40 @@ Verified cold from own clone. Acceptance: "push to cc-ci triggers a visible gree UI/API serve them. Full D7 UX is M8. Verdict: **M2 PASS.** No new findings. + +## M3 — Comment bridge: PRE-CLAIM PROGRESS (not yet PASS) @2026-05-26T23:48Z + +M3 is **Blocked** in STATUS (Gitea not delivering webhooks), so not a gate verdict yet. But the +bridge is deployed and I independently hammered its auth/filter logic — the part I can verify +regardless of the delivery leg (and which survives a pivot to API polling). Probes were live POSTs +to `https://ci.commoninternet.net/hook` via the SOCKS proxy, with HMAC signatures I computed from +the on-host secret (read with root; value never printed/committed): + +| probe | expect | got | +|---|---|---| +| no `X-Gitea-Signature` | 401 | **401** | +| bad signature | 401 | **401** | +| valid sig, event=`ping` (not issue_comment) | 204 | **204** | +| valid sig, `!testmexyz` on a real PR | 204 (no trigger) | **204** | +| valid sig, `!testme` but issue is not a PR | 204 | **204** | +| valid sig, `!testme` on PR, action=`edited` | 204 | **204** | +| valid sig, `!testme` on real PR, **non-collaborator** | 403 | **403** | + +So: HMAC fail-closed + timing-safe (`compare_digest`, verified before body parse), `!testmexyz` +correctly ignored (exact trimmed match), non-PR ignored, and a non-collaborator is rejected (403; +collaborator status re-checked via Gitea API, not trusted from the signed payload). Source review +of `bridge/bridge.py` found no auth bypass. + +**Blocker independently corroborated (operator-side):** the bridge hook *is* registered + active on +`recipe-maintainers/cc-ci` (id 210, events `[issue_comment]` → `ci.commoninternet.net/hook`), and +the bot is not a Gitea site-admin (`GET /admin/hooks` → 403) nor org owner, so it genuinely cannot +inspect/change Gitea's `[webhook] ALLOWED_HOST_LIST`. Endorse STATUS `## Blocked`: needs operator +allowlisting or the documented poll-the-API fallback. + +**Still UNVERIFIED for an M3 PASS:** (1) the positive path — a valid collaborator `!testme` actually +starts a build + posts the PR comment end-to-end; (2) real Gitea→bridge delivery (or the polling +pivot). Will complete both when M3 is claimed. + +**Noted for M7 (not a finding yet):** the Drone-managed Gitea webhook (id 209) carries its webhook +secret as a `?secret=` query param in the hook URL (Drone default; admin-only in Gitea, not in cc-ci +git / CI logs / dashboard). Will adjudicate against D6 at M7.