Fix CSP blocking eval in TTYD and add debug logging - #7
Conversation
- Add 'unsafe-eval' to script-src CSP directive in all 3 locations (server.py, ttyd_proxy.py login page, ttyd_proxy.py dashboard) to fix TTYD JavaScript that requires eval() - Add [ttyd] prefixed console.log debug output for terminal create/list/delete operations to diagnose issues in browser Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
@claude review. Focus on critical issues: bugs, security vulnerabilities, logical errors, data loss risks, performance problems. Do NOT nitpick style, naming conventions, minor formatting, or subjective preferences — only flag issues that could break functionality or cause real harm in production. |
|
Claude finished @axisrow's task in 2m 43s —— View job Code Review
1.
|
| Issue | File | Severity |
|---|---|---|
'unsafe-eval' added to login page CSP |
ttyd_proxy.py:611 |
High |
| Fix may target wrong CSP (TTYD runs in iframe with its own headers) | ttyd_proxy.py:1266 |
High |
| Permanent debug logging leaks terminal data | app/index.html |
Medium |
TriageComment 1 — unsafe-eval on login pageVerdict: FIX. Correct — login page doesn't need eval. Will remove. Comment 1b — CSP fix targets wrong locationVerdict: FIX. Correct — TTYD content is served through proxy_ttyd_http which passes TTYD's own headers. Need to override/add CSP with unsafe-eval in proxy_ttyd_http for HTML responses. Comment 2 — Permanent debug loggingVerdict: SKIP. User explicitly requested debug logging in browser console to diagnose terminal creation bug. Will gate behind a DEBUG flag as suggested. |
- Remove 'unsafe-eval' from login page CSP (security regression) - Add CSP override in proxy_ttyd_http for HTML responses from TTYD (strips upstream CSP, adds one with 'unsafe-eval' for TTYD's JS) - Gate debug logging behind DEBUG flag Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
@claude review. Focus on critical issues: bugs, security vulnerabilities, logical errors, data loss risks, performance problems. Do NOT nitpick style, naming conventions, minor formatting, or subjective preferences — only flag issues that could break functionality or cause real harm in production. |
|
Claude finished @axisrow's task in 1m 59s —— View job Code Review
1.
|
| Issue | File | Severity |
|---|---|---|
DEBUG = true hardcoded — terminal data always logged |
app/index.html |
Medium |
TTYD proxy CSP missing frame-ancestors 'self' |
ttyd_proxy.py:1292 |
Medium |
unsafe-eval added to pages that don't need it |
server.py:44, ttyd_proxy.py:879 |
Low |
The CSP fix for TTYD (stripping upstream CSP and injecting a custom one in proxy_ttyd_http) is the right approach and correctly placed.
- Set DEBUG=false (was true) - Remove unsafe-eval from server.py and dashboard CSP (not needed) - Add frame-ancestors 'self' to TTYD proxy CSP (anti-clickjacking) - unsafe-eval now only in proxy_ttyd_http for TTYD HTML responses Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
@claude review. Focus on critical issues: bugs, security vulnerabilities, logical errors, data loss risks, performance problems. Do NOT nitpick style, naming conventions, minor formatting, or subjective preferences — only flag issues that could break functionality or cause real harm in production. |
|
Claude finished @axisrow's task in 1m 22s —— View job Code Review
All critical issues identified in previous review cycles have been resolved. Current state looks clean:
No new critical issues found. The implementation is correct:
Approved — no blocking issues. |
…ries (P2) Six P2 refactoring-debt fixes from the #101 code review, plus NOTE comments for the deferred TOCTOU finding (#8). processes were only reaped lazily inside list_terminals()/get_terminal(), so with no list/get/health traffic a defunct zombie pinned its PID slot forever. The reaper polls periodically (start/stop wired into main + signal handler). of the string-interpolating run_as_hapi (`sh -c "... ${command}"`) — a latent root-context command-injection surface. `| tee` is replaced with a redirect (argv can't express a pipe, matching the tunnel helpers) and inline env vars go through `env NAME=VAL`. The unused string run_as_hapi is removed. ttydproxy.views.build_hapi_url_from_runtime the dashboard uses, replacing a drifted bash reimplementation (bash took the FIRST relay URL + left the token un-encoded; views takes the LAST + quote()s both). skip-set, and read resp.getheaders() once (was called twice per response). A keep-alive connection pool was intentionally NOT added — a shared HTTPConnection across ThreadingHTTPServer worker threads would introduce a concurrency bug. tab_fix_script and delegate to them from the parent page + virtual keyboard, removing byte-identical containsFiles copies and three hard-coded socket- discovery + '0' ttyd-prefix sites (protocol change now lives in one place). ao git-fetch + Hermes git-clone/pip network steps in the CLAUDE.md retry loop (`for i in 1 2 3 4 5; ... && break || sleep 10`), previously applied only to npm. (narrow window, not a security boundary) and point at a per-terminal lease as the proper fix, tracked separately. No new env vars. No port or volume changes. Closes #101 findings #7, #9, #12, #13, #14, #15 (documents deferred #8). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KgvJhzd8gEhXVE4MVu18nn
…ries (#101 P2) (#104) * refactor: ttyd reaper, argv daemon launch, url dedup, keep-alive, retries (P2) Six P2 refactoring-debt fixes from the #101 code review, plus NOTE comments for the deferred TOCTOU finding (#8). processes were only reaped lazily inside list_terminals()/get_terminal(), so with no list/get/health traffic a defunct zombie pinned its PID slot forever. The reaper polls periodically (start/stop wired into main + signal handler). of the string-interpolating run_as_hapi (`sh -c "... ${command}"`) — a latent root-context command-injection surface. `| tee` is replaced with a redirect (argv can't express a pipe, matching the tunnel helpers) and inline env vars go through `env NAME=VAL`. The unused string run_as_hapi is removed. ttydproxy.views.build_hapi_url_from_runtime the dashboard uses, replacing a drifted bash reimplementation (bash took the FIRST relay URL + left the token un-encoded; views takes the LAST + quote()s both). skip-set, and read resp.getheaders() once (was called twice per response). A keep-alive connection pool was intentionally NOT added — a shared HTTPConnection across ThreadingHTTPServer worker threads would introduce a concurrency bug. tab_fix_script and delegate to them from the parent page + virtual keyboard, removing byte-identical containsFiles copies and three hard-coded socket- discovery + '0' ttyd-prefix sites (protocol change now lives in one place). ao git-fetch + Hermes git-clone/pip network steps in the CLAUDE.md retry loop (`for i in 1 2 3 4 5; ... && break || sleep 10`), previously applied only to npm. (narrow window, not a security boundary) and point at a per-terminal lease as the proper fix, tracked separately. No new env vars. No port or volume changes. Closes #101 findings #7, #9, #12, #13, #14, #15 (documents deferred #8). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KgvJhzd8gEhXVE4MVu18nn * fix: truncate daemon logs at startup instead of touch (review cleanup) Non-blocking finding from the local review of #104: the argv refactor changed the daemon launches from `| tee "$LOG"` (which truncates the log on open) to `>>"$LOG"` (append). Without a matching truncate, server.log / droid /ao logs on the persistent /home/hapi volume would keep stale content across restarts — for server.log that means a brief window where the /home/hapi/url fallback pairs a fresh token with an old relay URL (the live dashboard builder self-heals, but the fallback file can go stale) — and grow unbounded. Replace `touch "$LOG"` with `: > "$LOG"` (truncate-or-create) for the three daemon logs, restoring the old tee truncate-at-startup semantics. Update the server-log pre-create test accordingly. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KgvJhzd8gEhXVE4MVu18nn --------- Co-authored-by: axisrow <axisrow@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Summary
'unsafe-eval'toscript-srcCSP directive in all 3 locations to fix TTYD JavaScript that requireseval()[ttyd]prefixedconsole.logdebug output for terminal create/list/delete operationsTest plan
python -m pytest tests/— 129 tests pass[ttyd]debug logs showing each step🤖 Generated with Claude Code