You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
**Encrypted, offline note-taking.** A three-panel, OneNote-style app that keeps your data local and protected with AES-256-GCM encryption.
3
+
**Encrypted, offline note-taking.** A OneNote-style app that keeps your data local and protected with AES-256-GCM encryption.
4
4
5
5
## Features
6
6
7
-
-**3-panel layout** — Notebooks → Sections → Pages, just like OneNote.
8
-
-**AES-256-GCM encryption** — Master password encrypts all data at rest, with scrypt key derivation (N=65536, r=8, p=1).
9
-
-**Per-notebook locks** — Individual password for sensitive notebooks, on top of the master.
10
-
-**Fully offline** — All fonts, scripts, and dependencies are bundled in `lib/`. The only network request is an optional update check against GitHub Releases on launch.
-**Encrypted backup** — Export and restore `.enc` backup files.
15
-
-**Auto-update** — Checks GitHub Releases on launch and prompts to download and install when a new version is available. Can be disabled in settings.
16
-
-**Dark & light themes** — Persisted across sessions.
17
-
-**Export** — HTML and plain text, with warnings before writing unencrypted output.
18
-
19
-
## Screenshot
20
-
21
-

7
+
-**3-panel layout** — Notebooks → Sections → Pages, just like OneNote
8
+
-**AES-256-GCM encryption** — Master password encrypts all data at rest with scrypt key derivation (N=65536)
9
+
-**Per-notebook locks** — Individual password for sensitive notebooks, with per-notebook brute-force rate limiting
10
+
-**Fully offline** — All fonts, scripts, and dependencies bundled locally. The only network request is an optional update check against GitHub Releases on launch
-**Encrypted backup** — Export/restore `.enc` backup files with password-verified-before-clobber restore
16
+
-**Auto-update** — Checks GitHub Releases on launch, downloads and installs updates seamlessly
17
+
-**Dark & light themes** — Persisted across sessions, applied to all dialogs
18
+
-**Export** — HTML and plain text with unencrypted file warnings
19
+
-**Keyboard shortcuts help** — Press F1 for a list of every shortcut
20
+
-**Sandboxed renderer** — Chromium OS-level process sandbox enabled by default
21
+
-**Content Security Policy** — `connect-src 'none'`, `script-src 'self'` — no eval, no outbound connections
22
+
-**DOMPurify + hardening hook** — All note content sanitized on load and paste; `<input>` types restricted to `checkbox` only to block in-note phishing
23
+
24
+
## What's new in 2.7.1
25
+
26
+
-**Fix blank window on launch** — 2.7.0 added Subresource Integrity (SRI) hashes to the bundled React/DOMPurify scripts. SRI requires CORS, which Electron's `file://` loader does not support, so all three scripts were blocked silently and the app loaded to a blank window. SRI has been removed; integrity of bundled files is guaranteed by the signed installer instead.
27
+
28
+
## What's new in 2.7.0
29
+
30
+
-**Sandbox** — Renderer now runs in Chromium's OS-level process sandbox by default. Can be disabled per-user in `noteforge-config.json` if it causes issues on a specific system.
31
+
-**Phishing-input hardening** — DOMPurify hook strips `<input type="password">` (and every other non-checkbox input type) so malicious content can't impersonate a password prompt inside a note.
32
+
-**Safe backup restore** — Restore now test-decrypts the backup with your password *before* touching current data. Failed restores leave everything intact. A rollback copy is kept on successful restores.
33
+
-**Per-notebook rate limiting** — Wrong-password counter now tracks each notebook independently (keyed by the blob's salt+iv hash), so one mistyped password doesn't burn the lockout quota for every other notebook.
34
+
-**Custom modal dialogs** — Native `alert()`/`confirm()`/`prompt()` replaced with themed modals. Password dialogs now honor light/dark theme.
35
+
-**Paste any photo** — Images up to 5 MB auto-downscale to 1600px JPEG instead of being rejected.
36
+
-**Idle timer improvements** — Now resets on `mousemove`/`wheel` too (throttled to 1 Hz). No more auto-locking mid-read.
37
+
-**Re-lock Now** — Right-click a notebook you've unlocked this session to relock it without closing the app.
38
+
-**Empty Trash** — Bulk-purge all soft-deleted pages from the trash view.
39
+
-**Cursor-aware toolbar** — Heading and font-size selectors now reflect the format under your cursor.
-**Schema version stamp** — Every saved file now carries a `version` field for safe future migrations.
42
+
-**Graceful auto-updater failures** — If `electron-updater` fails to load (corrupt install, symlink weirdness), the app still starts. Update errors now log instead of silently vanishing.
43
+
-**Automated test suite** — `npm test` runs 89+ tests covering crypto round-trips, KDF-downgrade protection, XSS vector blocking, IPC channel coverage, and the input-type hook. CI-ready.
22
44
23
45
## Install
24
46
25
47
### Download (Windows)
26
48
27
-
Grab the latest installer from [Releases](../../releases):
49
+
Download the latest installer from [Releases](../../releases):
28
50
29
-
-**`NoteForge Setup x.x.x.exe`** — Standard Windows installer (recommended).
30
-
-**`NoteForge-x.x.x-portable.exe`** — Portable, no install needed.
51
+
-**`NoteForge Setup x.x.x.exe`** — Standard Windows installer (recommended)
52
+
-**`NoteForge-x.x.x-portable.exe`** — Portable version, no install needed
31
53
32
-
Releases are built automatically by GitHub Actions — no manual build step on my end.
54
+
Releases are built automatically by GitHub Actions — no manual build steps required.
33
55
34
-
> **Note:** Windows will show a SmartScreen warning because the app isn't code-signed yet. Click **"More info"** → **"Run anyway"** to proceed. The source is fully open for inspection.
56
+
> **Note:** Windows may show a SmartScreen warning because the app isn't code-signed yet. Click **"More info"** → **"Run anyway"** to proceed. The source code is fully open for inspection.
35
57
36
-
### Build from source
58
+
### Build from Source
37
59
38
-
Requires [Node.js](https://nodejs.org/)20 LTS or 22 LTS. Node 22 is recommended (Electron's `@electron/*` packages are moving to Node 22 as the new minimum).
- Master password is **never stored** — only the derived key (`Buffer`) lives in memory during the session.
68
-
- Notebook passwords are **never held in the renderer** — after unlock, the renderer only has an opaque 128-bit handle to a session key that lives in the main process.
69
-
- Session keys are zeroed with `Buffer.fill(0)` on lock, close, and idle timeout.
70
-
- Locked notebook sections are **stripped from disk on every write** via `sanitizeForDiskSync()` in the renderer, with a second-layer `sanitizeDataJson()` safety net in the main process. Plaintext never reaches the data file even if the renderer is compromised.
71
-
-**KDF downgrade protection** — decrypt rejects blobs with `N < 16384`, non-power-of-2 `N`, or malformed fields, so an attacker who can write the data file can't weaken the encryption header and then have you type your password into a weakened blob.
72
-
- Rate limiting with exponential backoff on failed password attempts, persisted across restarts, with separate counters for master unlock and notebook unlock.
73
-
- Password strength enforcement: minimum 10 characters, at least 3 of 4 character classes (upper / lower / digit / symbol), dictionary check against 160 common passwords, and a low-entropy check that rejects passwords with fewer than 5 unique characters.
88
+
- Master password is **never stored** — only the derived key (Buffer) lives in memory during the session
89
+
- Session key is zeroed (`Buffer.fill(0)`) on lock, close, and idle timeout
90
+
- Locked notebook sections are **stripped from disk on every write** via `sanitizeForDiskSync()` — plaintext never reaches the data file
91
+
-**Per-notebook** rate limiting with exponential backoff on failed password attempts (persisted across restarts)
92
+
- KDF-downgrade protection: rejects any blob with weakened N/r/p parameters
93
+
- Password strength enforcement: 10+ chars, 3/4 character classes, dictionary check against 160+ common passwords, low-entropy rejection
74
94
75
-
### Content Security Policy (renderer)
95
+
### Content Security Policy (Renderer)
76
96
77
97
```
78
98
default-src 'none';
@@ -83,113 +103,94 @@ img-src 'self' data:;
83
103
connect-src 'none';
84
104
```
85
105
86
-
All scripts and fonts load from the local `lib/` directory. Zero CDN dependencies at runtime. `connect-src 'none'` blocks any outbound fetch or XHR from the renderer, even if code is injected.
106
+
All scripts and fonts loaded from local `lib/` directory. Zero CDN dependencies at runtime. `connect-src 'none'` blocks any outbound fetch/XHR from the renderer process, even if code is injected.
107
+
108
+
**Note:** The auto-updater runs in the main process (not governed by the renderer's CSP) and makes a single HTTPS request to GitHub Releases on launch to check for new versions. This can be disabled in File → Settings.
87
109
88
-
The auto-updater runs in the main process — not governed by the renderer's CSP — and makes a single HTTPS request to GitHub Releases on launch to check for new versions. Disable it in File → Settings if that matters to you.
110
+
### Additional Hardening
89
111
90
-
### Additional hardening
112
+
-**Sandboxed renderer** (`sandbox: true`) — Chromium OS-level sandbox, on by default
113
+
- Navigation guards block all non-`file://` navigation
- All permissions denied (`setPermissionRequestHandler`)
116
+
- DevTools disabled in production builds
117
+
-**DOMPurify input-type hook** — blocks in-note phishing by forcing all non-checkbox `<input>` elements to lose their type attribute
118
+
- Links inserted into notes get `target="_blank" rel="noopener noreferrer"` automatically
119
+
- Export dialogs warn about unencrypted output
120
+
- Print dialogs warn for password-protected notebooks
121
+
- Config keys allowlisted — renderer can only write known settings
122
+
- CI actions pinned to commit SHAs to prevent supply-chain attacks
91
123
92
-
- DOMPurify sanitizes all note content on load, paste, and export.
93
-
- Navigation guards block all non-`file://` navigation. `will-navigate` and `will-redirect` are both handled, and `setWindowOpenHandler` denies every attempt to open a new window.
Open an [issue](https://github.com/jamesccupps/NoteForge/issues) for bugs and feature requests. For security reports or general questions, email <jamesccupps@proton.me>.
185
-
186
-
## Changelog
187
-
188
-
See [CHANGELOG.md](CHANGELOG.md).
189
-
190
-
## Contact
191
-
192
-
Open an [issue](https://github.com/jamesccupps/NoteForge/issues) for bugs and feature requests. For security reports or general questions, email <jamesccupps@proton.me>.
0 commit comments