()
| 10165 | </tr>`; |
| 10166 | }).join('') + |
| 10167 | '</tbody></table>'; |
| 10168 | } |
| 10169 | if (d.reasons && d.reasons.length) { |
| 10170 | html += '<ul class="text-xs text-gray-400 mt-2 list-disc pl-5">' + |
| 10171 | d.reasons.map(r => '<li>' + escapeHtml(r) + '</li>').join('') + '</ul>'; |
| 10172 | } |
| 10173 | (d.advisories || []).forEach(a => { |
| 10174 | html += `<div class="mt-2 px-3 py-2 rounded border text-xs text-gray-400 border-slate-700 bg-slate-900/40">${escapeHtml(a)}</div>`; |
| 10175 | }); |
| 10176 | out.innerHTML = html; |
| 10177 | } catch (e) { |
| 10178 | out.innerHTML = '<p class="text-sm text-red-400">Failed: ' + escapeHtml(e.message) + '</p>'; |
| 10179 | } finally { |
| 10180 | _ndBusy(btn, false); |
| 10181 | } |
| 10182 | } |
| 10183 | async function vtpTrustBaseline() { |
| 10184 | try { |
| 10185 | await postAPI('/api/net/vtp-baseline', { action: 'reset' }); |
| 10186 | addConsoleMessage('VTP baseline reset — re-learning current domain / revision / server', 'info'); |
| 10187 | await runVtpWatch(); |
| 10188 | } catch (e) { |
| 10189 | addConsoleMessage('Failed to reset VTP baseline: ' + e.message, 'error'); |
| 10190 | } |
| 10191 | } |
| 10192 | |
| 10193 | // ---- IS-IS Watch (passive IGP routing-security scanner) -------------------- |
| 10194 | const _ISIS_VERDICT_STYLE = { |
| 10195 | clean: ['bg-green-950/40 border-green-900 text-green-400', '✓ No IS-IS anomalies detected'], |
| 10196 | 'weak-auth': ['bg-amber-950/50 border-amber-800 text-amber-300', '⚠ IS-IS without HMAC auth (or cleartext) — exposed to LSP injection'], |
| 10197 | anomaly: ['bg-amber-950/50 border-amber-800 text-amber-300', '⚠ IS-IS anomaly — duplicate system-id / new area'], |
| 10198 | storm: ['bg-red-950/60 border-red-800 text-red-300', '🛑 IS-IS flooding storm detected'], |
| 10199 | 'rogue-router': ['bg-red-950/60 border-red-800 text-red-300', '🛑 Rogue IS-IS speaker — adjacency spoofing'], |
| 10200 | injection: ['bg-red-950/60 border-red-800 text-red-300', '🛑 IS-IS LSP / prefix injection detected'], |
| 10201 | unknown: ['bg-slate-800 border-slate-700 text-slate-400', '— Could not determine'], |
| 10202 | }; |
| 10203 | function _isisFillIfaces() { |
| 10204 | const sel = document.getElementById('isis-iface'); |
| 10205 | if (!sel || sel.dataset.filled === '1') return Promise.resolve(); |
| 10206 | return fetchAPI('/api/net/interfaces').then(x => { |
| 10207 | (x.interfaces || []).forEach(i => { |
nothing calls this directly
no test coverage detected