CashPilot takes security seriously. This document describes how to report vulnerabilities, what versions are supported, and the security assumptions of the project.
| Version | Supported |
|---|---|
Latest release (latest Docker tag) |
Yes |
| Previous releases | No |
Only the latest published Docker images (drumsergio/cashpilot:latest and drumsergio/cashpilot-worker:latest) receive security patches. There are no LTS branches.
Do NOT open a public GitHub issue for security vulnerabilities.
Instead, use one of these channels:
- GitHub Security Advisories (preferred): Go to Security > Advisories and click "Report a vulnerability".
- Email: Contact the maintainer directly via the email listed on the GeiserX GitHub profile.
- CashPilot version or Docker image digest
- Steps to reproduce the vulnerability
- Affected component (UI, Worker, API, Docker configuration)
- Impact assessment (what an attacker could achieve)
- Proof-of-concept if available (keep it minimal)
| Step | Timeline |
|---|---|
| Acknowledgment of your report | Within 72 hours |
| Initial triage and severity assessment | Within 1 week |
| Fix developed and tested | Depends on severity |
| Patched release published | As soon as fix is verified |
| Public disclosure | After patch is available |
If you do not receive acknowledgment within 72 hours, please follow up.
- Report received via Security Advisory or email
- Acknowledge within 72 hours
- Triage — assess severity using CVSS, identify affected components
- Fix — develop and test a patch
- Release — publish patched Docker images
- Disclose — publish advisory with credit to reporter (if desired)
An embargo period applies between fix and disclosure. The reporter will be notified before any public disclosure.
- Authentication and authorization bypass (session tokens, API keys)
- Injection vulnerabilities (SQL injection, command injection, XSS)
- Privilege escalation (viewer gaining writer/owner access)
- Information disclosure (credentials, API keys, sensitive data leaks)
- Container escape or unexpected Docker API abuse
- Worker-to-UI communication security (API key auth bypass)
- Dependency vulnerabilities in shipped Docker images
- Vulnerabilities in the Docker daemon or host OS (report upstream)
- Misconfiguration by the deployer (exposed ports, weak passwords, missing TLS)
- Physical access attacks
- Denial of service via resource exhaustion (CashPilot is designed for trusted networks)
- Social engineering
- Vulnerabilities in third-party services that CashPilot connects to (bandwidth-sharing platforms, etc.)
CashPilot requires access to the Docker socket (/var/run/docker.sock) for container management. This is a privileged operation. Mitigations:
- The application runs as a non-root user (
cashpilot, UID 1000) inside the container - The entrypoint grants only the minimum group membership needed for socket access
--security-opt no-new-privileges:trueprevents privilege escalation inside the container- Container management is gated behind authenticated API endpoints (writer/owner role required)
User responsibility: Do not expose the Docker socket to untrusted networks. CashPilot is designed for trusted, private networks.
- UI users: Session-based authentication with bcrypt-hashed passwords. Sessions are signed tokens stored in HTTP-only cookies.
- Worker-to-UI: Per-worker fleet keys (since v1.0.0).
CASHPILOT_API_KEYis only a shared enrollment/bootstrap credential -- on a worker's first heartbeat the UI issues it a unique key (stored encrypted, returned once), and every subsequent request in either direction (worker heartbeat, UI command) authenticates with that worker's own key. The shared key is rejected once a worker is enrolled, so a leaked worker key only affects that one worker. - Role-based access: Three roles (viewer, writer, owner) with escalating permissions, plus an implicit
fleetrole for authenticated worker requests. Container management requires writer or owner role.
- SQLite database stored in a Docker volume (
/data/cashpilot.db) - Service credentials are encrypted at rest using Fernet symmetric encryption (
CASHPILOT_SECRET_KEY) - Database is not network-accessible (local file only)
- 400-day data retention with automatic purging
CashPilot is designed to run on private, trusted networks (home lab, VPN, LAN). It does not implement TLS natively. If exposing CashPilot to the internet:
- Place it behind a reverse proxy with TLS termination (e.g., Caddy, Traefik, nginx)
- Restrict access via firewall rules or VPN
- Use a strong
CASHPILOT_SECRET_KEYandCASHPILOT_API_KEY - Set the reverse-proxy-aware environment variables below so cookies, client-IP logging, and session invalidation behave correctly behind TLS termination
These variables only matter when CashPilot sits behind a reverse proxy; a direct/private-network deployment can leave them unset:
| Variable | Default | Description |
|---|---|---|
CASHPILOT_TRUSTED_PROXY |
unset (off) | Opt-in. When set (1/true/yes/on), trusts the right-most X-Forwarded-For entry as the real client IP. Only enable this behind exactly one reverse proxy you control -- the header is otherwise attacker-controlled |
CASHPILOT_BASE_URL |
-- | The externally-visible base URL (e.g. https://cashpilot.example.com). Used by CASHPILOT_SECURE_COOKIE=auto to detect HTTPS |
CASHPILOT_SECURE_COOKIE |
auto |
Controls the session cookie's Secure flag. auto sets it when CASHPILOT_BASE_URL starts with https; override with a truthy (true/1/yes/on) or falsy (false/0/no/off) value |
CASHPILOT_SESSION_EPOCH |
0 |
Unix timestamp. Bump it to mass-invalidate every existing session (e.g. after a credential leak) -- any session token issued before this timestamp is rejected |
Worker URLs arrive in the fleet-key-authenticated heartbeat and are later fetched with the fleet bearer token attached, so the UI validates every worker URL before contacting it:
- Cloud-metadata addresses (IPv4
169.254.169.254, IPv6fd00:ec2::254) and loopback/link-local ranges are always blocked, regardless of policy. - DNS-rebinding guard: hostnames are resolved and the resolved IP is re-validated before each request, so a name that points at a metadata or loopback address is rejected. IPv4-mapped IPv6 bypasses are normalized and caught.
- Default policy is permissive: LAN (RFC1918) and Tailscale (CGNAT
100.64.0.0/10) workers keep working out of the box with no configuration. - Opt-in
strictmode restricts workers to an explicit allowlist of CIDRs and hostname suffixes. See Fleet Management forCASHPILOT_WORKER_URL_POLICY,CASHPILOT_WORKER_ALLOWED_HOSTS, andCASHPILOT_WORKER_ALLOW_METADATA.
- Use a reverse proxy with TLS if accessible beyond localhost
- Set strong, unique values for
CASHPILOT_SECRET_KEYandCASHPILOT_API_KEY - Do not use
--privilegedfor the CashPilot container itself - Keep Docker Engine updated on all hosts
- Use
--network hostonly when necessary (e.g., cross-subnet worker communication) - Restrict Docker socket access — do not mount it in containers that don't need it
- Review deployed service configurations — CashPilot deploys third-party containers; review their security posture independently
- Back up your SQLite database regularly (
/data/cashpilot.db) - Enable strict worker-URL mode (
CASHPILOT_WORKER_URL_POLICY=strict) for internet-exposed deployments, withCASHPILOT_WORKER_ALLOWED_HOSTSset to your worker subnets
We follow coordinated disclosure practices. We will:
- Not take legal action against good-faith security researchers
- Work with you to understand and resolve the issue
- Credit you in the security advisory (unless you prefer anonymity)
- Not disclose the vulnerability publicly until a fix is available
We thank the security community for helping keep CashPilot safe. Contributors who report valid vulnerabilities will be credited here (with their permission).
No vulnerabilities reported yet.