# paste-bin A minimal, security-focused paste bin: share text, images, and files with expiring links. Built with Flask and file-based storage (no database). ## Features - Text, image, and file pastes with random 16-hex-char IDs - Expiry options: 1 hour, 1 day, 1 week, 1 month, or never - Automatic background cleanup of expired pastes - Per-IP upload rate limiting (10 uploads / 60 s) - Image magic-byte validation; SVG rejected (XSS prevention) - Paste-ID format validation (blocks path traversal on read/delete) - Security headers: CSP, HSTS, nosniff, frame deny, referrer policy - Raw view, pretty view, and download endpoints per paste ## Quick Start ```bash pip install -r requirements.txt python app.py # visit http://localhost:8080 ``` ## Configuration | Variable | Default | Description | |----------|---------|-------------| | `PORT` | `8080` | Web server port | | `SECRET_KEY` | random | Flask secret key | | `UPLOAD_FOLDER` | `./uploads` | Binary file storage | | `STORE_FOLDER` | `./store` | Paste metadata + text content | ## Docker ```bash docker build -t paste-bin . docker run -p 8080:8080 \ -v paste-uploads:/app/uploads \ -v paste-store:/app/store \ paste-bin ``` Or with compose (mounts persistent volumes): ```bash docker compose up -d ``` ## Tests ```bash pip install -r requirements.txt pytest pytest tests/ -v ``` Covers paste roundtrips, path-traversal blocking, SVG/magic-byte validation, expiry parsing, and rate-limit setup. ## Security Notes - Uploads are stored under a random ID; extension preserved only for downloads with `Content-Disposition: attachment`. - Text pastes are served as `text/plain` (never rendered as HTML). - Images are served with `X-Content-Type-Options: nosniff` + restrictive CSP. - Paste IDs are validated against `^[a-f0-9]{16}$` before any filesystem access, so crafted URLs cannot read or delete arbitrary files. ## License MIT — see [LICENSE](LICENSE).