# FlaskPaste A lightweight, secure pastebin REST API built with Flask. ## Features - **Simple REST API** - Create, retrieve, and delete pastes via HTTP - **Binary support** - Upload text, images, archives, and other binary content - **Automatic MIME detection** - Magic byte detection for common formats (PNG, JPEG, GIF, WebP, ZIP, PDF, GZIP) - **Client certificate authentication** - Optional auth via `X-SSL-Client-SHA1` header - **Automatic expiry** - Pastes expire after configurable period of inactivity - **Size limits** - Configurable limits for anonymous and authenticated users - **Abuse prevention** - Content-hash deduplication throttles repeated identical submissions - **Proof-of-work** - Configurable computational puzzle prevents automated spam - **Security headers** - HSTS, CSP, X-Frame-Options, Cache-Control, and more - **CLI client** - Standalone `fpaste` command-line tool included - **Request tracing** - X-Request-ID support for log correlation - **Proxy trust validation** - Optional shared secret for defense-in-depth - **Minimal dependencies** - Flask only, SQLite built-in ## Quick Start ```bash # Clone and setup git clone 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 | | `POST /` | Create a new paste | | `GET /` | Retrieve paste metadata | | `HEAD /` | Retrieve paste metadata (headers only) | | `GET //raw` | Retrieve raw paste content | | `HEAD //raw` | Retrieve paste headers (no body) | | `DELETE /` | Delete paste (requires auth) | ## Usage Examples ### Create a paste (raw text) ```bash curl --data-binary @file.txt http://localhost:5000/ ``` ### Create a paste (piped input) ```bash echo "Hello, World!" | curl --data-binary @- http://localhost:5000/ ``` ### Create a paste (JSON) ```bash curl -H "Content-Type: application/json" \ -d '{"content":"Hello from JSON!"}' \ http://localhost:5000/ ``` ### Retrieve paste metadata ```bash curl http://localhost:5000/abc12345 ``` ### Retrieve raw content ```bash curl http://localhost:5000/abc12345/raw ``` ### Delete a paste (requires authentication) ```bash curl -X DELETE \ -H "X-SSL-Client-SHA1: " \ http://localhost:5000/abc12345 ``` ## CLI Client A standalone command-line client `fpaste` is included (no external dependencies). ### Basic Usage ```bash # Create paste from file ./fpaste create file.txt # Create paste from stdin echo "Hello" | ./fpaste # Get paste content ./fpaste get abc12345 # Get paste metadata ./fpaste get -m abc12345 # Delete paste (requires auth) ./fpaste delete abc12345 # Show server info ./fpaste info ``` ### Configuration Set server URL and authentication via environment or config file: ```bash # 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 ``` ## Configuration Configuration via environment variables: | Variable | Default | Description | |----------|---------|-------------| | `FLASK_ENV` | `development` | Environment (`development`, `production`, `testing`) | | `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` | `432000` (5 days) | Paste expiry in seconds | | `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_POW_SECRET` | (auto) | Secret for signing PoW challenges | ## 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: ```nginx location / { proxy_pass http://127.0.0.1:5000; proxy_set_header X-SSL-Client-SHA1 $ssl_client_fingerprint; } ``` Authenticated users can: - Upload larger pastes (50 MiB vs 3 MiB) - Delete their own pastes ## Production Deployment ### Using Gunicorn ```bash pip install gunicorn gunicorn -w 4 -b 0.0.0.0:5000 wsgi:app ``` ### Using Podman/Docker ```bash 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 ```bash pip install pytest pytest-cov pytest tests/ -v ``` ### Test Coverage ```bash 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 can delete their pastes - **Size limits** - Prevents resource exhaustion attacks - **Abuse prevention** - Content-hash deduplication prevents spam flooding - **Security headers** - HSTS, CSP, X-Frame-Options, X-Content-Type-Options, Cache-Control - **Request tracing** - X-Request-ID for log correlation and debugging - **Proxy trust** - Optional `X-Proxy-Secret` validation to prevent header spoofing ## License MIT