Changelog¶
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog.
[Unreleased]¶
Changed¶
- SMUGGLE: document the redesigned Files-tab HTML Smuggling flow:
PINGexposessmuggle_capabilitiesdiscovery for source caps, field limits, defaults, suggestion lists, MIME presets/maps, constructor enums, trigger maps, custom-trigger method eligibility, retention policy, and boolean caps. New discovery limits aredownload_ext=32andtrigger_event=64; capability flags advertise custom extension, MIME, trigger-event, and searchable-option support.SMUGGLEkeeps existing response keys while adding effective mode/preset, notice, locale, filename-application, constructor metadata, andtriggerEventCustom. The one-shot URL behavior is now explicit: the firstGET,HEAD, matching conditional request, browser preload, or link scanner can consume an artifact, and regenerating creates an independent URL rather than invalidating older unconsumed URLs. - SMUGGLE UX: clarify XOR as obfuscation, not confidentiality; distinguish
source file, one-shot artifact, and extracted file; document that extension
and MIME choices do not convert bytes; replace the former extension allowlist
boundary with suggested suffixes plus validated custom/compound suffixes up
to 32 characters; and keep MIME presets/custom MIME constructor-only and
metadata-only. MIME discovery now covers common text, archive (including
tar.gz), image/media, Office, package, executable, and script suffixes. Payload built-ins addbase64url,base32, andpercent; trigger coverage expands forbutton,input,select,textarea,details, andcssanimand addscsstransition,script, andform; download variants addresponse-blob,readable-stream,message-channel-blob, andidle-callback-blob; page templates addminimal; output formats are unchanged. A validated custom event is limited to a registered element, relies on a natural browser/user event, and cannot inject raw HTML/JavaScript or request synthetic dispatch, so it may not fire. Explicituse_constructor=0now conflicts with constructor-only parameters instead of silently discarding them. Extension, preset, payload, trigger, output, download, template, and MIME selectors are searchable in the dialog; this search is a UI detail, while server discovery and validation remain authoritative. Page copy, request diagnostics, and result metadata remain closed progressive disclosures. - INFO: add opt-in
?inspect=1heuristic file metadata. Responses gain an additive nestedinspectionobject only when requested; bounded inspection recognizes outer formats without claiming numeric confidence or proving XOR encryption. File rows now expose metadata through an accessible inline expandable details panel instead of the former More-menu metadata dialog. The list adds local name search, ascending/descending name sorting, and a select-shown checkbox for safer bulk deletion; clear-all moves from the bottom danger block into a compact list-actions menu. Successful bulk deletion now reports through a dismissible bottom-right toast, while errors keep their persistent detail surfaces. - Managed UX: keep the disposable VPS journey focused on install, test, and cleanup; update/rollback remain available under optional long-lived maintenance and do not require GitHub Actions at install or runtime.
- Release: Python and container verification now complete before one shared release gate; push-tag-only PyPI and GHCR publication jobs become eligible to run in parallel after that gate. Public publication remains intentionally deferred.
- Docs: document the managed VPS two-command lifecycle, credential and UFW safeguards, exact capacity calculations, verified update/rollback, and conservative uninstall. Installer/latest-download assets have not been published; this change does not publish, deploy, or mutate a live VPS.
[2.1.0] - 2026-06-29¶
Added¶
- Config: INI/env/CLI settings layer with
--config,--check-config,--print-config, and--write-sample-config; public-direct validation requires real TLS,auth_file, explicit memory budget, enabled timeouts, and non-experimental profile. - Deployment: first-class
deploy/systemd/anddeploy/docker/public-direct artifacts for console Linux servers and Docker Compose. - Extensions: explicit
xferry.extensionsplugin API with profile, CORS, and browser-mutation policy metadata;PINGnow reportsplugin_methods. - Release: tag-gated PyPI trusted publishing and GHCR image publishing with version checks, SBOM/provenance settings, and image attestation.
- SMUGGLE: constructor renderer for allowlisted payload encodings, output formats, trigger events, download variants, page templates, MIME selection, and optional leading null byte metadata.
Changed¶
- Behavior: default feature profile is now
workspace; use--profile experimentalor the deprecated--advanced-uploadalias for the legacy experimental surface. - Infrastructure: Python 3.14 is now part of the constrained CI matrix, package/security readiness smoke, package metadata, and support docs.
- UI: polished mobile upload/file action density, header/tab viewport budget, RU/EN wording, request batch mismatch labels, and opsec method result consistency.
Security¶
- Default posture: advanced upload,
SMUGGLE,NOTE, WebSocket notes, upload clear, and note clear are opt-in through theexperimentalprofile. - Deps: refresh the pinned CI
piptool to 26.1.2 sopip-auditstays clean for the Python 3.14 readiness path. - SMUGGLE: constructor mode is mutually exclusive with legacy XOR, and
generated temp cleanup only matches server-created
smuggle_<hex>artifacts so user uploads with a shared prefix are left intact.
[2026-06-15] - Docs and release remediation boundary¶
Added¶
- Infrastructure: GitHub Actions CI (Python 3.10–3.13 matrix) with ruff/mypy/pytest and a 65 % coverage gate
- Infrastructure:
security.ymlworkflow runningpip-auditandbanditweekly and on every PR - Infrastructure:
dependabot.ymlfor weekly pip, GitHub Actions, Docker, and pre-commit updates - Infrastructure:
.pre-commit-config.yamlmirroring CI checks locally - Docs:
tools/sync_docs.pygenerates the MkDocs mirrors forAPI.md,CHANGELOG.md,CONTRIBUTING.md, andSECURITY.md, with CI drift checks - Docs: standalone
LICENSE(MIT) file in repo root - Docs:
SECURITY.md— disclosure policy, supported versions, response SLA - Docs: five ADRs in
docs/ADR/documenting key design decisions - Docs:
docs/threat-model.md— STRIDE-based threat analysis - Docs:
examples/directory withbasic_file_server.sh,advanced_upload_nginx.md,notepad_client.py, Docker compose - Docs: MkDocs + Material configuration (
mkdocs.yml) for documentation site - Docs: expanded
CONTRIBUTING.mdwith Conventional Commits policy and PR checklist - Docs:
.github/PULL_REQUEST_TEMPLATE.md - Infrastructure: multi-stage
Dockerfilewith non-root user and HEALTHCHECK, plus.dockerignore - Infrastructure: tag-gated release artifact workflow with wheel/sdist smoke, SBOM, and GitHub artifact attestations
- Tests: 46 new tests (
test_metrics.py,test_handler_registry.py,test_security/test_tls_manager.py,test_http/test_io.py,test_property/with Hypothesis) - Deps: new optional extras
[test](hypothesis, pytest-benchmark) and[docs](mkdocs-material) - TLS:
--sslipmode for issuing a valid Let's Encrypt certificate for the current public IPv4 viasslip.io
Changed¶
- Refactor: extracted
MetricsCollectortosrc/metrics.py - Refactor: extracted
TLSManagertosrc/security/tls_manager.py— SSL context, cert acquisition, cleanup - Refactor: introduced
HandlerRegistryinsrc/handlers/registry.pyto replace the plain dict with typed routing lookups - Refactor: extracted
receive_request()tosrc/http/io.pywith unit tests - Refactor: split
_process_requestinto guard functions (_check_payload_size,_resolve_keep_alive,_post_process_response,_build_error_response) - Docs: architecture and threat-model docs now describe
RequestPipeline,NotepadService,TLSManager, PBKDF2 auth, and the shared descendant-path resolver that exist in the codebase today - Behavior: file access is always limited to
<root>/uploads/; separate startup flags for this restriction were removed - Behavior: advanced upload is enabled by default; unknown non-standard methods carrying body, header, chunked-header, or URL payload data are accepted as uploads
- TLS: self-signed certificates are generated with
cryptography; Let's Encrypt issuance uses the built-inacmeclient instead of acertbotsubprocess - Deps:
cryptographyand Certbot'sacmelibrary are runtime dependencies;[crypto]remains as an empty compatibility extra -
Size:
src/server.pyreduced from 1,000 LOC to 869 LOC -
NOTE method for Secure Notepad with end-to-end AES-256-GCM encryption
- ECDH P-256 key exchange for session key derivation (uses the runtime
cryptographypackage) - WebSocket support (RFC 6455) for real-time notepad sync via
/notes/ws - Upload method selector — POST, PUT, PATCH, and NONE all perform file upload
- HEAD, PATCH, DELETE HTTP method handlers
Security¶
- Refresh pinned CI constraints for
idna,pymdown-extensions, andurllib3advisories - Fix XSS in HTML smuggling — filenames escaped via
json.dumps()for JS context,innerHTMLreplaced withtextContent(B01) - Replace SHA-256 password hashing with PBKDF2-SHA256 (600K iterations) (B07)
- Fix path traversal check — replace
startswith()withPath.relative_to()(B06) - Add auth rate limiting — 5 failures per IP = 30s cooldown (B08)
- Add per-request total timeout — 30s headers, 300s body (anti-Slowloris) (B02)
Performance¶
- Replace O(n^2) buffer concatenation with chunks list in request receiver (B03)
- Move TLS handshake from accept loop to worker thread (B04)
- Increase socket listen backlog from 5 to 128 (B05)
- Add
cancel_futures=Trueto ThreadPoolExecutor shutdown (B32) - Streaming file I/O — GET and FETCH stream files in 64KB chunks from disk instead of loading entirely into memory (B17)
Improved¶
- Log response status code and latency:
[reqid] IP - METHOD /path -> 200 (12ms)(B09, B37) - Log path traversal attempts at WARNING level (B10)
- Log DoS protection triggers (oversized requests, timeouts) (B11)
- Use
logger.exception()for stack traces on request errors (B12) - Fix HTTP header parser to accept
Header:valuewithout space (B19) - Thread-safe smuggle temp file set with
threading.Lock(B20) - Centralize path validation into
_resolve_safe_path()method (B21) - Merge XOR encrypt/decrypt into single
xor_bytes()function (B22) - Clean partial files on write failure in upload and advanced upload handlers (B30)
- Clean smuggle temp files on server shutdown (B31)
- Add Content-Security-Policy header to HTML responses (B34)
- Block symlink access in file serving (defense-in-depth) (B35)
- Use cryptographically secure RNG (
SystemRandom) in captcha generation (B36) - Add 8-char hex request ID for log correlation +
X-Request-Idresponse header (B37) - Add pagination to INFO directory listing:
?offset=N&limit=M(B39) - Parse query string parameters from URL into
request.query_paramsdict - Remove server root directory path from PING response (B47)
- In-memory metrics (request count, errors, bytes sent, status codes) exposed via PING (B28)
- Add
--json-logCLI flag for structured JSON log output (B38) - Add Table of Contents to README (B43)
- Update README: fix outdated technical details (backlog, timeouts, auth hashing)
Code Quality¶
- Fix all ruff lint errors:
open()→Path.open(),raise ... from err, line length (B23) - Per-file E501 ignore for minified CSS/HTML templates in ruff config
- Add
make_request()test helper in conftest (B25) - Add path traversal test suite — 15 tests covering traversal, uploads-only paths, symlinks (B26)
- Add handler integration tests — 30 tests for GET/POST/FETCH/INFO/PING/OPTIONS/advanced upload (B27)
- Add streaming, symlink, pagination, and query param tests
- Add CLI argument parsing tests (16 tests) and server routing/advanced upload/smuggle tests (16 tests) (B44)
- Fix mypy errors: 20 → 0 across 8 files (B24)
- Test count: 64 → 149
Removed¶
- Remove unused
ServerConfigdataclass fromconfig.py(B15) - Remove unused exception hierarchy from
exceptions.py(B16)
[2.0.0] - 2025-02-08¶
Added¶
- Custom HTTP methods: GET, POST, FETCH, INFO, PING, NONE, SMUGGLE
- TLS/HTTPS with self-signed or custom certificates
- Let's Encrypt support via certbot subprocess
- HTTP Basic Authentication with random credential generation
- Advanced upload: JSON body, header, URL parameter transports, XOR handling, HMAC verification
- Uploads-only file access: restrict user file operations to
uploads/directory - HTML Smuggling with optional password-protected downloads
- Password captcha generation for protected downloads
--openflag to auto-open browser- Web UI with file upload, download, and directory listing
- XOR encryption/decryption CLI tool (
tools/decrypt.py)