507e1385a6
Every IconSelect caller was audited: each builds item.icon from a constant ICON_* literal, a lookup-table getter, or renderDeviceIcon(stored_id) — none of which embed user input today. The new sanitiseIcon() helper is the belt-and-braces guard for a future caller that forgets the trusted-SVG contract: reject icon strings containing <script>/<iframe>/<embed>/<object>/javascript:/on*= markers, warn to the console, and fall back to empty so the cell still renders the (escaped) label + desc.