T05 · Unauthorized Access and Privilege Escalation
- Location
loomlens-openclaw-plugin.ts:137- Finding
Unauthenticated and Persistent Model Override
- Content
View full analysis
{ // event.context contains: sessionKey, messages, preferredModel, modelHint, cfg // If loomlens has a model override pending for this session, apply it here. const override = await getPendingModelOverride(event.context.sessionKey); if (override) { event.model = override; } return event; }; ``` ```ts const pendingOverrides = new Map(); async function setPendingModelOverride(sessionKey: string, modelId: string): Promise { pendingOverrides.set(sessionKey, modelId); } async function getPendingModelOverride(sessionKey: string): Promise { return pendingOverrides.get(sessionKey); } ``` ```ts api.registerRoute('POST', '/loomlens/override', async (req, res) => { const { sessionKey, modelId } = req.body ?? {}; if (!sessionKey || !modelId) { res.status(400).json({ error: 'sessionKey and modelId required' }); return; } await setPendingModelOverride(sessionKey, modelId); res.json({ ok: true, modelId }); }); ``` ### Technical Analysis The model-override endpoint accepts a caller-supplied session key and model identifier without performing authentication or verifying that the caller owns the specified session. The supplied model identifier is not validated against an approved model registry. The override is subsequently trusted by the `before_model_resolve` hook and assigned directly to `event.model`. Although the documented behavior describes an override for the next prompt, `getPendingModelOverride` does not remove the value after use. There is also no expiry timer for overrides. Consequently, a successfully planted override remains active for subsequen ...[truncated 1708 chars]- Remediation
View remediation
