A production-oriented Node.js notes application with defense-in-depth security controls.
- User registration and session-based authentication
- Create, read, update, and delete notes (per-user isolation)
- Server-rendered UI with auto-escaping templates
- SQLite storage with parameterized queries and foreign keys
| Threat | Mitigation |
|---|---|
| SQL injection | Parameterized statements only (better-sqlite3) |
| XSS | EJS <%= %> escaping; strict Content-Security-Policy |
| CSRF | Double-submit cookie pattern (csrf-csrf) on all state-changing requests |
| Session fixation | Session regeneration on successful login |
| Session hijacking | httpOnly, secure (production), sameSite=strict cookies |
| IDOR | All note queries scoped by user_id from session |
| Brute force | Rate limits on auth (10/15min) and writes (30/min) |
| Mass assignment | Explicit Zod schemas; no direct req.body passthrough |
| Password storage | bcrypt (12 rounds) |
| HTTP hardening | Helmet (CSP, HSTS in production), HPP, disabled X-Powered-By |
| Information disclosure | Generic error messages; no stack traces to users |
cp .env.example .env
# Edit .env — set SESSION_SECRET (min 32 chars):
# openssl rand -base64 48
npm install
npm run db:init
npm start- Set
NODE_ENV=production - Generate a strong
SESSION_SECRET(48+ random bytes) - Terminate TLS at a reverse proxy (nginx, Caddy, cloud load balancer)
- Set
TRUST_PROXY=trueso secure cookies and rate limits work correctly - Bind to localhost (
HOST=127.0.0.1) and expose only via the proxy - Run as a non-root user; restrict filesystem permissions on
data/ - Keep dependencies updated:
npm auditand patch regularly - Back up
data/notes.dbon a schedule
- HTTPS only (redirect HTTP → HTTPS)
- Forward
X-Forwarded-Proto: https - Do not expose the Node process directly to the internet
See .env.example.
| Command | Description |
|---|---|
npm start |
Run server |
npm run dev |
Run with file watch |
npm run db:init |
Create/upgrade database schema |
src/
server.js # Entry point
app.js # Express setup & middleware
config.js # Validated configuration
db/ # SQLite access layer
middleware/ # Auth, CSRF, rate limits, validation
routes/ # Auth and notes handlers
validation/ # Zod schemas
views/ # EJS templates (HTML-escaped output)
public/ # Static assets (CSP-compatible)
-
SESSION_SECRETis unique and ≥32 characters - HTTPS enabled end-to-end
-
NODE_ENV=production -
TRUST_PROXY=truebehind reverse proxy -
npm auditshows no high/critical issues (or documented exceptions) - Database directory not world-readable
- Firewall allows only proxy → app traffic
No application is “100% secure.” This project implements industry-standard controls; ongoing patching, monitoring, and infrastructure hardening remain your responsibility.