Refresh checkpoint with CSP and navigation guards
This commit is contained in:
parent
4d4dfde1de
commit
ac614072fe
1 changed files with 28 additions and 12 deletions
|
|
@ -1,4 +1,4 @@
|
||||||
# Checkpoint — Upload pick tokens (2026-08-21)
|
# Checkpoint — Header-based CSP + navigation guards (2026-08-21)
|
||||||
|
|
||||||
A stopping point you can return to if this session is closed. Everything below was
|
A stopping point you can return to if this session is closed. Everything below was
|
||||||
verified green at the moment this file was written.
|
verified green at the moment this file was written.
|
||||||
|
|
@ -6,12 +6,12 @@ verified green at the moment this file was written.
|
||||||
## Where things are
|
## Where things are
|
||||||
|
|
||||||
- Project: `/home/avi/Projects/0_Nostr`
|
- Project: `/home/avi/Projects/0_Nostr`
|
||||||
- Git repo: `master` @ `6e627a3` ("Replace upload file paths with single-use pick tokens").
|
- Git repo: `master` @ `4d4dfde` ("Enforce header-based CSP and block window open/navigation").
|
||||||
Before it: `4bde395` ("Restrict renderer IPC to an explicit method allowlist"), then
|
Before it: `6e627a3` (upload pick tokens), `4bde395` (IPC allowlist), then checkpoint
|
||||||
`dafed33` (checkpoint refresh), on top of contact-aware feed (`a1445d1`) etc.
|
commits, on top of contact-aware feed (`a1445d1`) etc.
|
||||||
- Working tree is **clean** apart from this checkpoint update, which is committed right after.
|
- Working tree is **clean** apart from this checkpoint update, which is committed right after.
|
||||||
|
|
||||||
## What was completed: security hardening items #1 and #2
|
## What was completed: security hardening items #1, #2 and #3
|
||||||
|
|
||||||
Fixes from the 2026-08-21 security audit.
|
Fixes from the 2026-08-21 security audit.
|
||||||
|
|
||||||
|
|
@ -39,8 +39,25 @@ page could read+publish arbitrary local files to nostr.build. Now:
|
||||||
- Fake backend mirrors the contract: `upload_image` without a non-empty `token` throws an
|
- Fake backend mirrors the contract: `upload_image` without a non-empty `token` throws an
|
||||||
`unknown_token` error, so tests exercise the same protocol rule.
|
`unknown_token` error, so tests exercise the same protocol rule.
|
||||||
|
|
||||||
|
**#3 Header-based CSP + navigation/window guards (`4d4dfde`):**
|
||||||
|
- The static CSP meta tag was **removed** from `frontend/index.html` and replaced with
|
||||||
|
response headers stamped by `main.ts` (`onHeadersReceived`, mainFrame only):
|
||||||
|
- `CSP_PROD` for `app://` pages: `script-src 'self'` — **no `'unsafe-inline'`**, so an
|
||||||
|
injected `<script>` cannot execute. `connect-src 'self'` (all real network goes through
|
||||||
|
the backend/main process); img-src keeps `https:` for remote feed/preview images.
|
||||||
|
- `CSP_DEV` when `NOSTR_GUI_DEV_URL` matches: keeps `'unsafe-inline'` (Vite's React-refresh
|
||||||
|
preamble is an inline script) but pins `connect-src` to localhost instead of the old
|
||||||
|
wide-open `ws:` — HMR still works.
|
||||||
|
- The meta had to go because it would also have blocked the dev preamble; headers let us
|
||||||
|
ship strict-prod / workable-dev from one HTML file.
|
||||||
|
- `will-navigate`: any navigation away from app:// or the dev origin is blocked; http(s)
|
||||||
|
targets open in the system browser via `shell.openExternal`.
|
||||||
|
- `setWindowOpenHandler`: all `target="_blank"` popups are denied; external links go to the
|
||||||
|
system browser. Unknown schemes are denied without opening anything.
|
||||||
|
|
||||||
## Commits
|
## Commits
|
||||||
|
|
||||||
|
- `4d4dfde` "Enforce header-based CSP and block window open/navigation" — main.ts + index.html.
|
||||||
- `6e627a3` "Replace upload file paths with single-use pick tokens" — main.ts, api.ts,
|
- `6e627a3` "Replace upload file paths with single-use pick tokens" — main.ts, api.ts,
|
||||||
types.ts, AppProvider.tsx, ComposeScreen.tsx, fakeBackend.ts (+62/−27).
|
types.ts, AppProvider.tsx, ComposeScreen.tsx, fakeBackend.ts (+62/−27).
|
||||||
- `4bde395` "Restrict renderer IPC to an explicit method allowlist" — main.ts (+49 lines).
|
- `4bde395` "Restrict renderer IPC to an explicit method allowlist" — main.ts (+49 lines).
|
||||||
|
|
@ -65,6 +82,8 @@ Manual protocol checks worth doing once:
|
||||||
- DevTools console: `window.backend.request('not_a_method')` → `unknown_method` envelope (#1).
|
- DevTools console: `window.backend.request('not_a_method')` → `unknown_method` envelope (#1).
|
||||||
- DevTools console: `window.backend.request('upload_image', {path:'/etc/passwd'})` →
|
- DevTools console: `window.backend.request('upload_image', {path:'/etc/passwd'})` →
|
||||||
`unknown_token` error; no file is read (#2). Real attachment flow works unchanged.
|
`unknown_token` error; no file is read (#2). Real attachment flow works unchanged.
|
||||||
|
- DevTools console: `document.cookie` / injected `<script>` does not run; Application tab
|
||||||
|
shows the CSP header on the app:// document (#3). Link previews open in the system browser.
|
||||||
|
|
||||||
## How to resume
|
## How to resume
|
||||||
|
|
||||||
|
|
@ -78,13 +97,10 @@ Manual protocol checks worth doing once:
|
||||||
|
|
||||||
Remaining audit items in priority order:
|
Remaining audit items in priority order:
|
||||||
|
|
||||||
1. **CSP** — drop `'unsafe-inline'` from `script-src` in `frontend/index.html`; add
|
1. **Legacy vault perms** — repo-root `profiles_vault.json` is group-readable (0664);
|
||||||
`setWindowOpenHandler(() => ({action:'deny'}))` + route external links through
|
|
||||||
`shell.openExternal` in `main.ts`.
|
|
||||||
2. **Legacy vault perms** — repo-root `profiles_vault.json` is group-readable (0664);
|
|
||||||
chmod 600 / delete after confirming migration; auto-tighten during migration in `src/vault.rs`.
|
chmod 600 / delete after confirming migration; auto-tighten during migration in `src/vault.rs`.
|
||||||
3. **Write-race fixes** — create files with mode 0600 at creation time in `vault.rs`
|
2. **Write-race fixes** — create files with mode 0600 at creation time in `vault.rs`
|
||||||
(`write_restricted`, `backup_file`).
|
(`write_restricted`, `backup_file`).
|
||||||
4. **Zeroize** — wipe decrypted key material via the `zeroize` crate.
|
3. **Zeroize** — wipe decrypted key material via the `zeroize` crate.
|
||||||
5. Smaller: link-preview SSRF guard (block loopback/private IPs), signer pending-cap,
|
4. Smaller: link-preview SSRF guard (block loopback/private IPs), signer pending-cap,
|
||||||
NIP-46 secret echo check, backend request timeout.
|
NIP-46 secret echo check, backend request timeout.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue