You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix: [AI-194] pre-release security and resource cleanup fixes for tracing (#197)
* fix: [AI-194] pre-release security and resource cleanup fixes for tracing
- Escape `t.summary.status` with `e()` in trace viewer HTML to prevent XSS
- Add SIGINT/SIGTERM handlers to gracefully stop trace viewer server on Ctrl+C
- Log snapshot write failures with `console.debug` instead of silently swallowing
Closes#194
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: comprehensive XSS hardening for trace viewer HTML
Systematically escape all user-controllable fields in `viewer.ts`:
- Escape `span.kind` and `span.status` in detail panel, waterfall, tree, and log views
- Escape `span.spanId` in `data-sid` attributes
- Coerce all numeric fields with `Number()` to prevent string injection via `.toLocaleString()`
- Add single-quote escaping (`'`) to the `e()` function for defense-in-depth
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: await `server.stop()` for graceful shutdown in trace viewer
`Bun.Server.stop()` returns a `Promise<void>` — calling it without
`await` exits the process before in-flight requests are drained.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: catch `server.stop()` rejection in shutdown handler
Prevents unhandled promise rejection if the server fails to stop
cleanly on SIGINT/SIGTERM.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
var e = function(s) { if (s == null) return ''; return String(s).replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>').replace(/"/g,'"'); };
186
+
var e = function(s) { if (s == null) return ''; return String(s).replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>').replace(/"/g,'"').replace(/'/g,'''); };
187
187
var fd = function(ms) { if (!ms && ms !== 0) return '-'; ms = Math.abs(ms); if (ms < 1000) return ms + 'ms'; if (ms < 60000) return (ms/1000).toFixed(1) + 's'; return Math.floor(ms/60000) + 'm' + Math.floor((ms%60000)/1000) + 's'; };
188
188
var fc = function(c) { if (c == null || isNaN(c)) return '$0'; return c < 0.01 ? '$' + c.toFixed(4) : '$' + c.toFixed(2); };
189
189
var fb = function(b) { if (!b) return '0 B'; if (b < 1024) return b + ' B'; if (b < 1048576) return (b/1024).toFixed(1) + ' KB'; if (b < 1073741824) return (b/1048576).toFixed(1) + ' MB'; return (b/1073741824).toFixed(2) + ' GB'; };
0 commit comments