bitspire/apps/machine/index.html
Patrick Mulligan 1ac50b6add security(H1): add Content Security Policy
Add CSP in two layers:
1. Meta tag in index.html (works for all builds)
2. HTTP header via Electron session API (defense-in-depth)

Policy: script-src 'self' blocks XSS from loading external scripts
or executing inline scripts. style-src allows 'unsafe-inline' for
Vue's style injection. connect-src allows ws/wss/http/https for
configurable relay and API endpoints.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 09:36:59 -05:00

50 lines
1.7 KiB
HTML

<!doctype html>
<html lang="en" class="dark">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no" />
<!--
Content Security Policy:
- script-src 'self': only our own bundled scripts, no inline/eval (XSS protection)
- style-src 'self' 'unsafe-inline': Vue injects styles inline
- connect-src: WebSocket for Nostr relay, HTTPS for Lightning.Pub and exchange rate APIs
- img-src 'self' data: blob:: QR codes use data URIs
- default-src 'self': deny everything not explicitly allowed
- frame-src 'none': no iframes
- object-src 'none': no plugins
-->
<meta
http-equiv="Content-Security-Policy"
content="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; connect-src 'self' ws: wss: http: https:; img-src 'self' data: blob:; font-src 'self'; frame-src 'none'; object-src 'none'"
/>
<title>Lamassu ATM</title>
<style>
/* Prevent text selection and context menu on kiosk */
* {
user-select: none;
-webkit-user-select: none;
touch-action: manipulation;
-webkit-tap-highlight-color: transparent;
}
html,
body {
margin: 0;
padding: 0;
background: #000;
}
/* Kiosk-only: lock overflow and hide cursor */
@media (min-width: 1024px) {
html,
body {
overflow: hidden;
cursor: none;
}
}
</style>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>