T09 · Insecure Skill Coding Practices
Warning
- Location
- miro-push.mjs:372
- Finding
- Destructive replacement occurs before validation of the new diagram## Vulnerability Details **File Location**: `miro-push.mjs`, lines 372-405 **Vulnerability Type**: Destructive operation ordering and insufficient input validation **Risk Level**: Medium ### Vulnerable Code ```js async function undo(sessionKey) { const state = loadState(); const sess = state.sessions?.[sessionKey]; if (!sess?.lastRun) { console.log(`Nothing to undo for sessionKey=${sessionKey}`); return; } for (const id of sess.lastRun.connectorIds ?? []) await deleteConnector(id).catch(() => {}); for (const id of sess.lastRun.stickyIds ?? []) await deleteSticky(id).catch(() => {}); for (const id of sess.lastRun.frameIds ?? []) await deleteFrame(id).catch(() => {}); state.sessions[sessionKey].lastRun = null; saveState(state); console.log(`Undone sessionKey=${sessionKey}`); } async function apply(jsonPath) { const doc = JSON.parse(fs.readFileSync(jsonPath, "utf-8")); const meta = doc.meta ?? {}; const sessionKey = String(meta.sessionKey ?? "").trim(); if (!sessionKey) throw new Error("meta.sessionKey is required"); const state = loadState(); state.sessions = state.sessions ?? {}; state.sessions[sessionKey] = state.sessions[sessionKey] ?? { lastRun: null }; // Idempotent run if (state.sessions[sessionKey].lastRun) await undo(sessionKey); const frames = Array.isArray(doc.frames) ? doc.frames : []; const stickies = Array.isArray(doc.stickies) ? doc.stickies : []; const connectors = Array.isArray(doc.connectors) ? doc.connectors : []; ``` ### Technical Analysis The `apply` operation validates only that `meta.sessionKey` is nonempty before invoking `undo`. The previous Miro objects are therefore deleted before the replacement document's frames, stickies, connectors, identifiers, dimensions, and API feasibility are validated. If any subsequent Miro creation request fails, the script's rollback logic can delete only the newly created objec ...[truncated 1511 chars]
- Remediation
- ## Remediation Suggestions 1. Define and enforce a strict JSON schema before performing any network-side deletion: - Require unique, nonempty frame and sticky IDs. - Validate all connector endpoints. - Validate frame references used by stickies. - Enforce finite numeric coordinates and safe dimension limits. - Enforce maximum counts and string lengths. 2. Create and verify the replacement run before deleting the previous run whenever Miro semantics permit it. 3. If delete-first replacement is unavoidable, retain the complete prior source document and implement a tested restoration transaction. 4. Do not silently suppress deletion errors. Collect failures, retain affected IDs in state, and report that the undo was incomplete. 5. Clear `lastRun` only after every required deletion succeeds. Otherwise preserve unresolved IDs for retry. 6. Consider binding each state session to the configured board ID so that state cannot accidentally be reused against another board.
