Skip to content

Commit bf78cd9

Browse files
committed
release: 1.3.0 β€” observability, SQLite pool, CSP nonce, CLI split
Bumps server (pyproject.toml) and CLI (cli/pyproject.toml) in lockstep so `v1.3.0` names a single consistent release across the Docker image and the PyPI wheel. Highlights since 1.2.0: Security * Webhook DNS-rebinding defense: resolve once at delivery time, pin the TCP connection to that IP, reject the whole host on any private address (fix(webhook): pin TCP…). * SSRF filter now uses ipaddress.is_global + is_multicast, covering the ranges we were missing (CGNAT, benchmark, TEST-NET, IPv4/6 multicast, etc.) instead of a hand-rolled list that drifts. * X-Forwarded-For now reads the rightmost entry β€” leftmost is client-controlled and was bypassable. Documented the multi-hop caveat. * CSP script-src hardened: `'unsafe-inline'` replaced by a per-request nonce; all inline `onclick=` handlers rewritten as `addEventListener`. style-src keeps `'unsafe-inline'` while the inline `style="…"` attributes remain β€” separate chore. * DELETE endpoints return a uniform 403, not 404/403, so probing with a bad token can't enumerate existing paste IDs. Observability * New /metrics endpoint (Prometheus) with business counters (pastes created/viewed/deleted, webhook outcomes) and latency + pool-wait histograms. * /healthz is now documented as part of the operator surface. Storage * SQLite: single-conn + lock β†’ pooled connections (WAL + busy_timeout handle writer serialization). Configurable via SQLITE_POOL_SIZE, observable via ghostbit_sqlite_pool_wait_seconds. * iter_all() streams via fetchmany(500) so admin export doesn't materialize huge DBs in memory. * Redis save() on an already-expired paste now returns False instead of a phantom True, so admin import counts it as skipped. Code quality * Root pyproject.toml with ruff config + package metadata; server and CLI both pip install -e'able with [dev] extras. * CI workflow runs ruff check + format check + pytest on every PR touching app/, tests/, or cli/. * Language metadata (slug β†’ extensions, CM mode, Pygments aliases) centralized in app/languages.json; the four previous duplicates in main.py, detect.py, index.html, paste.html are now derived views. * CLI split from one 827-line cli.py into a cli/ package (crypto, config, history, api, completion, __init__ entry point). * Per-page JS moved out of the templates into static/{index,paste, raw,footer}.js, read bootstrap data from <script type="application/json"> blocks.
1 parent 356b1c4 commit bf78cd9

2 files changed

Lines changed: 2 additions & 2 deletions

File tree

β€Žcli/pyproject.tomlβ€Ž

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "ghostbit-cli"
7-
version = "1.2.0"
7+
version = "1.3.0"
88
description = "Ghostbit CLI β€” create end-to-end encrypted pastes from the terminal"
99
readme = "README.md"
1010
license = "MIT"

β€Žpyproject.tomlβ€Ž

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "ghostbit"
7-
version = "1.2.0"
7+
version = "1.3.0"
88
description = "Self-hosted, end-to-end encrypted paste service"
99
readme = "README.md"
1010
license = "MIT"

0 commit comments

Comments
Β (0)