- Validate paste IDs against ^[a-f0-9]{16}$ before filesystem access
(blocks read/delete traversal via crafted URLs)
- Remove duplicate ALLOWED_IMAGE_EXTENSIONS that re-allowed SVG
(XSS via stored SVG); keep magic-byte validation
- Remove duplicate cleanup thread (two background loops were started)
- Unknown expiry keys now default to 1 day instead of never
- request.secure -> request.is_secure (werkzeug 3.x)
- Add gunicorn to requirements (Dockerfile CMD referenced it)
- 11 unit tests, ruff clean, MIT LICENSE, full README (was empty)
1.9 KiB
1.9 KiB
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
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
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):
docker compose up -d
Tests
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.