T09 · Insecure Skill Coding Practices
- Location
references/moci.ts:345- Finding
Unsigned Caller Tokens Allow Unauthorized Memory Writes
- Content
View full analysis
300_000) throw new Error("Expired"); return p as CallerToken; } catch { throw new Error("Invalid caller token"); } } // --- Memory Write (FIX #14, #12) --- interface WriteResult { success: boolean; seq?: number; error?: string; } async function addMemory( identity: MociIdentity, content: string, source: string, callerToken: string, hmacKey: string ): Promise { let caller: CallerToken; try { caller = verifyCallerToken(callerToken); } catch (e) { return { success: false, error: `Auth: ${(e as Error).message}` }; } if (!ALLOWED_WRITERS.includes(caller.callerId)) return { success: false, error: `Writer not allowed: ${caller.callerId}` }; ``` ### Technical Analysis `verifyCallerToken()` only Base64-decodes and parses caller-controlled JSON. It does not verify a digital signature, message authentication code, trusted issuer, audience, or single-use nonce. Consequently, the `callerId` used by the writer allowlist is not authenticated. A caller can select an authorized value such as `gateway`, `heartbeat`, or `skill:moci`. The timestamp check is also incomplete: a future `issuedAt` value produces a negative age and remains valid because only tokens older than five minutes are rejected. This directly contradicts the authenticated write-gate described in `references/memory-security.md`. Base64 is an encoding format and provides no authenticity or integrity. ### Attack Path 1. The attacker constructs a JSON object such as: ```json { "callerId": "skill:moci", "issuedAt": 4102444800000, "nonce": "attacker-controlled" ...[truncated 1076 chars]- Remediation
View remediation
