Username 8f9868f0d9 flaskpaste: initial commit with security hardening
Features:
- REST API for text/binary pastes with MIME detection
- Client certificate auth via X-SSL-Client-SHA1 header
- SQLite with WAL mode for concurrent access
- Automatic paste expiry with LRU cleanup

Security:
- HSTS, CSP, X-Frame-Options, X-Content-Type-Options
- Cache-Control: no-store for sensitive responses
- X-Request-ID tracing for log correlation
- X-Proxy-Secret validation for defense-in-depth
- Parameterized queries, input validation
- Size limits (3 MiB anon, 50 MiB auth)

Includes /health endpoint, container support, and 70 tests.
2025-12-16 04:42:18 +01:00

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
  • Security headers - HSTS, CSP, X-Frame-Options, Cache-Control, and more
  • 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

# 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)
POST / Create a new paste
GET /<id> Retrieve paste metadata
GET /<id>/raw Retrieve raw paste content
DELETE /<id> Delete paste (requires auth)

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

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_PROXY_SECRET (empty) Shared secret for proxy trust validation

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;
}

Authenticated users can:

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

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 can delete their pastes
  • Size limits - Prevents resource exhaustion attacks
  • 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

Description
Lightweight, secure REST API pastebin with Flask
Readme 2.6 MiB
Languages
Python 95%
Shell 4.2%
Makefile 0.4%
Dockerfile 0.4%