MyNotes

Security at MyNotes

What we do to keep your notes private, what we don't claim to do, and how to reach us if you find a problem.

Encryption

  • In transit. Every page and API request is HTTPS-only with HSTS. Plain-HTTP requests are upgraded automatically.
  • At rest. The PostgreSQL database and its backups are encrypted by the managed-Postgres provider. Backup snapshots are encrypted independently and rotated.
  • Not end-to-end encrypted. Honest framing: notes are not encrypted client-side, which means an operator with database access could in principle read them — the same as for almost any hosted note-taking service. Our Terms commit us not to.

Authentication & sessions

  • Password requirements. Minimum length and complexity (one uppercase, one lowercase, one digit, one special character) are enforced at sign-up and password change.
  • Email confirmation required. Accounts cannot sign in until the email has been confirmed.
  • Disposable-email blocklist. Sign-ups from temporary-email providers are rejected.
  • Session rotation. Changing your password rotates the per-user session token — every previously-signed-in browser is signed out on its next request. Manual "sign out all other devices" is also available from /settings/security.
  • Brute-force protection. Rack::Attack throttles sign-ups (5 / hour / IP) and per-email login attempts (5 / 20 minutes) — blunting credential-stuffing without locking real users out.
  • Two-factor authentication. Not yet — on the short list. In the meantime, use a unique strong password from a password manager.

Authorization

  • Implicit per-user scoping. Every authenticated read goes through current_user.notes.find — there are no Note.find(id) call paths in the controller layer. A request for someone else's note id returns 404, not "forbidden."
  • CSRF protection. All state-changing browser requests carry a per-session CSRF token; the API uses bearer-token auth and is exempt from cookie-based CSRF (a stolen cookie can't make API calls).
  • Scoped error logs. The per-user API error log is read through current_user.api_errors only — there's no admin route that exposes another user's request paths.

API tokens

  • Stored hashed. Tokens are hashed at rest; the plaintext is shown to the user once at issuance and never recovered.
  • Default 90-day expiry. Tokens issued without an explicit expiry are capped at 90 days. User-set expiries beyond one year are rejected. Past expiries are rejected outright.
  • Per-token rate limits. Reads / writes / appends per minute are capped per-tier — see /limits.
  • Idempotency keys on every write endpoint with a 24-hour dedup window per user — replays with a different body return 409 idempotency_key_conflict.
  • Revocable from the UI. /settings/api_tokens shows every active token; revoke flips it dead instantly.

Dependencies & infrastructure

  • Continuous dependency scanning. Every push runs bundler-audit (Ruby gems) and importmap audit (JS modules) in CI. A known-vulnerable dependency fails the build.
  • Static analysis on every push. brakeman scans the Rails source for the OWASP-derived issue classes; a finding fails the build.
  • Error tracking. Sentry captures unhandled exceptions in production; Personally-identifiable data is scrubbed at the SDK boundary.
  • Encrypted backups. Daily Postgres dumps are pruned on a retention schedule and copied off-host (rsync / S3-compatible).

Privacy posture

Operational specifics are in the Privacy Policy. Two commitments worth surfacing here:

  • No AI training on your notes. Bound by the Terms.
  • Reading and exporting are free even after a subscription lapses. Your notes are never inaccessible to you.

Reporting a vulnerability

Found a security issue? Email hello@example.com with SECURITY in the subject line. We'll acknowledge within one business day and keep you in the loop while we patch. Please don't publicly disclose until we've had a reasonable chance to fix the issue.

The machine-readable companion to this section lives at /.well-known/security.txt (RFC 9116).