No description
  • Go 39.7%
  • JavaScript 33%
  • CSS 18.6%
  • HTML 8%
  • Dockerfile 0.7%
Find a file
Kalvin Carefour Johnny ba308aac8c
Create LICENSE
2026-03-28 00:01:16 +08:00
static Fix XSS vulnerability, harden crypto, and improve server/Docker config 2026-03-27 06:03:40 +00:00
.dockerignore Fix security vulnerabilities, bugs, and add .env configuration system 2026-03-26 23:19:39 +00:00
.env.example Fix XSS vulnerability, harden crypto, and improve server/Docker config 2026-03-27 06:03:40 +00:00
.gitignore First commit 2026-03-26 22:42:36 +08:00
db.go First commit 2026-03-26 22:42:36 +08:00
docker-compose.yml Fix XSS vulnerability, harden crypto, and improve server/Docker config 2026-03-27 06:03:40 +00:00
Dockerfile Fix security vulnerabilities, bugs, and add .env configuration system 2026-03-26 23:19:39 +00:00
go.mod First commit 2026-03-26 22:42:36 +08:00
go.sum First commit 2026-03-26 22:42:36 +08:00
handlers.go Fix XSS vulnerability, harden crypto, and improve server/Docker config 2026-03-27 06:03:40 +00:00
LICENSE Create LICENSE 2026-03-28 00:01:16 +08:00
main.go Fix XSS vulnerability, harden crypto, and improve server/Docker config 2026-03-27 06:03:40 +00:00
models.go Fix security vulnerabilities, bugs, and add .env configuration system 2026-03-26 23:19:39 +00:00
README.md Update README.md 2026-03-27 23:43:38 +08:00

ZeroMark

A zero-knowledge, end-to-end encrypted bookmark manager. Self-hosted with Go + MariaDB.

The server never sees your plaintext data. All encryption and decryption happens client-side in your browser using the Web Crypto API.

CC0 1.0 Universal (CC0 1.0) Public Domain Dedication

AI Generated Badge

How it works

Crypto flow

  1. You enter a master password on login/register
  2. Two keys are derived from it using PBKDF2 (310,000 iterations, SHA-256):
    • Auth key — derived from username:auth:zeromark salt, sent to server for authentication
    • Encryption key — derived from username:enc:zeromark salt, never leaves your browser
  3. All bookmark and collection data is encrypted client-side with AES-256-GCM before being sent to the server
  4. The server stores only encrypted blobs + IVs
  5. Search works client-side on decrypted data in memory

What the server sees

  • Your username
  • A salted SHA-256 hash of your auth key (which is itself a PBKDF2-derived key)
  • Encrypted blobs it cannot decrypt
  • Nothing else

What the server cannot do

  • Read your bookmark names, URLs, or descriptions
  • Search your bookmarks
  • Recover your data if you lose your password

Stack

  • Backend: Go (standard library HTTP + go-sql-driver/mysql)
  • Database: MariaDB 11
  • Frontend: Vanilla HTML/CSS/JS, Web Crypto API
  • Deployment: Docker Compose

Run with Docker

docker compose up -d

Open http://localhost:8080 and register an account.

Run locally (dev)

  1. Start a MariaDB instance with a zeromark database
  2. Set environment variables:
export DB_HOST=localhost
export DB_PORT=3306
export DB_USER=zeromark
export DB_PASS=zeromark
export DB_NAME=zeromark
  1. Build and run:
go build -o zeromark .
./zeromark

Environment variables

Variable Default Description
DB_HOST localhost MariaDB host
DB_PORT 3306 MariaDB port
DB_USER zeromark Database user
DB_PASS zeromark Database password
DB_NAME zeromark Database name
LISTEN_ADDR :8080 HTTP listen address

Licence

CC0 — Public domain. Do whatever you want with it.