passwd-page
Health Gecti
- License — License: MIT
- Description — Repository has a description
- Active repo — Last push 0 days ago
- Community trust — 16 GitHub stars
Code Gecti
- Code scan — Scanned 12 files during light audit, no dangerous patterns found
Permissions Gecti
- Permissions — No dangerous permissions requested
Bu listing icin henuz AI raporu yok.
Zero-knowledge secret sharing for humans and agents
▄▄
██
██▄███▄ ▄█████▄ ▄▄█████▄ ▄▄█████▄ ██ ██ ▄███▄██ ██▄███▄ ▄█████▄ ▄███▄██ ▄████▄
██▀ ▀██ ▀ ▄▄▄██ ██▄▄▄▄ ▀ ██▄▄▄▄ ▀ ▀█ ██ █▀ ██▀ ▀██ ██▀ ▀██ ▀ ▄▄▄██ ██▀ ▀██ ██▄▄▄▄██
██ ██ ▄██▀▀▀██ ▀▀▀▀██▄ ▀▀▀▀██▄ ██▄██▄██ ██ ██ ██ ██ ▄██▀▀▀██ ██ ██ ██▀▀▀▀▀▀
███▄▄██▀ ██▄▄▄███ █▄▄▄▄▄██ █▄▄▄▄▄██ ▀██ ██▀ ▀██▄▄███ ██ ███▄▄██▀ ██▄▄▄███ ▀██▄▄███ ▀██▄▄▄▄█
██ ▀▀▀ ▀▀▀▀ ▀▀ ▀▀▀▀▀▀ ▀▀▀▀▀▀ ▀▀ ▀▀ ▀▀▀ ▀▀ ▀▀ ██ ▀▀▀ ▀▀▀▀ ▀▀ ▄▀▀▀ ██ ▀▀▀▀▀
██ ██ ▀████▀▀
┌──────┐ zero-knowledge secret sharing ╭──────────────────╮
│ ┌──┐ │ for humans & agents │ ████░░░░░░░░░ │
│ │ │ │ │ encrypted │
│ └──┘ │ encrypted on your device │ self-destruct │
│ ████ │ self-destructing after one read │ one-time read │
│ ████ │ works from browser, cli, or any agent │ ▓▓▓▓▓▓▓▓▓▓▓▓ │
└──────┘ ╰──────────────────╯
passwd.page
Zero-knowledge secret sharing for humans and agents.
Your agents need secrets. Pasting them into prompts gets them logged, leaked, and stored in places you don't control. passwd.page is the zero-knowledge handoff -- encrypted on your device, self-destructing after one read, and accessible from a browser, CLI, or any AI agent via MCP.
What's new (v3)
- QR code on share page -- scan to open on another device.
- File sharing -- drag-and-drop any file up to 1 MiB, encrypted client-side.
- Optional passphrase -- second factor via PBKDF2-SHA256 (600k iters) + AES-GCM key wrapping.
- Secret types --
text,api_key,ssh_key,postgres_url,jwt,oauth_token,env_file,file. - Custom TTLs -- 5m / 15m / 1h / 24h / 7d / 30d.
- Self-host polish -- see SELF_HOSTING.md (docker-compose / systemd unit).
Features
- Zero-knowledge -- server never sees plaintext
- End-to-end encrypted -- AES-256-GCM, client-side
- Burn-after-read -- secret is atomically deleted on first retrieval
- TTL expiry -- unread secrets auto-expire (5m, 15m, 1h, 24h, 7d, or 30d)
- Browser UI, CLI tool, MCP tool server -- three interfaces, one protocol
- Single binary, self-hostable -- Go binary with embedded frontend (~7MB)
- No accounts, no cookies, no tracking -- stateless by design
- Open source -- MIT licensed
How it compares
A one-time secret link / ephemeral password sharing tool, like PrivateBin or One-Time Secret -- but built for the agent era.
| passwd.page | One-Time Secret | PrivateBin | |
|---|---|---|---|
| Zero-knowledge (key never hits server) | ✅ | ⚠️ optional | ✅ |
| Burn-after-read | ✅ | ✅ | ✅ |
| File sharing | ✅ | ⚠️ paid | ✅ |
| CLI tool | ✅ | ⚠️ 3rd-party | ❌ |
| MCP server for AI agents | ✅ | ❌ | ❌ |
| Single self-hostable binary | ✅ | ❌ (Ruby/Redis) | ⚠️ (PHP) |
| No signup | ✅ | ✅ | ✅ |
How It Works
- Encrypt -- your device generates a random AES-256-GCM key and encrypts the secret.
- Store -- only the ciphertext is sent to the server. The key never leaves your device.
- Share -- you get a URL where the key lives in the fragment, which is never sent over HTTP.
https://passwd.page/s/abc123#kG7xR2m...
^^^^^^ ^^^^^^^^^
server sees server NEVER sees
(per RFC 3986, fragments are client-only)
The server is physically unable to decrypt your secret. Even if compromised, stored data is useless without the keys.
Architecture
User's machine Your server / passwd.page
───────────────── ─────────────────────────
Claude Code / Cursor / GPT
↕ stdio (JSON-RPC)
passwd-mcp (local binary)
↕ HTTPS (ciphertext only)
└──────────────────────────────────────→ passwd-server
(stores encrypted blobs)
Browser
↕ Web Crypto API (local encryption)
└──────────────────────────────────────→ passwd-server
CLI
↕ pkg/crypto (local encryption)
└──────────────────────────────────────→ passwd-server
All encryption happens on the user's device. The server only stores and serves ciphertext.
| Binary | Runs where | Purpose |
|---|---|---|
passwd-server |
Your server or Render/Docker | Hosted service — stores encrypted blobs, serves the web UI |
passwd-mcp |
User's machine | MCP tool server — Claude Code spawns it as a local subprocess |
passwd |
User's machine | CLI client — encrypt and share from the terminal |
The MCP binary is a thin local process: it encrypts locally, sends only ciphertext to the server over HTTPS, and returns a URL to the agent. Plaintext never leaves the user's machine.
Quick Start
Browser
Go to passwd.page, paste a secret, get a one-time link.
CLI
Install with one line — no Go toolchain required:
curl -fsSL https://passwd.page/install | sh
This drops passwd-page and passwd-mcp into /usr/local/bin (or $INSTALL_DIR if set). Checksums are verified against the GitHub Release.
Alternative (needs Go) -- note this installs a binary named passwd, which
shadows the system passwd command; the curl installer above uses the saferpasswd-page name:
go install github.com/davidfeldi/passwd-page/cmd/passwd@latest
Usage (passwd-page is the name installed by the curl script; use passwd if you built via go install):
# Share a secret
passwd-page create "my-api-key" --ttl 1h --type api_key
# https://passwd.page/s/abc123#kG7x...
# Retrieve (decrypts locally, prints to stdout)
passwd-page get "https://passwd.page/s/abc123#kG7x..."
# my-api-key
# From a file
passwd-page create --file .env --type env_file --ttl 24h
# From stdin
echo "secret" | passwd-page create
# Disable burn-after-read (secret persists until TTL)
passwd-page create --no-burn "reusable secret" --ttl 7d
AI Agent (MCP)
Install the MCP tool server:
go install github.com/davidfeldi/passwd-page/cmd/passwd-mcp@latest
Add to your Claude Code config (settings.json or claude_desktop_config.json):
{
"mcpServers": {
"passwd": {
"command": "passwd-mcp",
"env": {
"PASSWD_SERVER": "https://passwd.page"
}
}
}
}
Not sure what to paste? Run passwd-mcp --show-config to print a ready-to-paste
config block (with the absolute binary path filled in). passwd-mcp --list-tools
lists the exposed tools.
Then ask your agent: "Share this API key securely" or "Retrieve the secret at this URL."
The MCP server exposes three tools (all accept type and ttl params, enum-validated server-side):
share_secret-- encrypt and upload a secret, returns a one-time URLshare_file-- encrypt and upload a file (<= 1 MiB), returns a one-time URLretrieve_secret-- fetch and decrypt a secret from a passwd.page URL
Use Cases
- Human to Human -- share a database password with a teammate
- Human to Agent -- give your AI agent the staging API key without pasting it into a prompt
- Agent to Human -- CI pipeline shares deploy credentials via a self-destructing link
- Agent to Agent -- service-to-service token handoff with zero trust
API
POST /api/secrets
Create a new encrypted secret.
// Request
{
"ciphertext": "<base64-encoded ciphertext>",
"expiresIn": "5m" | "15m" | "1h" | "24h" | "7d" | "30d",
"burnAfterRead": true,
"type": "text"
}
// Response (201)
{
"id": "<secret-id>",
"expiresAt": "<ISO 8601 timestamp>"
}
File size limit: 1 MiB plaintext (client-side enforced). API body limit: 2 MiB.
GET /api/secrets/{id}
Retrieve a secret. If burn-after-read is enabled, the secret is atomically deleted on read.
// Response (200)
{
"ciphertext": "<base64-encoded ciphertext>",
"burnAfterRead": true,
"type": "text"
}
// Response (404) -- expired, burned, or not found
{
"error": { "code": "not_found", "message": "..." }
}
GET /health
{ "ok": true }
Rate limits: 10 creates/min, 60 reads/min per IP. Static assets are not rate-limited.
Self-Hosting
From Source
git clone https://github.com/davidfeldi/passwd-page
cd passwd.page
# Build the frontend
cd frontend && npm install && npm run build && cd ..
# Build and run the server
go build -o passwd-server ./cmd/passwd-server
./passwd-server -port 8080 -db /var/lib/passwd-page/data.db
Docker
docker build -t passwd-page .
docker run -p 8080:8080 passwd-page
Render.com (free tier)
Fork the repo, connect it to Render, and it auto-deploys from the Dockerfile. The server reads the PORT environment variable that Render provides.
Configuration
| Variable / Flag | Default | Used by | Description |
|---|---|---|---|
PASSWD_SERVER |
https://passwd.page |
CLI, MCP | Server URL |
PORT or -port |
8080 |
Server | HTTP listen port |
-db |
passwd.db |
Server | SQLite database path |
--ttl / -t |
24h |
CLI | Secret TTL (5m, 15m, 1h, 24h, 7d, 30d) |
--burn / --no-burn |
burn on | CLI | Burn after read toggle |
--server / -s |
(from env) | CLI | Override server URL per-command |
--file / -f |
CLI | Read secret from a file |
Project Structure
passwd.page/
cmd/passwd-server/ Web server with embedded frontend + SQLite
cmd/passwd/ CLI client (create, get, version)
cmd/passwd-mcp/ MCP tool server (JSON-RPC over stdio)
pkg/crypto/ Shared AES-256-GCM encryption (Go)
internal/server/ HTTP handlers, middleware (CSP, HSTS, rate limiting)
internal/storage/ SQLite storage layer, TTL cleanup goroutine
internal/client/ API client (used by CLI + MCP)
frontend/ Svelte 5 SPA (SvelteKit, adapter-static)
e2e/ Playwright end-to-end tests
docs/ Architecture documentation
Security Model
Encryption
- Algorithm: AES-256-GCM with a 256-bit random key and 96-bit IV per encryption
- Browser: Web Crypto API (native, hardware-accelerated, no external crypto libs)
- CLI / MCP: Go
crypto/aes+crypto/cipherviapkg/crypto - Encoding: base64url for keys and ciphertext
Key Distribution
The decryption key is placed in the URL fragment (#). Per RFC 3986 Section 3.5, the fragment identifier is never sent to the server in HTTP requests. The server receives and stores only ciphertext -- it has no mechanism to decrypt secrets.
Burn-After-Read
Implemented via atomic DELETE...RETURNING in SQLite. The secret is read and permanently deleted in a single transaction. There is no window where a second reader can retrieve the same secret.
Server Hardening
- Content Security Policy (CSP) on all responses
- HSTS (HTTP Strict Transport Security)
- Rate limiting on API routes (10 creates/min, 60 reads/min per IP)
- Request body size limits
- SQLite file permissions hardened to
0600 - No cookies, no sessions, no auth state -- access is by knowledge of ID + key
Explicit Reveal
The recipient page requires clicking a "Reveal Secret" button before decryption occurs. This prevents preview bots, link unfurlers, and crawlers from accidentally burning secrets.
Residual Risks
These are inherent to any browser-based secret sharing and are not unique to passwd.page:
- Browser extensions with page access can read URL fragments
- Clipboard managers may log copied secrets
- Browser history stores full URLs including fragments
- Screenshots and screen recording
Audit
- OWASP score: 91/100 (no high-severity findings)
- STRIDE threat model: 11 threats analyzed, all mitigated or accepted with documented rationale
- Dependencies: 1 Go dependency (
go-sqlite3), 0 frontend runtime dependencies
Contributing
See CONTRIBUTING.md for local setup, the test commands, and
the PR workflow. In short: fork, branch, make sure go test ./... andnpx vitest run pass, then open a focused pull request.
Code style: gofmt for Go, standard Prettier for TypeScript/Svelte. Keep
external dependencies to a minimum, and never weaken the zero-knowledge model.
Tech Stack
| Layer | Technology |
|---|---|
| Backend | Go (stdlib net/http) |
| Frontend | Svelte 5 (SvelteKit, adapter-static) |
| Database | SQLite (WAL mode, go-sqlite3) |
| Crypto (browser) | Web Crypto API (AES-256-GCM) |
| Crypto (Go) | pkg/crypto (AES-256-GCM) |
| Deployment | Single binary via go:embed |
License
MIT License -- Copyright (c) 2026 passwd.page contributors
See LICENSE for the full text.
Built for the age of agents. passwd.page
Yorumlar (0)
Yorum birakmak icin giris yap.
Yorum birakSonuc bulunamadi