EscrowService.refund()/release() check the caller's role but never bind the check to the specific escrow's sponsor — any SPONSOR can force-refund any other sponsor's escrow
维护者通常 1 天内回复
@Ranjeet2063 已经在做这个了。
开始于 2026年9月20日。
评估
- 难度
- 3/5
- 预计耗时
- 1-2 天
- 新手友好度
- 42/100
- Issue 类型
- 缺陷
- 描述清晰度
- 基本清楚
- 活跃度
- 活跃
- 技术栈
- typescript
- 领域
- authorization, backend
调研方向
Start in src/escrow/escrow.service.ts at refund() and release(), which take only escrowId, then in src/escrow/escrow.controller.ts where the route is gated by RolesGuard in src/auth/guards/roles.guard.ts. Thread the caller's id and role from the controller into the service and compare it against escrow.sponsorId for sponsors. Done when a sponsor who did not fund an escrow gets a rejection on refund and release, and the funder's own calls still succeed. The maintainer-of-repository check is not specified, so confirm its scope with the maintainers first.
由索引模型根据 Issue 内容生成。
描述
EscrowController.refund() (src/escrow/escrow.controller.ts) is gated by @Roles(UserRole.MAINTAINER, UserRole.SPONSOR) via RolesGuard. Reading src/auth/guards/roles.guard.ts, RolesGuard.canActivate only checks requiredRoles.some((role) => user.roles.includes(role)) — it has zero concept of which resource is being acted on. It never compares the authenticated caller's id to anything on the target Escrow.
EscrowService.refund(escrowId) (src/escrow/escrow.service.ts) takes only escrowId — no caller identity is threaded through at all — and unconditionally refunds to escrow.fundedByAddress, the original funder. So any authenticated user holding the SPONSOR role (not just the sponsor who actually funded this specific escrow, tracked on escrow.sponsorId) can call POST /escrow/:id/refund for any LOCKED escrow in the system and force it back to REFUNDED — cancelling a rival sponsor's active bounty/milestone escrow, even one where a contributor has already done the work and is waiting on release(). Funds don't go to the attacker (they return to the rightful original funder), so this is a griefing/availability attack rather than theft, but it lets one sponsor account unilaterally kill any other sponsor's in-flight payout.
This is distinct from #40 (DTOs trusting client-supplied recipient/funder ids) and #41 (TeamsService.assignToBounty missing an ownership guard on team assignment) — this is specifically the escrow refund/release authorization path lacking an escrow.sponsorId === callingUser.id (or equivalent maintainer-of-repo) check. Note that right now this is latent rather than actively exploitable, because (per the separate "nothing grants SPONSOR/MAINTAINER role" finding) every user is created with only roles: [UserRole.CONTRIBUTOR] and role assignment is currently unreachable through the app's own API. But the moment that's wired up (or a seed script/admin panel grants roles, which is exactly how local dev and e2e fixtures already assign roles), this gap becomes immediately live.
Fix: in EscrowService.refund/release, accept the authenticated caller's id/role from the controller and assert it matches escrow.sponsorId (for SPONSOR) or an appropriate maintainer-of-repository check (for MAINTAINER), not just "has a SPONSOR/MAINTAINER role somewhere."
- 主要语言
- TypeScript
- 星标
- 2
- 派生
- 90
- 平均合并
- 31 分钟
- 30 天内合并 PR
- 20
环境准备
- 提供 Dockerfile 或 Docker Compose 文件
- 没有 Pull Request 模板
- 没有贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
MergeFi/backend 的其他 Issue
-
bug
难度 2/5 1-3 小时 新手友好度 85/100
维护者通常 1 天内回复
-
bug security
难度 2/5 1-3 小时 新手友好度 74/100
维护者通常 1 天内回复
-
bug
难度 2/5 1-3 小时 新手友好度 82/100
维护者通常 1 天内回复
-
bug testing
难度 2/5 1-3 小时 新手友好度 85/100
维护者通常 1 天内回复
-
bug security
难度 2/5 1-3 小时 新手友好度 76/100
维护者通常 1 天内回复
相似的 Issue
-
Codex使用可 コード
难度 2/5 1-3 小时 新手友好度 72/100
ryuki-moro/Nicomaru#218 ·
维护者通常 3 天内回复
-
难度 2/5 1-3 小时 新手友好度 72/100
sveltejs/svelte-eslint-parser#1008 ·
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 78/100
silverbucket/inbox-rs#351 ·
维护者通常 1 天内回复
-
[Bug]: The H2 series' and the H3C's fan 3 is labelled "Chamber Fan", Bambu calls it the exhaust fan未关闭area:ui
难度 2/5 1-3 小时 新手友好度 88/100
维护者通常 1 天内回复
-
bug front P2
难度 2/5 1-3 小时 新手友好度 86/100
invoicerr-app/invoicerr#964 ·
维护者通常 1 天内回复