🎯 Objective
Add authentication and ownership verification to GET /api/tasks/:id and DELETE /api/tasks/:id to prevent information disclosure and unauthorized task cancellation.
📁 Files to Modify
| Action |
File Path |
Description |
| Modify |
backend/src/api/app.ts |
Add ownership checks to task endpoints |
| Modify |
backend/src/api/docs/openapi.ts |
Document auth requirements |
📁 Files to Create/Modify (Tests)
| Action |
File Path |
Description |
| Modify |
backend/tests/tasks.test.ts |
Add tests for unauthorized access |
🔍 Current Vulnerable Code (app.ts)
// VULNERABLE — No auth, returns full task details to anyone
app.get('/api/tasks/:id', async (req, res) => {
const task = taskStore.getTask(req.params.id);
// Returns: prompt, DAG, results, walletPublicKey — all exposed
res.json(task);
});
// VULNERABLE — No ownership check, anyone can cancel any task
app.delete('/api/tasks/:id', async (req, res) => {
const task = taskStore.getTask(req.params.id);
if (task.status === 'queued') {
taskStore.updateTaskStatus(task.id, 'cancelled');
res.json({ status: 'cancelled' });
}
});
💥 Impact
- Any user can read any other user's task prompts and results (information disclosure)
- Any user can cancel any other user's queued tasks (denial of service)
- Sensitive data in prompts (business plans, code, etc.) is exposed
✅ Expected Fix
GET /api/tasks/:id
app.get('/api/tasks/:id', async (req, res) => {
const task = taskStore.getTask(req.params.id);
if (!task) {
return res.status(404).json({ error: 'Task not found' });
}
const requesterKey = req.headers['walletpublickey'] as string;
// If requester is not the owner, redact sensitive fields
if (requesterKey && requesterKey !== task.walletPublicKey) {
return res.status(403).json({ error: 'Access denied' });
}
res.json(task);
});
DELETE /api/tasks/:id
app.delete('/api/tasks/:id', async (req, res) => {
const task = taskStore.getTask(req.params.id);
if (!task) {
return res.status(404).json({ error: 'Task not found' });
}
const requesterKey = req.headers['walletpublickey'] as string;
if (!requesterKey || requesterKey !== task.walletPublicKey) {
return res.status(403).json({ error: 'Not authorized to cancel this task' });
}
if (task.status !== 'queued') {
return res.status(409).json({ error: `Cannot cancel task in '${task.status}' status` });
}
taskStore.updateTaskStatus(task.id, 'cancelled');
res.json({ status: 'cancelled' });
});
📁 Reference Files
| File Path |
Purpose |
backend/src/api/app.ts (line ~303) |
GET /api/tasks/:id |
backend/src/api/app.ts (line ~345) |
DELETE /api/tasks/:id |
backend/src/coordinator/taskStore.ts |
Task storage interface |
backend/src/api/middleware/auth.ts |
Existing auth middleware pattern |
✅ Acceptance Criteria
🎯 Objective
Add authentication and ownership verification to
GET /api/tasks/:idandDELETE /api/tasks/:idto prevent information disclosure and unauthorized task cancellation.📁 Files to Modify
backend/src/api/app.tsbackend/src/api/docs/openapi.ts📁 Files to Create/Modify (Tests)
backend/tests/tasks.test.ts🔍 Current Vulnerable Code (app.ts)
💥 Impact
✅ Expected Fix
GET /api/tasks/:id
DELETE /api/tasks/:id
📁 Reference Files
backend/src/api/app.ts(line ~303)backend/src/api/app.ts(line ~345)backend/src/coordinator/taskStore.tsbackend/src/api/middleware/auth.ts✅ Acceptance Criteria
GET /api/tasks/:idDELETE /api/tasks/:idqueuedtasks (notrunningorcompleted)