T09 · Insecure Skill Coding Practices
- Location
miro-push.mjs:372- Finding
Destructive replacement occurs before validation of the new diagram
- Content
View full analysis
Vulnerability Details
File Location:
miro-push.mjs, lines 372-405
Vulnerability Type: Destructive operation ordering and insufficient input validation
Risk Level: MediumVulnerable 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
applyoperation validates only thatmeta.sessionKeyis nonempty before invokingundo. 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
View remediation
Remediation Suggestions
- 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.
- Create and verify the replacement run before deleting the previous run whenever Miro semantics permit it.
- If delete-first replacement is unavoidable, retain the complete prior source document and implement a tested restoration transaction.
- Do not silently suppress deletion errors. Collect failures, retain affected IDs in state, and report that the undo was incomplete.
- Clear
lastRunonly after every required deletion succeeds. Otherwise preserve unresolved IDs for retry. - Consider binding each state session to the configured board ID so that state cannot accidentally be reused against another board.
- Define and enforce a strict JSON schema before performing any network-side deletion:
