Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

[BUG]: IDOR : Missing Ownership Check in ConcedeDebate

Open Beginner friendly
#772 1 comment 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
75/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
docker, go, mongodb, redis
Domain
api, backend, security

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
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
  1. Start MongoDB (and Redis) with Docker:
    docker start debateai-mongo-1 debateai-redis-1
  2. Start the backend and authenticate two users: [email protected] and [email protected].
  3. As the owner, start a bot debate via POST /vsbot/create and record the returned debateId.
  4. 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"}]
}
  1. 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

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from AOSSIE-Org/DebateAI

All issues in AOSSIE-Org/DebateAI

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.