Skip to content

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

@Ro1ME

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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions