Summary
PR #6092 (closing #6089) fixed 15 locked data bypass paths across the main API, but the Developer API (routers/developer.py) and Knowledge Graph (routers/knowledge_graph.py) were not covered. All 6 write endpoints in the Developer API allow modifying or deleting locked conversations, memories, and action items. The PATCH endpoints also leak locked content in their responses.
This was discovered during a re-audit requested by @beastoin, who flagged the PATCH conversation endpoint in the Developer API.
Current Behavior
Developer API — Write endpoints bypass is_locked (6 endpoints)
| # |
Method |
Path |
Line |
Severity |
Impact |
| D1 |
PATCH |
/v1/dev/user/conversations/{id} |
1036 |
HIGH |
Can modify title/discarded + response leaks full locked conversation |
| D2 |
DELETE |
/v1/dev/user/conversations/{id} |
1016 |
MEDIUM |
Can delete locked conversations |
| D3 |
PATCH |
/v1/dev/user/memories/{id} |
314 |
HIGH |
Can modify content/visibility/tags/category + response leaks full locked memory |
| D4 |
DELETE |
/v1/dev/user/memories/{id} |
296 |
MEDIUM |
Can delete locked memories |
| D5 |
PATCH |
/v1/dev/user/action-items/{id} |
542 |
HIGH |
Can modify description/completed/due_at + response leaks full locked action item |
| D6 |
DELETE |
/v1/dev/user/action-items/{id} |
527 |
MEDIUM |
Can delete locked action items |
Note: The Developer API's READ endpoints are already protected:
- GET conversations list: filters locked (line 763) ✓
- GET conversation by ID: returns 404 for locked (line 870) ✓
- GET action items: filters locked (line 430) ✓
- GET memories: truncates locked content (line 172) ✓
Knowledge Graph — Locked memories processed into graph (1 endpoint)
| # |
Method |
Path |
Line |
Severity |
Impact |
| K1 |
POST |
/v1/knowledge-graph/rebuild |
52 |
HIGH |
get_memories(uid, limit=500) includes locked memories, processes full content through LLM, stores derived knowledge accessible via GET /v1/knowledge-graph |
Expected Behavior
- PATCH endpoints on locked items should return HTTP 402 (matching
_get_valid_conversation_by_id() pattern from routers/conversations.py:50-58)
- DELETE endpoints on locked items should return HTTP 402 (prevent modification of locked data)
- Knowledge graph rebuild should filter out locked memories before LLM processing
Root Cause
PR #6092 covered 20 files but missed routers/developer.py and routers/knowledge_graph.py entirely. The Developer API was built as a separate surface from the main API and wasn't included in the original bypass audit (#6089).
Recommended Fix
Developer API (3 HIGH + 3 MEDIUM)
Add is_locked guard to all 6 write endpoints. Pattern:
# For conversations:
conversation = conversations_db.get_conversation(uid, conversation_id)
if not conversation:
raise HTTPException(status_code=404, detail="Conversation not found")
if conversation.get('is_locked', False):
raise HTTPException(status_code=402, detail="A paid plan is required to access this conversation.")
# For memories:
memory = memories_db.get_memory(uid, memory_id)
if not memory:
raise HTTPException(status_code=404, detail="Memory not found")
if memory.get('is_locked', False):
raise HTTPException(status_code=402, detail="A paid plan is required to access this memory.")
# For action items:
action_item = action_items_db.get_action_item(uid, action_item_id)
if not action_item:
raise HTTPException(status_code=404, detail="Action item not found")
if action_item.get('is_locked', False):
raise HTTPException(status_code=402, detail="A paid plan is required to access this action item.")
Knowledge Graph
Filter locked memories before processing:
def _rebuild_graph_task(uid: str, user_name: str):
memories = memories_db.get_memories(uid, limit=500)
memories = [m for m in memories if not m.get('is_locked', False)]
rebuild_knowledge_graph(uid, memories, user_name)
Files to Modify
backend/routers/developer.py — 6 endpoints (D1-D6)
backend/routers/knowledge_graph.py — 1 endpoint (K1)
Testing
- Unit tests for each endpoint with
is_locked=True data → expect 402
- Unit test for knowledge graph rebuild with locked memories → expect filtered out
- Verify existing Developer API read endpoints remain protected
Related
by AI for @beastoin
Summary
PR #6092 (closing #6089) fixed 15 locked data bypass paths across the main API, but the Developer API (
routers/developer.py) and Knowledge Graph (routers/knowledge_graph.py) were not covered. All 6 write endpoints in the Developer API allow modifying or deleting locked conversations, memories, and action items. The PATCH endpoints also leak locked content in their responses.This was discovered during a re-audit requested by @beastoin, who flagged the PATCH conversation endpoint in the Developer API.
Current Behavior
Developer API — Write endpoints bypass
is_locked(6 endpoints)/v1/dev/user/conversations/{id}/v1/dev/user/conversations/{id}/v1/dev/user/memories/{id}/v1/dev/user/memories/{id}/v1/dev/user/action-items/{id}/v1/dev/user/action-items/{id}Note: The Developer API's READ endpoints are already protected:
Knowledge Graph — Locked memories processed into graph (1 endpoint)
/v1/knowledge-graph/rebuildget_memories(uid, limit=500)includes locked memories, processes full content through LLM, stores derived knowledge accessible via GET/v1/knowledge-graphExpected Behavior
_get_valid_conversation_by_id()pattern fromrouters/conversations.py:50-58)Root Cause
PR #6092 covered 20 files but missed
routers/developer.pyandrouters/knowledge_graph.pyentirely. The Developer API was built as a separate surface from the main API and wasn't included in the original bypass audit (#6089).Recommended Fix
Developer API (3 HIGH + 3 MEDIUM)
Add
is_lockedguard to all 6 write endpoints. Pattern:Knowledge Graph
Filter locked memories before processing:
Files to Modify
backend/routers/developer.py— 6 endpoints (D1-D6)backend/routers/knowledge_graph.py— 1 endpoint (K1)Testing
is_locked=Truedata → expect 402Related
by AI for @beastoin