Skip to content

[Bug]:Authorization Bypass in Book Confirmation Flow - Unauthorized Book Modification via book_id #514

Description

@Ro1ME

Do you need to file an issue?

  • I have searched the existing issues and this bug is not already filed.
  • I believe this is a legitimate bug, not just a question or feature request.

Describe the bug

DeepTutor contains an authorization bypass vulnerability in the book confirmation flow. An unauthenticated or unauthorized caller can reuse a publicly exposed book_id to submit a confirm-proposal request for an existing book, causing unauthorized overwrites of persisted metadata and spine content.

The vulnerability exists in deeptutor/book/storage.py:_atomic_write_text where the book confirmation endpoint does not validate that the caller has ownership or authorization to modify the book object identified by the user-controlled book_id parameter.

Vulnerability Type: Authorization bypass through user-controlled object identifier
Attack Vector: Remote HTTP request
Severity: High - allows unauthorized modification of user data

Steps to reproduce

  1. Install and start DeepTutor:

    • Clone the repository and install dependencies
    • Start the service according to upstream documentation
    • Open the web application in a browser
  2. Create a victim book (Browser 1 - Victim Context):

    • Open Developer Tools → Network tab → Enable "Preserve log"
    • Create a test book through the normal UI with any harmless topic
    • In the Network tab, locate the book creation or listing response
    • Record the generated book_id (e.g., from /api/v1/book/books response)
    • Alternative: Run in Console: fetch('/api/v1/book/books').then(r => r.json()).then(console.log)
  3. Open a second browser context (Browser 2 - Attacker Context):

    • Use a different browser profile or incognito/private window
    • Do NOT reuse the victim's session cookies or authentication
    • Open Developer Tools → Console
  4. Craft unauthorized confirm-proposal request:

    • In Browser 2 Console, prepare a POST request to /api/v1/book/books/confirm-proposal
    • Use the victim's book_id from step 2
    • Include a malicious or modified proposal payload with Content-Type: application/json
    • Example approach: Create a disposable book in Browser 2, confirm it once through UI, copy the request as fetch from Network tab, then replace only the book_id with the victim's ID
  5. Execute the unauthorized request:

    • Send the crafted request from Browser 2 Console
    • Observe that the server accepts the request (returns 200 OK instead of 401/403)
  6. Verify unauthorized modification (Browser 1 - Victim Context):

    • Return to the victim browser and refresh the book page
    • Or run in Console: fetch('/api/v1/book/books/<victim-book-id>').then(r => r.json()).then(console.log)
    • Confirm that the book's title, description, scope, or spine has been overwritten with the attacker's values
  7. Confirm persistence:

    • Verify the changes are persisted in deeptutor/book/storage.py
    • Confirm no owner-binding or authorization check prevented the modification

Expected Behavior

The /api/v1/book/books/confirm-proposal endpoint should:

  • Validate that the caller has ownership or authorization to modify the book identified by book_id
  • Return HTTP 401 (Unauthorized) or 403 (Forbidden) when an unauthorized caller attempts to modify another user's book
  • Implement proper object-level authorization checks before persisting any changes
  • Bind book objects to their creator/owner and enforce this binding on all modification operations

Related Module

API/Backend

Configuration Used

Default DeepTutor configuration

No special configuration required to reproduce

Vulnerability exists in default installation

Logs and screenshots

Network Tab - Victim book_id captured:

{
  "book_id": "abc123-victim-book-id",
  "title": "Original Victim Book",
  "owner": "victim_user"
}

Console - Unauthorized request from attacker context:

fetch('/api/v1/book/books/confirm-proposal', {
  method: 'POST',
  headers: {'Content-Type': 'application/json'},
  body: JSON.stringify({
    book_id: 'abc123-victim-book-id',  // Victim's book_id
    proposal: {
      title: 'Attacker Modified Title',
      description: 'Unauthorized content',
      // ... other proposal fields
    }
  })
}).then(r => r.json()).then(console.log);
// Response: 200 OK - Request accepted without authorization check

Verification - Victim book modified:

{
  "book_id": "abc123-victim-book-id",
  "title": "Attacker Modified Title",  // Changed!
  "description": "Unauthorized content",  // Changed!
  "owner": "victim_user"  // Owner unchanged but content modified
}

Additional Information

  • DeepTutor Version:v1.4.0 / main@6153d8c (2026-05-22)
  • Operating System:Windows 11, macOS 14.0, Ubuntu 22.04 (all affected)
  • Python Version:3.10+
  • Node.js Version:18.17.0+
  • Browser (if applicable):Chrome 120+, Firefox 121+ (any modern browser)
  • Related Issues:None

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions