fix(forms): ignore client clawhubUserId on appeal submit - #40
Conversation
Persist configured fields plus server-fetched context only, and resolve ClawHub unban from that context instead of attacker FormData keys. Signed-off-by: Sebastien Tardif <SebTardif@ncf.ca>
|
🦞👀 Pull request received. I will update this pull request when review starts. ClawSweeper review completeClawSweeper finished reviewing this revision. The review result is being finalized. |
|
Codex review: needs real behavior proof before merge. Reviewed September 10, 2026, 11:33 PM ET / September 11, 2026, 03:33 UTC (Revision 2). ClawSweeper reviewWhat this changesThe PR filters appeal submissions to configured input fields, gives server-fetched account context precedence, and requires a stored ClawHub identity for unban requests. Merge readiness⛔ Blocked before merge - 6 items remain The fix remains necessary on current main, and the earlier test-location finding is resolved. No introduced correctness defect was found, but the security-sensitive change still needs production-path proof and an explicit rollout decision for pending appeals. Priority: P0 Review scores
Verification
How this fits togetherHermit's forms service authenticates applicants, retrieves moderation context, stores appeals, and sends them to Discord reviewers. Accepting a ClawHub appeal uses Hermit's service credential to request an account unban. flowchart TD
A[Authenticated applicant and form fields] --> B[Filter configured inputs]
C[ClawHub account context] --> D[Merge server context last]
B --> D
D --> E[Stored appeal]
E --> F[Authorized Discord reviewer]
F --> G[ClawHub unban service]
Decision needed
Why: Existing rows have no trust-version marker, and choosing revalidation or invalidation affects legitimate pending appeals. Before merge
Findings
Agent review detailsSecurityNeeds attention: The patch improves intake security without a detected new vulnerability, but persisted identity trust remains a rollout and proof concern. Review metrics
Merge-risk optionsMaintainer options:
Technical reviewBest possible solution: Preserve server-owned identity at intake and establish an approved acceptance-time or rollout safeguard for untrusted pending appeals, with final-effect authorization evidence. Do we have a high-confidence way to reproduce the issue? Yes, from source: submit an extra clawhubUserId with a valid eligible account's form, then have a reviewer accept it; main stores and dispatches the substituted ID. This review did not execute that path. Is this the best way to solve the issue? Yes for new submissions: filtering configured inputs and overlaying server context is a narrow repair. Complete remediation still requires an approved treatment of pending rows and proof through the final unban boundary. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning medium; reviewed against fd6920504d12. LabelsLabel justifications:
EvidenceSecurity concerns:
What I checked:
Likely related people:
Rank-up movesOptional improvements that raise the rating; they are not merge blockers.
Rating scale
Overall follows the weaker of proof and patch quality. Workflow
HistoryReview history (1 earlier review cycle)
|
Signed-off-by: Sebastien Tardif <SebTardif@ncf.ca>
What Problem This Solves
POST https://appeals.openclaw.ai/clawhub/submitcopies every FormData key exceptsession, then stores{...context, ...collected.payload}. A hiddenclawhubUserIdfield replaces the ClawHub ID that was fetched for the signed-in GitHub account.Accept then runs
clawhub.unbanUserwithtarget: "clawhubUserId"from that stored payload. The review UI shows the injected ID, but the action still unbans whoever the applicant wrote.This change persists only configured form fields, overlays server-fetched context last, and resolves the unban target from that context.
Why This Change Was Made
An authenticated applicant could unban a different ClawHub user by submitting an extra form field. The OAuth-bound context must win.
User Impact
Ban-appeal submit still works for the signed-in account. Extra FormData keys are ignored. Reviewers still see the ClawHub ID from server context.
Evidence
Live
bunagainst the patched collect/merge helpers with attacker FormData:The client sent
clawhubUserId=attacker. It is absent fromcollectedand the stored payload keepsoauth-clawhub-user.Same-repo: the appeal form landed in #13. #35 stops accept/deny when form actions fail; it does not stop payload overwrite.
Real behavior proof
C:\tmp\wt-he-f008ate356aee.Requestwith FormDatareason=please unbanandclawhubUserId=attacker, then calledcollectPayloadandbuildSubmissionPayloadwith contextoauth-clawhub-user.reason. StoredclawhubUserIdisoauth-clawhub-user.appeals.openclaw.aiwith a real GitHub OAuth session.