index.html
Rama main · réplica de lectura del repositorio original.
<!doctype html>
<html lang="">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.svg" />
<link rel="apple-touch-icon" href="/apple-touch-icon.svg" />
<link rel="canonical" href="https://gupt.app" />
<!--
Canonical Content-Security-Policy. Keep in sync with the header emitted by
Caddyfile (Docker) and bin/gupt.js (npx) — that copy is the one that can
carry frame-ancestors, which a <meta> policy silently ignores.
script-src is 'self' with no unsafe-* escape hatches: the build emits no
inline script, no inline on*= handlers and no eval()/new Function(), so a
strict policy costs nothing and blocks injected script outright.
style-src keeps 'unsafe-inline' because Vue compiles :style bindings and
static style="" attributes into inline styles; inline CSS cannot execute
script, so this is the one permissive entry that is not worth fighting.
connect-src stays open to ws:/wss:/http:/https: on purpose — reaching
arbitrary relays and gateways is what a federated messenger does.
frame-src / worker-src / manifest-src are stated explicitly even though
every one of them currently resolves to 'self' via default-src. They are
here to be read, not to widen the policy: a directive nobody wrote down is
a directive nobody notices when default-src is next edited. Same-origin
frames and workers stay allowed so a future sandboxed PDF page or a
worker-backed decoder is a one-token change made deliberately.
There is deliberately no third-party frame source, and that is a privacy
decision rather than an omission. GUPT's location messages render
coordinates as text and leave the OpenStreetMap link inert until tapped,
because an <iframe> map would hand the reader's IP and their interest in
that coordinate to a tile server the moment the message scrolled into
view. Adding an embed here would quietly undo that.
A PDF viewer would need two separate decisions, not one: worker-src blob:
if the decoder ships a blob-backed worker, and frame-src blob: only if it
renders inline via <iframe src="blob:">. object-src 'none' already blocks
the <object>/<embed> plugin path, which is the one worth keeping closed.
-->
<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: http: https:; media-src 'self' blob: data: http: https:; font-src 'self' data:; object-src 'none'; base-uri 'none'; form-action 'none'; frame-src 'self'; worker-src 'self'; manifest-src 'self'"
/>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="application-name" content="GUPT" />
<meta name="apple-mobile-web-app-title" content="GUPT" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
<meta name="theme-color" content="#09090b" />
<meta
name="description"
content="GUPT is an anonymous privacy suite — encrypted messaging, passwords, notes, bookmarks, and ephemeral file sharing — with no phone number, no account, and no server. Built on Nostr."
/>
<meta property="og:type" content="website" />
<meta property="og:title" content="GUPT" />
<meta property="og:url" content="https://gupt.app" />
<meta
property="og:description"
content="GUPT is an anonymous privacy suite — encrypted messaging, passwords, notes, bookmarks, and ephemeral file sharing — with no phone number, no account, and no server. Built on Nostr."
/>
<meta property="og:image" content="https://gupt.app/social-banner.png" />
<meta property="og:image:type" content="image/png" />
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />
<meta
property="og:image:alt"
content="GUPT social banner featuring the app mark, end-to-end encrypted messaging features, and interactive chat interface."
/>
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="GUPT" />
<meta
name="twitter:description"
content="GUPT is an anonymous privacy suite — encrypted messaging, passwords, notes, bookmarks, and ephemeral file sharing — with no phone number, no account, and no server."
/>
<meta name="twitter:image" content="https://gupt.app/social-banner.png" />
<meta
name="twitter:image:alt"
content="GUPT social banner featuring the app mark, end-to-end encrypted messaging features, and interactive chat interface."
/>
<title>GUPT — Anonymous Privacy Suite</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>