Do you need to file an issue?
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
-
Install and start DeepTutor:
- Clone the repository and install dependencies
- Start the service according to upstream documentation
- Open the web application in a browser
-
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)
-
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
-
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
-
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)
-
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
-
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
Do you need to file an issue?
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_idto 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_textwhere the book confirmation endpoint does not validate that the caller has ownership or authorization to modify the book object identified by the user-controlledbook_idparameter.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
Install and start DeepTutor:
Create a victim book (Browser 1 - Victim Context):
book_id(e.g., from/api/v1/book/booksresponse)fetch('/api/v1/book/books').then(r => r.json()).then(console.log)Open a second browser context (Browser 2 - Attacker Context):
Craft unauthorized confirm-proposal request:
/api/v1/book/books/confirm-proposalbook_idfrom step 2book_idwith the victim's IDExecute the unauthorized request:
Verify unauthorized modification (Browser 1 - Victim Context):
fetch('/api/v1/book/books/<victim-book-id>').then(r => r.json()).then(console.log)Confirm persistence:
deeptutor/book/storage.pyExpected Behavior
The
/api/v1/book/books/confirm-proposalendpoint should:book_idRelated 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:
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