Skip to content

Security + reliability + docs: whole-repo audit follow-ups#105

Merged
GeiserX merged 3 commits into
mainfrom
fix/audit-security-docs
Jul 17, 2026
Merged

Security + reliability + docs: whole-repo audit follow-ups#105
GeiserX merged 3 commits into
mainfrom
fix/audit-security-docs

Conversation

@GeiserX

@GeiserX GeiserX commented Jul 17, 2026

Copy link
Copy Markdown
Owner

Follow-ups from a 12-lens whole-repo audit (security-weighted). Every critical/high finding was adversarially verified before inclusion. This PR fixes the bounded, clearly-correct security/correctness/docs findings; the larger refactors and one product decision are tracked as issues (see below) rather than bundled here.

Security (commit 19a39d7)

  • Worker deploy-spec validation → allowlist. Capabilities and network_mode: host are now permitted only if a real services/*.yml catalog entry declares them (derived live from the catalog, fail-closed), replacing a 3-entry capability denylist that missed SYS_MODULE/DAC_READ_SEARCH/etc. Blocked bind-mount roots expanded (/mnt,/media,/opt,/srv,/data,/tmp). Added the missing auth-rejection test on the socket-privileged deploy endpoint. (Verified the worker image ships services/ + catalog.py, so mysterium's NET_ADMIN + host-network deploy still passes.)
  • Stored DOM-XSS closed in fleet.html: esc() now escapes quotes, so a worker name can't break out of data-worker-name="…".
  • Fleet-key robustness: an undecryptable per-worker key (secret-key rotation) now reports the worker unenrolled → re-enrolls on the shared key, instead of an empty string that bricks auth both ways; and the worker only adopts an issued key after it's durably persisted (no memory-only key lost on restart).
  • CASHPILOT_SECURE_COOKIE accepts the usual truthy/falsy spellings.

Reliability (commit 916b357)

  • Fleet lockout fixed: the stale-worker reaper no longer deletes an enrolled worker after 1h offline (that dropped its key → permanent lockout on reboot); enrolled workers are only marked offline. Per-worker error boundary added.
  • Vanished-service downtime is now visible: health records check_down for a known non-external service missing from an online worker's heartbeat, instead of freezing green.
  • Login rate-limit dict releases keys (no unbounded per-IP growth); per-source exchange-rate staleness; Storj unrecognized-shape now raises instead of silent $0.

Docs + CI (commit 068e007)

  • release.yml change-detection filter was stale — it omitted app/routers, app/deps, app/metrics, app/setup_token, so fixes to those (including auth/API-key guards) never triggered a release/image build. Now included.
  • Docs reconciled with the post-refactor/v1.0.0 app: first-run setup token documented; CASHPILOT_COLLECT_INTERVAL/CASHPILOT_PORT corrected; worker reachability + CASHPILOT_WORKER_URL; SECURITY.md per-worker fleet-key model; architecture.md (python:3.14-alpine/su-exec, workers table); Prometheus guide added to nav; CLAUDE.md refreshed; compose pin example → 1.0.1.

Verification

ruff check . + ruff format --check . clean; 1142 tests pass (regression tests added for every code fix above).

Tracked separately (not in this PR)

Larger refactors + one product call, filed as issues: auth-revocation durability across restart (needs a schema migration — highest-priority follow-up), worker client_id protocol, SSRF DNS-rebind TOCTOU, CSP unsafe-inline/inline-onclick refactor, main.py/app.js god-module + duplicate-deploy-path consolidation, DB connection-proxy cleanup, perf batch, :latest policy decision for our own images, test-coverage hardening, dead-code removal.

Not auto-merging — flagging for review since this touches the just-shipped v1.0.0 fleet-key code.

GeiserX added 3 commits July 17, 2026 16:38
…tify fleet-key handling

Whole-repo audit follow-ups (security lens):
- worker_api: capability + host-network validation is now an ALLOWLIST derived
  live from services/*.yml (only caps/host-mode a real catalog service declares
  are permitted) instead of a 3-entry denylist that missed SYS_MODULE/DAC_READ_
  SEARCH/etc.; expand blocked bind-mount roots (/mnt,/media,/opt,/srv,/data,/tmp);
  add the missing auth-rejection test for the socket-privileged deploy endpoint
- worker_api: only adopt an issued per-worker key AFTER it is durably persisted
  (a write failure no longer leaves a memory-only key that vanishes on restart)
- fleet.html: esc() now escapes quotes too, closing stored DOM-XSS via a worker
  name breaking out of a double-quoted attribute
- database: an undecryptable per-worker key (secret-key rotation) now reports the
  worker as unenrolled so it re-enrols on the shared key, instead of collapsing to
  an empty string that bricks fleet auth in both directions
- auth: CASHPILOT_SECURE_COOKIE accepts the usual truthy/falsy spellings, not just
  the exact string 'true'
…me, bound rate-limit memory

- main: the stale-worker reaper no longer deletes an ENROLLED worker's row after
  1h offline (that dropped its per-worker key and locked it out permanently on the
  next reboot); enrolled workers are only marked offline, removal is a UI action.
  Per-worker error boundary so one bad timestamp can't abort the whole sweep
- main: health check now records check_down for a known non-external service that
  vanishes from an online worker's heartbeat, instead of freezing its score green
- main: login rate-limit dict releases keys when attempts age out / on success,
  so it can't grow unbounded per distinct client IP
- exchange_rates: per-source freshness — crypto/fiat staleness tracked
  independently so one source failing can't mislabel the other (additive
  crypto_stale/fiat_stale keys; existing shape unchanged)
- collectors/storj: an unrecognized API response now raises (surfaced via collector
  alerts) instead of silently recording $0
…release path filter

- release.yml: the change-detection filter now includes app/routers, app/deps,
  app/metrics, app/setup_token — fixes to those (incl. auth/API-key guards) now
  actually trigger a release + image build instead of silently not shipping
- docs: document the first-run setup token; correct CASHPILOT_COLLECT_INTERVAL
  (name+minutes) and CASHPILOT_PORT (worker-only); fix the 'no port forwarding on
  the worker' claim + document CASHPILOT_WORKER_URL; update SECURITY.md to the
  per-worker fleet-key model + proxy/cookie/session env vars; fix architecture.md
  (python:3.14-alpine/su-exec, workers table, no worker SQLite); add the Prometheus
  guide to the nav; CLAUDE.md routers/deps/setup_token/metrics + port 8080 + 15
  collectors; refresh the docker-compose pin example to 1.0.1
@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@GeiserX, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 35 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 70023a31-8756-4ad0-9834-653439d03f0b

📥 Commits

Reviewing files that changed from the base of the PR and between f79f50c and 068e007.

📒 Files selected for processing (21)
  • .github/workflows/release.yml
  • CLAUDE.md
  • README.md
  • SECURITY.md
  • app/auth.py
  • app/collectors/storj.py
  • app/database.py
  • app/exchange_rates.py
  • app/main.py
  • app/templates/fleet.html
  • app/worker_api.py
  • docker-compose.yml
  • docs/architecture.md
  • docs/fleet.md
  • docs/getting-started.md
  • mkdocs.yml
  • tests/test_database.py
  • tests/test_exchange_rates.py
  • tests/test_worker_api_coverage.py
  • tests/test_worker_keys.py
  • tests/test_workers.py
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/audit-security-docs

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@codecov

codecov Bot commented Jul 17, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 94.11765% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 93.04%. Comparing base (f79f50c) to head (068e007).

Files with missing lines Patch % Lines
app/auth.py 85.71% 1 Missing ⚠️
app/collectors/storj.py 0.00% 1 Missing ⚠️
app/exchange_rates.py 90.00% 1 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main     #105      +/-   ##
==========================================
+ Coverage   92.63%   93.04%   +0.41%     
==========================================
  Files          31       31              
  Lines        3243     3276      +33     
==========================================
+ Hits         3004     3048      +44     
+ Misses        239      228      -11     
Files with missing lines Coverage Δ
app/database.py 88.34% <100.00%> (+0.76%) ⬆️
app/main.py 94.00% <100.00%> (+1.00%) ⬆️
app/auth.py 97.08% <85.71%> (-0.86%) ⬇️
app/collectors/storj.py 97.14% <0.00%> (ø)
app/exchange_rates.py 98.27% <90.00%> (-1.73%) ⬇️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@GeiserX
GeiserX merged commit 2da01e2 into main Jul 17, 2026
8 checks passed
@GeiserX
GeiserX deleted the fix/audit-security-docs branch July 17, 2026 15:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant