[BUG]: IDOR : Missing Ownership Check in ConcedeDebate
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 75/100
Research direction
Read backend/controllers/debatevsbot_controller.go, ConcedeDebate (lines 529-661). Find how the caller's email is retrieved from the Gin context, then scope the FindOne at line 557 and update filter at line 564 to also match debate.Email == caller email. Run TestBUG05_IDOR_ConcedeDebate or assert a 403 for cross-user concede. Done means an attacker gets 403 and the owner's debate stays unchanged.
Written by the indexing model from the issue text.
Description
Bug Description
POST /vsbot/concede accepts a debateId and updates the corresponding debates_vs_bot document to outcome: "User conceded" without verifying that the debate belongs to the authenticated caller.
In backend/controllers/debatevsbot_controller.go:557, the lookup is scoped only by _id:
err = db.DebateVsBotCollection.FindOne(
context.Background(),
bson.M{"_id": objID},
).Decode(&debate)
and the update at backend/controllers/debatevsbot_controller.go:564 is likewise unscoped:
filter := bson.M{"_id": objID}
update := bson.M{"$set": bson.M{"outcome": "User conceded"}}
No comparison is made between debate.Email and the authenticated user's email. Any authenticated user who obtains or guesses another user's debateId can force-concede that debate, overwrite its history with attacker-supplied content, and have a loss transcript/gamification applied to the attacker's own account.
Steps to Reproduce
- Start MongoDB (and Redis) with Docker:
docker start debateai-mongo-1 debateai-redis-1 - Start the backend and authenticate two users: [email protected] and [email protected].
- As the owner, start a bot debate via POST /vsbot/create and record the returned debateId.
- As the attacker, call the concede endpoint with the owner's debateId:
POST /vsbot/concede
Authorization: Bearer <attacker_token>
Content-Type: application/json
{
"debateId": "<OWNER_DEBATE_ID>",
"history": [{"sender": "User", "text": "Attacker injected history"}]
}
- Observe the response and the owner's document:
db.debates_vs_bot.findOne({_id: ObjectId("<OWNER_DEBATE_ID>")})
// outcome: "User conceded", history replaced by attacker-supplied history
Automated reproduction used a temporary test (TestBUG05_IDOR_ConcedeDebate) that inserts an owner-owned debate, authenticates as the attacker, and posts the owner's debateId to ConcedeDebate.
Logs and Screenshots
=== RUN TestBUG05_IDOR_ConcedeDebate
zz_bug05_idor_tmp_test.go:125: [email protected] [email protected] debateId=6adcc1ec0534e1a1696b0b8f
zz_bug05_idor_tmp_test.go:126: HTTP status=200 body={"message":"Debate conceded successfully"}
zz_bug05_idor_tmp_test.go:127: owner debate outcome after attacker request="User conceded" history=1 messages
zz_bug05_idor_tmp_test.go:136: BUG CONFIRMED: attacker conceded another user's debate (HTTP 200, outcome="User conceded")
--- PASS: TestBUG05_IDOR_ConcedeDebate (0.10s)
PASS
ok arguehub/controllers 0.116s
Additional observed side effect: the attacker received +10 points for a loss in the gamification update (updateGamificationAfterBotDebate), because the handler applies the concession to the caller's account rather than the debate owner.
Environment Details
- OS: Linux (x86_64)
- Go: go1.24
- Framework: Gin Gonic v1.9.1
- Database: MongoDB 7.0 (debateai-mongo-1, port 27017)
- Cache: Redis 7-Alpine (debateai-redis-1, port 6379)
- Affected endpoint: POST /vsbot/concede
- Affected file: backend/controllers/debatevsbot_controller.go (ConcedeDebate, lines 529–661; vulnerable lookup line 557, update line 564)
- Severity: High (Broken Access Control / IDOR)
Impact
High - Major feature is broken
Code of Conduct
- I have joined the Discord server and will post updates there
- I have searched existing issues to avoid duplicates
- Dominant language
- TypeScript
- Stars
- 104
- Forks
- 244
- Avg merge
- 1d 22h
- Merged PRs (30d)
- 42
Getting set up
- Ships a Dockerfile or Docker Compose file
- No pull request template
- No contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from AOSSIE-Org/DebateAI
-
bug
Difficulty 1/5 Under an hour Newbie friendliness 85/100
AOSSIE-Org/DebateAI#773 · 2 comments ·
Maintainers usually reply within 1 day
-
[BUG]: Header avatar and display name don't update after editing the profilePossibly taken @mithunkc017-ship-it claimed this 1 day ago. Openbug
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
AOSSIE-Org/DebateAI#770 · 2 comments ·
Maintainers usually reply within 1 day
-
[BUG]: Signed-out visitors see a fake account menu ("User", "No email", "Sign out") on public pagesPossibly taken @dhruvbit claimed this 1 day ago. Openbug
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
AOSSIE-Org/DebateAI#769 · 4 comments ·
Maintainers usually reply within 1 day
-
bug
Difficulty 1/5 1-3 hours Newbie friendliness 90/100
AOSSIE-Org/DebateAI#768 · 1 comment ·
Maintainers usually reply within 1 day
-
bug
Difficulty 1/5 Under an hour Newbie friendliness 92/100
AOSSIE-Org/DebateAI#760 ·
Maintainers usually reply within 1 day
All issues in AOSSIE-Org/DebateAI
Similar issues
-
type: bug
Difficulty 2/5 1-3 hours Newbie friendliness 79/100
Maintainers usually reply within 1 day
-
0️⃣ phase/new
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
-
Difficulty 1/5 Under an hour Newbie friendliness 70/100
microsoft/playwright#43640 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 70/100