T05 · Unauthorized Access and Privilege Escalation
Error
- Location
- src/queue.js:65
- Finding
- Missing Agent Authentication and Task-Level Authorization<![CDATA[ ## Vulnerability Details **File Location**: `src/cli.js:67-108`; `src/queue.js:65-103`; `src/queue.js:107-188` **Vulnerability Type**: Missing authentication, agent impersonation, and broken task-level authorization **Risk Level**: High ### Vulnerable Code ```js task.command('claim <task-id>') .description('Claim a task') .requiredOption('--agent <name>', 'Agent name') .action((taskId, opts) => { const db = initDb(); try { const t = claimTask(db, taskId, opts.agent); if (t) console.log(`Task ${taskId} claimed by ${opts.agent}`); else console.error(`Failed to claim task ${taskId} (already taken or not pending)`); } catch (e) { console.error(e.message); } closeDb(); }); task.command('complete <task-id>') .description('Complete a task') .option('--result-path <path>', 'Path to result file') .option('--summary <text>', 'Summary of result') .action((taskId, opts) => { const db = initDb(); try { completeTask(db, taskId, { resultPath: opts.resultPath, summary: opts.summary }); console.log(`Task ${taskId} completed.`); } catch (e) { console.error(e.message); } closeDb(); }); task.command('fail <task-id>') .description('Fail a task') .option('--reason <text>', 'Reason for failure') .action((taskId, opts) => { const db = initDb(); try { failTask(db, taskId, opts.reason); console.log(`Task ${taskId} marked as failed.`); } catch (e) { console.error(e.message); } closeDb(); }); ``` ```js export function claimTask(db, taskId, agentName) { // Wrap everything in a transaction — no stale reads outside const doClaim = db.transaction(() => { const task = getTask(db, taskId); if (!task) throw new Error(`Task ${taskId} not found`); if (task.status !== 'pending') return null; // Check dependencies inside the transaction if (task.depends_on.length > 0) { const placeholders = task.depends_on.map(() => '?').join(','); co ...[truncated 4217 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Introduce authenticated principals for all state-changing operations. Do not accept a plain agent name as proof of identity. 2. Require the verified actor identity in `claimTask`, `completeTask`, `failTask`, and `retryTask`. 3. Verify that the claiming agent exists before updating the task. 4. Enforce ownership for completion and failure: ```js if (task.assigned_agent !== actor.name && !actor.isAdmin) { throw new Error('Not authorized to modify this task'); } ``` 5. Define explicit administrative permissions for cross-agent task management and retry operations. 6. Store the verified principal—not caller-supplied display text—in `handoff_log`. 7. Enforce concurrency limits inside the same claim transaction, for example with a conditional agent update that requires `current_load < max_concurrent`, and reject the claim if no agent row is updated. 8. Restrict filesystem permissions on the SQLite database so untrusted local users cannot bypass application authorization through direct database access. 9. Add tests covering nonexistent agents, impersonation attempts, cross-agent completion/failure, unauthorized retry, and concurrent limit enforcement. ]]>
