Files
flaskpaste/README.md
Username 028367d803 docs: modernize and clean deprecated content
- replace deprecated FLASK_ENV with FLASK_DEBUG
- remove duplicate FLASKPASTE_MAX_EXPIRY entry
- update API version to 1.5.0
- add missing /pastes and /pki endpoints to table
- remove deprecated X-XSS-Protection header
- add PKI config variables
- update features list with current capabilities
- update auth benefits and security sections
2025-12-21 22:36:48 +01:00

13 KiB

FlaskPaste

A lightweight, secure pastebin REST API built with Flask.

Features

  • Simple REST API - Create, retrieve, list, and delete pastes via HTTP
  • Binary support - Upload text, images, archives, and other binary content
  • Automatic MIME detection - Magic byte detection (PNG, JPEG, GIF, WebP, ZIP, PDF, GZIP)
  • Client certificate authentication - mTLS or header-based via reverse proxy
  • Tiered expiry - 1 day (anon), 7 days (untrusted), 30 days (trusted PKI)
  • Size limits - 3 MiB anonymous, 50 MiB authenticated
  • Abuse prevention - Content-hash deduplication throttles spam
  • Proof-of-work - Computational puzzles prevent automated abuse
  • Anti-flood - Dynamic PoW difficulty increases under attack
  • Rate limiting - Per-IP throttling with auth multiplier
  • E2E encryption - Client-side AES-256-GCM with key in URL fragment
  • Burn-after-read - Single-access pastes that auto-delete
  • Password protection - PBKDF2-HMAC-SHA256 with 600k iterations
  • Built-in PKI - Certificate authority for client certificate issuance
  • Admin support - First registered user can manage all pastes
  • Security headers - HSTS, CSP, X-Frame-Options, X-Content-Type-Options
  • CLI client - Standalone fpaste tool with encryption support
  • Request tracing - X-Request-ID for log correlation
  • Minimal dependencies - Flask + SQLite, optional cryptography for CLI

Quick Start

# Clone and setup
git clone <repository>
cd flaskpaste
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt

# Run development server
python run.py

API Endpoints

Method Endpoint Description
GET / API information and usage
GET /health Health check (returns DB status)
GET /challenge Get proof-of-work challenge
GET /client Download fpaste CLI client
POST / Create a new paste
GET /<id> Retrieve paste metadata
HEAD /<id> Retrieve paste metadata (headers only)
GET /<id>/raw Retrieve raw paste content
HEAD /<id>/raw Retrieve paste headers (no body)
DELETE /<id> Delete paste (requires auth)
GET /pastes List user's pastes (requires auth)
GET /register/challenge Get PoW challenge for registration
POST /register Register and get client certificate
GET /pki PKI status and CA info
GET /pki/ca.crt Download CA certificate

Usage Examples

Create a paste (raw text)

curl --data-binary @file.txt http://localhost:5000/

Create a paste (piped input)

echo "Hello, World!" | curl --data-binary @- http://localhost:5000/

Create a paste (JSON)

curl -H "Content-Type: application/json" \
     -d '{"content":"Hello from JSON!"}' \
     http://localhost:5000/

Retrieve paste metadata

curl http://localhost:5000/abc12345

Retrieve raw content

curl http://localhost:5000/abc12345/raw

Delete a paste (requires authentication)

curl -X DELETE \
     -H "X-SSL-Client-SHA1: <your-cert-fingerprint>" \
     http://localhost:5000/abc12345

List user's pastes (requires authentication)

curl -H "X-SSL-Client-SHA1: <your-cert-fingerprint>" \
     http://localhost:5000/pastes

CLI Client

A standalone command-line client fpaste is included. For E2E encryption, install the optional cryptography package.

Installation

# Download from running server
curl -sS https://paste.example.com/client > fpaste && chmod +x fpaste

# Optional: enable encryption support
pip install cryptography

Basic Usage

# Create paste from file (encrypts by default)
./fpaste file.txt
# Returns: https://paste.example.com/abc123#<key>

# Shortcut: file path auto-selects "create" command
./fpaste secret.txt                    # Same as: ./fpaste create secret.txt

# Create paste from stdin
echo "Hello" | ./fpaste

# Disable encryption (upload plaintext)
./fpaste -E file.txt
./fpaste create --no-encrypt file.txt

# Create burn-after-read paste (single access, auto-deletes)
./fpaste -b secret.txt

# Create paste with custom expiry (1 hour)
./fpaste -x 3600 temp.txt

# Combine options: encrypted + burn-after-read
./fpaste -b secret.txt

# Get paste content (auto-decrypts if URL has #key fragment)
./fpaste get "https://paste.example.com/abc123#<key>"

# Get paste metadata
./fpaste get -m abc12345

# List your pastes (requires auth)
./fpaste list

# List all pastes (admin only)
./fpaste list --all

# Delete paste (requires auth)
./fpaste delete abc12345

# Delete multiple pastes
./fpaste delete abc12345 def67890

# Delete all pastes (admin only, requires confirmation)
./fpaste delete --all --confirm 42  # where 42 is expected count

# Show server info
./fpaste info

# Register and get client certificate (if server supports it)
./fpaste register
# Saves certificate to ~/.config/fpaste/

# Register with auto-configuration
./fpaste register --configure
# Creates cert files and updates config with fingerprint

# Register with custom name
./fpaste register -n my-laptop --configure

End-to-End Encryption

Content is encrypted by default using AES-256-GCM before upload:

  • Key is generated locally and never sent to server
  • Key is appended to URL as fragment (#...) which browsers never transmit
  • Server stores only opaque ciphertext
  • Retrieval auto-detects #key fragment and decrypts locally
  • Use -E or --no-encrypt to disable encryption

This provides true zero-knowledge storage: the server cannot read your content.

Configuration

Set server URL and authentication via environment or config file:

# Environment variables
export FLASKPASTE_SERVER="https://paste.example.com"
export FLASKPASTE_CERT_SHA1="your-cert-fingerprint"

# Or config file (~/.config/fpaste/config)
server = https://paste.example.com
cert_sha1 = your-cert-fingerprint

mTLS Client Certificate Authentication

The CLI supports mutual TLS (mTLS) for direct client certificate authentication:

# Environment variables
export FLASKPASTE_CLIENT_CERT="/path/to/client.crt"
export FLASKPASTE_CLIENT_KEY="/path/to/client.key"
export FLASKPASTE_CA_CERT="/path/to/ca.crt"  # Optional CA verification

# Or config file (~/.config/fpaste/config)
client_cert = /path/to/client.crt
client_key = /path/to/client.key
ca_cert = /path/to/ca.crt

When client certificates are configured, fpaste performs mTLS authentication directly with the server (or TLS-terminating proxy). This is more secure than header-based authentication as the certificate is validated at the TLS layer.

Generating Client Certificates

The CLI includes a built-in certificate generator for mTLS authentication:

# Generate EC certificate (recommended, fast key generation)
./fpaste cert
# Outputs fingerprint to stdout, details to stderr

# Generate and auto-configure fpaste
./fpaste cert --configure
# Creates ~/.config/fpaste/client.{crt,key} and updates config

# Custom options
./fpaste cert -a rsa -b 4096 -d 730 -n "my-client" --configure
# RSA 4096-bit key, 2-year validity, custom common name

# Supported curves for EC: secp256r1, secp384r1 (default), secp521r1
./fpaste cert -c secp256r1 --configure

The generated certificate includes:

  • CLIENT_AUTH extended key usage for mTLS
  • SHA1 fingerprint compatible with X-SSL-Client-SHA1 header
  • Self-signed with configurable validity period

Configuration

Configuration via environment variables:

Variable Default Description
FLASK_DEBUG 0 Enable debug mode (1 = enabled)
FLASKPASTE_DB ./data/pastes.db SQLite database path
FLASKPASTE_ID_LENGTH 12 Paste ID length (hex characters)
FLASKPASTE_MAX_ANON 3145728 (3 MiB) Max paste size for anonymous users
FLASKPASTE_MAX_AUTH 52428800 (50 MiB) Max paste size for authenticated users
FLASKPASTE_EXPIRY_ANON 86400 (1 day) Default expiry for anonymous users
FLASKPASTE_EXPIRY_UNTRUSTED 604800 (7 days) Default expiry for untrusted cert users
FLASKPASTE_EXPIRY_TRUSTED 2592000 (30 days) Default expiry for trusted (PKI) cert users
FLASKPASTE_MAX_EXPIRY 7776000 (90 days) Maximum custom expiry allowed
FLASKPASTE_DEDUP_WINDOW 3600 (1 hour) Dedup throttle window in seconds
FLASKPASTE_DEDUP_MAX 3 Max identical submissions per window
FLASKPASTE_PROXY_SECRET (empty) Shared secret for proxy trust validation
FLASKPASTE_POW_DIFFICULTY 20 PoW difficulty (leading zero bits, 0=disabled)
FLASKPASTE_POW_TTL 300 (5 min) PoW challenge validity period
FLASKPASTE_REGISTER_POW 24 Registration PoW difficulty (higher than paste creation)
FLASKPASTE_POW_SECRET (auto) Secret for signing PoW challenges
FLASKPASTE_ANTIFLOOD 1 Enable anti-flood (dynamic PoW difficulty)
FLASKPASTE_ANTIFLOOD_WINDOW 60 Anti-flood measurement window (seconds)
FLASKPASTE_ANTIFLOOD_THRESHOLD 5 Requests per window before difficulty increase
FLASKPASTE_ANTIFLOOD_STEP 2 Difficulty bits added per threshold breach
FLASKPASTE_ANTIFLOOD_MAX 28 Maximum PoW difficulty
FLASKPASTE_ANTIFLOOD_DECAY 60 Seconds before difficulty decreases
FLASKPASTE_RATE_LIMIT 1 Enable IP-based rate limiting
FLASKPASTE_RATE_WINDOW 60 Rate limit window (seconds)
FLASKPASTE_RATE_MAX 10 Max requests per window (anon)
FLASKPASTE_RATE_AUTH_MULT 5 Multiplier for authenticated users
FLASKPASTE_URL_PREFIX (empty) URL prefix for reverse proxy deployments
FLASKPASTE_MIN_ENTROPY 0 Min entropy bits/byte (0=disabled, 6.0=require encryption)
FLASKPASTE_MIN_ENTROPY_SIZE 256 Only check entropy for content >= this size
FLASKPASTE_PKI_ENABLED 0 Enable PKI certificate authority
FLASKPASTE_PKI_CA_PASSWORD (empty) CA password (required when PKI enabled)
FLASKPASTE_PKI_CERT_DAYS 365 Client certificate validity (days)

Authentication

FlaskPaste uses client certificate authentication. When deployed behind a reverse proxy (nginx, Apache), configure the proxy to:

  1. Terminate TLS and validate client certificates
  2. Extract the certificate SHA1 fingerprint
  3. Pass it via the X-SSL-Client-SHA1 header

Example nginx configuration:

location / {
    proxy_pass http://127.0.0.1:5000;
    proxy_set_header X-SSL-Client-SHA1 $ssl_client_fingerprint;
}

Trust Levels

FlaskPaste distinguishes three trust levels:

Level Description Default Expiry
Anonymous No certificate 1 day
Untrusted Valid certificate, not registered via PKI 7 days
Trusted Certificate registered via /register endpoint 30 days

Authenticated users can:

  • Upload larger pastes (50 MiB vs 3 MiB)
  • Delete their own pastes
  • List their own pastes

Admin users (first user to register via PKI) can additionally:

  • List all pastes (GET /pastes?all=1)
  • Delete any paste

Production Deployment

Using Gunicorn

pip install gunicorn
gunicorn -w 4 -b 0.0.0.0:5000 wsgi:app

Using Podman/Docker

podman build -t flaskpaste .
podman run -d -p 5000:5000 -v flaskpaste-data:/app/data flaskpaste

See Containerfile for container build configuration.

Development

Running Tests

pip install pytest pytest-cov
pytest tests/ -v

Test Coverage

pytest tests/ --cov=app --cov-report=term-missing

Project Structure

flaskpaste/
├── app/
│   ├── __init__.py      # Flask app factory
│   ├── config.py        # Configuration classes
│   ├── database.py      # SQLite management
│   └── api/
│       ├── __init__.py  # Blueprint setup
│       └── routes.py    # API endpoints
├── tests/               # Test suite
├── data/                # SQLite database
├── run.py               # Development server
├── wsgi.py              # Production WSGI entry
├── Containerfile        # Podman/Docker build
└── requirements.txt     # Dependencies

Security Considerations

  • Input validation - Paste IDs are hex-only, auth headers validated
  • MIME sanitization - Content-Type headers are sanitized
  • SQL injection protection - Parameterized queries throughout
  • Ownership enforcement - Only owners (or admins) can delete pastes
  • Size limits - Prevents resource exhaustion attacks
  • Abuse prevention - Content-hash deduplication prevents spam flooding
  • Entropy enforcement - Optional minimum entropy rejects plaintext uploads
  • E2E encryption - Client-side AES-256-GCM, server is zero-knowledge
  • Burn-after-read - Single-use pastes for sensitive data
  • Password protection - PBKDF2-HMAC-SHA256 with 600k iterations
  • Security headers - HSTS, CSP, X-Frame-Options, X-Content-Type-Options
  • Proof-of-work - Computational puzzles prevent automated spam
  • Rate limiting - Per-IP throttling with auth multiplier
  • Request tracing - X-Request-ID for log correlation
  • PKI support - Built-in CA for client certificate issuance

License

MIT