Go Code Review: Dashboard Security Audit
Find/use a Go code review skill to audit dashboard code. Focus on security: auth, token handling, input validation, WebSocket proxy. Add findings as sub-tasks.
Finish Gmail and Calendar setup
MEDIUM: WebSocket Missing Origin Validation (CSWSH)
## Summary The WebSocket endpoint does not validate the Origin header, making it vulnerable to Cross-Site WebSocket Hijacking (CSWSH). ## Attack Scenario 1. Victim is authenticated to the dashboard 2. Victim visits malicious site (attacker.com) 3. Attacker's JavaScript opens WebSocket to dashboard: ```javascript new WebSocket('wss://dashboard.victim.com/ws') ``` 4. Browser sends cookies/credentials automatically 5. Attacker can send/receive messages through victim's session ## Affected Code ```go http.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) { if r.Header.Get("Upgrade") != "websocket" { http.Error(w, "Expected websocket", http.StatusBadRequest) return } // No Origin check! proxyWebSocket(w, r, "127.0.0.1:18789") }) ``` ## Impact - **Severity: MEDIUM** - Cross-site request forgery for WebSocket connections - Attacker can interact with gateway as victim (once other auth issues are fixed) ## Affected File dashboard/main.go lines 24-30 ## Recommended Fix ```go http.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) { // Validate Origin origin := r.Header.Get("Origin") allowedOrigins := []string{ "https://yourdomain.com", "http://localhost:8081", // Dev only } valid := false for _, allowed := range allowedOrigins { if origin == allowed { valid = true break } } if !valid { http.Error(w, "Invalid origin", http.StatusForbidden) return } // ... proceed with WebSocket upgrade }) ``` ## References - Parent: maximo-bb1 - OWASP: https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/11-Client-side_Testing/10-Testing_WebSockets
LOW: No Rate Limiting on WebSocket Connections
## Summary The dashboard has no rate limiting on WebSocket connections or chat messages, making it vulnerable to denial-of-service attacks. ## Impact - **Severity: LOW** (mitigated by authentication issues being fixed first) - Attacker could open many WebSocket connections exhausting server resources - Could flood the gateway with messages - No backpressure mechanism for rapid message sending ## Affected Files - dashboard/main.go - no connection rate limiting - dashboard/static/chat.html - no client-side throttling ## Recommended Fix 1. Add connection rate limiting per IP: ```go import "golang.org/x/time/rate" var limiter = rate.NewLimiter(rate.Limit(10), 20) // 10 req/sec, burst 20 http.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) { if !limiter.Allow() { http.Error(w, "Too many requests", http.StatusTooManyRequests) return } // ... rest of handler }) ``` 2. Add per-user rate limiting after authentication 3. Consider connection pooling limits per user ## References - Parent: maximo-bb1
Build custom chat UI for dashboard
Build a custom chat interface that matches the dashboard aesthetic. Should connect to Clawdbot WebSocket API directly, support streaming responses, message history, and use the same dark purple theme as the rest of the dashboard.
Set up audio transcription (Whisper)
Unified dashboard at cabewaldrop.com
Single auth landing page with links to kanban, metrics, vnc
Install Chrome/Chromium browser
Install chromium-browser for headless automation
Install Xvfb and virtual display dependencies
apt install xvfb x11vnc and related packages
Headless browser for shopping automation
Set up always-on Chrome with Xvfb + noVNC for Amazon cart automation from anywhere
Build oura-sync Go module
Standalone module to fetch Oura API data and write to InfluxDB. Path: /root/clawd/oura-sync
Set up InfluxDB and Grafana
Install InfluxDB 2.7, Grafana 12.3, configure datasources
Oura Ring + Grafana health metrics integration
Health data visualization stack: InfluxDB + Grafana + oura-sync collector
Integrate Clerk for Google social login
Replace basic auth with Clerk. Use Google social login. Free tier should be sufficient.
Separate backlog section below Kanban board
Top 3 backlog items show in Next column, rest displayed in horizontal rows below the board
Make Kanban board responsive for mobile
Desktop looks good, but columns are smashed on mobile. Need to stack columns vertically or make horizontally scrollable.
Phase 2: Basic Kanban UI
HTML/CSS Kanban board layout with columns (Next, In Progress, In Review, Done). Display tasks from API. Go templates + HTMX for interactivity.
Phase 1: Project setup & Go backend skeleton
Set up Go project structure (Chi router), define data models, create API to read Beads issues, basic project layout
Beads Kanban Board - Epic
Full-stack Go Kanban board on top of Beads. Sprint view with statuses: Next, In Progress, In Review, Done. Plus backlog. Web-hosted with auth.
LOW: Missing Security Headers
## Summary The dashboard server does not set standard security headers, leaving it more vulnerable to various client-side attacks. ## Missing Headers - `Content-Security-Policy`: No CSP to prevent XSS and data injection - `X-Content-Type-Options: nosniff`: Browser could MIME-sniff responses - `X-Frame-Options: DENY`: Clickjacking possible - `Strict-Transport-Security`: No HSTS enforcement - `X-XSS-Protection: 1; mode=block`: Legacy XSS protection not enabled ## Impact - **Severity: LOW** - Increases attack surface for XSS (no CSP) - Clickjacking attacks possible (no frame options) - Mixed content possible if HSTS not set ## Affected File dashboard/main.go - no security headers set on any response ## Recommended Fix Add middleware to set security headers: ```go func securityHeaders(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("X-Content-Type-Options", "nosniff") w.Header().Set("X-Frame-Options", "DENY") w.Header().Set("X-XSS-Protection", "1; mode=block") w.Header().Set("Strict-Transport-Security", "max-age=31536000; includeSubDomains") w.Header().Set("Content-Security-Policy", "default-src 'self'; script-src 'self' 'unsafe-inline' cdn.jsdelivr.net; style-src 'self' 'unsafe-inline' fonts.googleapis.com; font-src fonts.gstatic.com") next.ServeHTTP(w, r) }) } // In main(): http.ListenAndServe(":8081", securityHeaders(http.DefaultServeMux)) ``` ## References - Parent: maximo-bb1
MEDIUM: Chat Page Missing Clerk Authentication Integration
## Summary The chat.html page does not integrate with Clerk authentication at all. While the main dashboard verifies Clerk login before showing content, chat.html is accessible without any auth check. ## Affected Code The entire chat.html page has no Clerk integration: - No Clerk SDK import - No authentication check before rendering - No redirect to login if unauthenticated Compare to main page which has: ```javascript await window.Clerk.load(); if (window.Clerk.user) { // show app } else { // show login } ``` ## Impact - **Severity: MEDIUM** - Direct URL access to /chat/ bypasses dashboard authentication - Combined with the hardcoded gateway token, this allows completely unauthenticated access ## Affected File dashboard/static/chat.html (entire file) ## Recommended Fix 1. Add Clerk SDK to chat.html 2. Check authentication status before showing chat UI 3. Redirect to login if not authenticated: ```javascript // Add to chat.html <script async crossorigin="anonymous" data-clerk-publishable-key="..." src="https://cdn.jsdelivr.net/npm/@clerk/clerk-js@latest/dist/clerk.browser.js"></script> // In script section: await window.Clerk.load(); if (!window.Clerk.user) { window.location.href = '/'; return; } ``` ## References - Parent: maximo-bb1
HIGH: XSS Vulnerability in Chat Message Rendering
## Summary The formatMessage() function in chat.html performs markdown-to-HTML conversion but does not sanitize input first. User content is inserted via innerHTML, enabling XSS attacks. ## Affected Code ```javascript function formatMessage(text) { if (!text) return ''; return text .replace(/\`\`\`(\w*)\n?([\s\S]*?)\`\`\`/g, '<pre><code>$2</code></pre>') .replace(/\`([^\`]+)\`/g, '<code>$1</code>') .replace(/\*\*([^*]+)\*\*/g, '<strong>$1</strong>') .replace(/\*([^*]+)\*/g, '<em>$1</em>') .replace(/\n/g, '<br>'); } // Then used as: msg.innerHTML = \`...${formatMessage(content)}...\`; ``` ## Impact - **Severity: HIGH** - Malicious content like `<script>alert('xss')</script>` bypasses the regex filters - Both user messages AND assistant responses are vulnerable - Attacker could steal session tokens, perform actions as user - If assistant response contains malicious content (prompt injection), it executes ## Affected File dashboard/static/chat.html lines 329-338, 348 ## Recommended Fix 1. Escape HTML entities BEFORE markdown processing: ```javascript function escapeHtml(text) { const div = document.createElement('div'); div.textContent = text; return div.innerHTML; } function formatMessage(text) { if (!text) return ''; text = escapeHtml(text); // Escape first! // Then apply markdown transforms ... } ``` 2. Or use a proper markdown library with built-in XSS protection (e.g., marked.js with sanitize option, DOMPurify) ## References - Parent: maximo-bb1
CRITICAL: Hardcoded Gateway Token Exposed in Client-Side JavaScript
## Summary The gateway authentication token is hardcoded directly in static/chat.html: ```javascript const GATEWAY_TOKEN = 'b7f6284bd7cc21b388679c8e269af10d212ef39f3ebec4ab'; ``` ## Impact - **Severity: CRITICAL** - Anyone who views the page source can steal this token - Token provides direct access to the Clawdbot gateway - Could allow unauthorized command execution on the system ## Affected File dashboard/static/chat.html line 280 ## Recommended Fix 1. Remove token from client-side code entirely 2. Implement server-side session management: - User authenticates via Clerk - Server validates Clerk JWT and issues a short-lived session token - Store session server-side with user binding 3. Or proxy all gateway communication through authenticated server endpoints ## References - Parent: maximo-bb1
Spotify Integration Research
Research Spotify API for playlist creation. Goal: create personalized morning playlists based on user's liked songs. Document OAuth flow, required scopes, API endpoints.
Ubuntu Server Hardening & Automation
Research Ubuntu server best practices: unattended upgrades, fail2ban, UFW firewall rules, SSH hardening, log rotation, monitoring. Automate with scripts/ansible.
Implement secure chat token endpoint
Replace hardcoded GATEWAY_TOKEN in chat.html with authenticated /api/chat-token endpoint. Verify Clerk session before returning token.
Test Amazon add-to-cart flow
Verify full flow: search product, add to cart, confirm
Configure Clawdbot browser tool for local Chrome
Point browser tool at the local Chrome instance
Create systemd service for persistent browser
Keep Chrome running in Xvfb, auto-restart on crash
Set up noVNC for browser-based access
Web-based VNC viewer so Cabe can log into Amazon from anywhere
SSL for metrics.cabewaldrop.com
Add DNS record, run certbot for SSL
Create Oura Grafana dashboard
Dashboard with sleep/readiness/activity gauges, time series, steps, temperature deviation
Add due dates to tasks
Support due date field and display
Test task from UI
Testing the create task API
Phase 5: Authentication
Login system, session management, protect routes. Start simple (single user or basic auth).
Phase 4: Sprint management
Create/manage sprints, assign tasks to sprints, backlog view, sprint selector.
Phase 3: Drag-and-drop & status updates
Add drag-drop to move tasks between columns. Update Beads status via API. Use Sortable.js or similar.
Export board to CSV
Allow exporting all tasks to CSV format
Email notification when task assigned
Send email when a task is assigned to someone
Implement task comments
Allow adding comments to tasks
Add dark mode to Kanban board
Support dark/light theme toggle
Write documentation for API endpoints
Document all the Kanban API endpoints
Research competitor pricing models
Look at how similar tools price their services
Phase 6: Polish & deployment
Styling polish, deployment config, systemd service, reverse proxy setup.
MEDIUM: WebSocket Proxy Forwards All Headers Without Sanitization
## Summary The proxyWebSocket function forwards the entire HTTP request (including all headers) to the backend without sanitization. ## Affected Code ```go // Forward the WebSocket upgrade request r.Write(backendConn) ``` ## Impact - **Severity: MEDIUM** - All client headers are forwarded verbatim to the gateway - Potential header injection if client controls header values - Could allow spoofing of X-Forwarded-For, X-Real-IP, or custom auth headers - May pass through malicious headers that the backend trusts from 'internal' sources ## Affected File dashboard/main.go line 106 ## Recommended Fix 1. Create a sanitized copy of the request with only necessary headers: ```go // Create clean request for backend newReq, _ := http.NewRequest("GET", "/ws", nil) newReq.Header.Set("Upgrade", "websocket") newReq.Header.Set("Connection", "Upgrade") newReq.Header.Set("Sec-WebSocket-Key", r.Header.Get("Sec-WebSocket-Key")) newReq.Header.Set("Sec-WebSocket-Version", r.Header.Get("Sec-WebSocket-Version")) // Add verified client info newReq.Header.Set("X-Forwarded-For", getClientIP(r)) newReq.Write(backendConn) ``` 2. Explicitly blocklist sensitive headers: Authorization, Cookie, X-* (unless allowed) ## References - Parent: maximo-bb1
MEDIUM: Hardcoded Session Key Allows Session Hijacking
## Summary The chat interface uses a hardcoded session key for all users, meaning everyone shares the same chat session. ## Affected Code ```javascript const SESSION_KEY = 'agent:main:main'; ``` ## Impact - **Severity: MEDIUM** - All authenticated users share the same conversation history - One user can see another user's messages - Privacy violation - chat content is not isolated per user ## Affected File dashboard/static/chat.html line 281 ## Recommended Fix 1. Generate unique session keys per authenticated user 2. Include user ID in session key: `agent:main:${userId}` 3. Derive session from Clerk user identity after authentication ```javascript // After Clerk auth: const SESSION_KEY = \`agent:main:user:${window.Clerk.user.id}\`; ``` ## References - Parent: maximo-bb1
MEDIUM: Error Handling Leaks Internal Details
## Summary The proxyWebSocket function exposes internal error details to clients, which could aid attackers in reconnaissance. ## Affected Code ```go clientConn, _, err := hijacker.Hijack() if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) // Leaks error backendConn.Close() return } ``` ## Impact - **Severity: MEDIUM** - Error messages may reveal internal paths, network topology, or implementation details - Aids attackers in understanding the system for further exploitation ## Affected File dashboard/main.go line 102 ## Recommended Fix Replace with generic error message: ```go if err != nil { log.Printf("Hijack failed: %v", err) // Log internally http.Error(w, "Connection upgrade failed", http.StatusInternalServerError) // Generic to client backendConn.Close() return } ``` ## References - Parent: maximo-bb1
HIGH: WebSocket Proxy Lacks Authentication
## Summary The /ws endpoint in main.go proxies WebSocket connections to the gateway without any authentication verification. Anyone who can reach the server can establish a WebSocket connection. ## Affected Code ```go http.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) { if r.Header.Get("Upgrade") != "websocket" { http.Error(w, "Expected websocket", http.StatusBadRequest) return } proxyWebSocket(w, r, "127.0.0.1:18789") }) ``` ## Impact - **Severity: HIGH** - No Clerk token verification before proxying - No session validation - Bypasses all authentication - the frontend Clerk auth is purely cosmetic - Combined with the hardcoded token in chat.html, this is a complete auth bypass ## Affected File dashboard/main.go lines 24-30 ## Recommended Fix 1. Add middleware to verify Clerk JWT on /ws endpoint 2. Validate user session before allowing WebSocket upgrade 3. Example flow: - Client includes Clerk session token in WS handshake (header or query param) - Server validates token with Clerk SDK - Only then proxy the connection ## References - Parent: maximo-bb1
Generate chat UI icon with Gemini
Use nano banana (Gemini image gen) to create a custom chat icon that matches the dashboard aesthetic
Configure heartbeat checks
Set up periodic checks for email, calendar, etc.