docs: harden public docs by removing security-sensitive details (#331)

* docs: remove security-sensitive implementation details from public documentation

Generalize or remove internal architecture details that could aid targeted
attacks — CVE tables, database schema, rate limit thresholds, proxy internals,
encryption algorithm names, and WebSocket middleware bypass info.

* test(metrics): fix flaky minute-bucket aggregation test

Floor baseTime to the start of the current minute so baseTime + 5000
never crosses a minute boundary and produces 2 buckets instead of 1.
This commit is contained in:
Anso
2026-04-01 23:48:49 -04:00
committed by GitHub
parent 7d9dcc77d4
commit c4e2595ded
7 changed files with 28 additions and 120 deletions
+9 -22
View File
@@ -1,6 +1,6 @@
---
title: Architecture Overview
description: System design, request flow, database schema, and deployment model.
description: System design, request flow, and deployment model.
---
## System overview
@@ -12,7 +12,7 @@ Sencho is a self-contained application packaged as a single Docker container:
- **Database:** SQLite via `better-sqlite3` — no external database required
- **Container management:** Docker Engine API via the mounted Docker socket, plus Docker Compose CLI for stack operations
There are no external dependencies. No Redis, no PostgreSQL, no message queues. All state lives in a single SQLite file (`sencho.db`) inside the data directory.
There are no external dependencies. No Redis, no PostgreSQL, no message queues. All state lives in a single SQLite file inside the data directory.
---
@@ -21,10 +21,10 @@ There are no external dependencies. No Redis, no PostgreSQL, no message queues.
### Browser sessions
1. The browser loads the React SPA from the Express static file server
2. The frontend makes API calls via an `apiFetch` wrapper that injects the active node ID as an `x-node-id` header
3. Express middleware evaluates the node ID:
- **Local node:** The request passes through authentication middleware and hits the local route handler, which communicates with Docker via the mounted socket
- **Remote node:** The request is transparently proxied to the remote Sencho instance using `http-proxy-middleware`. The backend strips the `x-node-id` header and injects `Authorization: Bearer <token>` for the remote node
2. The frontend makes API calls, including which node should handle each request
3. The backend evaluates which node is targeted:
- **Local node:** The request passes through authentication and hits the local route handler, which communicates with Docker via the mounted socket
- **Remote node:** The request is securely proxied to the target Sencho instance with appropriate authentication
4. The response flows back through the same path to the browser
### API token access
@@ -48,20 +48,7 @@ SSO is supported via LDAP, Google OIDC, GitHub OAuth, and Okta OIDC. SSO users a
## Database
Sencho stores all state in a single SQLite database using the default journal mode (DELETE/ROLLBACK). The schema includes approximately 20 tables:
| Table group | Tables | Purpose |
|-------------|--------|---------|
| **Identity** | `users`, `role_assignments`, `sso_config` | User accounts, RBAC, SSO provider configs |
| **Nodes** | `nodes` | Local and remote node connection details |
| **Configuration** | `global_settings` | Key-value application settings |
| **Automation** | `webhooks`, `webhook_executions`, `scheduled_tasks`, `scheduled_task_runs` | Webhook definitions/history, cron tasks |
| **Monitoring** | `stack_alerts`, `notification_history`, `container_metrics`, `agents` | Alert rules, notifications, time-series metrics, notification channels |
| **Fleet** | `fleet_snapshots`, `fleet_snapshot_files` | Multi-node backup snapshots |
| **Security** | `api_tokens`, `audit_log` | API token hashes, action audit trail |
| **Updates** | `stack_update_status` | Image update availability tracking |
| **Registries** | Stored via `RegistryService` | Private container registry credentials (encrypted at rest) |
| **State** | `system_state` | Internal application state |
Sencho stores all state in a single SQLite database — no external database required. The schema covers user identity, node configuration, automation rules, monitoring data, and security audit trails. Sensitive values (such as registry credentials and node tokens) are encrypted at rest.
All schema migrations run automatically on startup. See [Upgrading Sencho](/operations/upgrade#automatic-migrations) for details.
@@ -78,7 +65,7 @@ This means:
- No SSH, SFTP, or remote Docker TCP socket connections
- Each node is fully autonomous and can operate independently
- The primary instance proxies both HTTP requests and WebSocket connections
- Node routing is controlled via the `x-node-id` request header (HTTP) or `?nodeId=` query parameter (WebSocket)
- Node routing is handled automatically by the frontend. API users can target a specific node using a request header or query parameter (see [API Overview](/api-reference/overview))
---
@@ -89,7 +76,7 @@ This means:
| `/api/stacks/{stackName}/logs` | Live container log streaming | Cookie or query param token |
| `/ws` | Host console terminal (PTY) | Cookie-based, admin only |
WebSocket connections bypass Express middleware. Authentication is handled manually by parsing cookies and verifying JWTs inside the `upgrade` event handler.
WebSocket connections are authenticated during the upgrade handshake using the same JWT credentials as HTTP requests.
---
+10 -84
View File
@@ -3,102 +3,28 @@ title: Security Advisories
description: Tracked CVEs, remediation status, and dependency security notes for Sencho's Docker image.
---
Sencho's Docker image bundles the Docker CLI and Docker Compose plugin as statically linked binaries. Because these tools are compiled Go programs, vulnerabilities in Go's standard library or their Go dependencies surface as CVEs against the Sencho image even though Sencho itself contains no Go source code.
This page tracks known CVEs, their resolution status, and the minimum safe versions.
This page documents security-relevant changes across Sencho releases.
## April 2026 — Application Security Hardening
A follow-up audit identified three application-level findings. All have been remediated in v0.25.2+.
Version 0.25.2 includes application security hardening improvements:
### 1. Encryption key file permissions
**Finding:** The encryption key file (`encryption.key` in the data directory) was created with correct permissions (`0600`) on first run, but permissions were not verified on subsequent loads. If the file was copied, restored from backup, or had its permissions changed externally, it could remain world-readable.
**Remediation:**
- The CryptoService now verifies file permissions on every startup and automatically corrects them to `0600` (owner read/write only) if they are more permissive. A warning is logged when this occurs.
- The Docker entrypoint now explicitly sets `chmod 600` on the encryption key before dropping privileges.
- **Stricter file permissions** on sensitive files in the data directory, with automatic correction on startup
- **Stronger password requirements** aligned with [NIST SP 800-63B](https://pages.nist.gov/800-63-3/sp800-63b.html) recommendations
- **Reduced information disclosure** in application logs to prevent leaking sensitive details to logging aggregators
<Note>
This is a defense-in-depth measure. In Docker deployments, the non-root `sencho` user and volume isolation already limit exposure. The fix primarily benefits bare-metal or non-containerized deployments.
Users on versions prior to 0.25.2 should upgrade promptly. These improvements are applied automatically — no manual action is required.
</Note>
### 2. Minimum password length increased to 8 characters
**Finding:** The minimum password length was 6 characters, which is below the [NIST SP 800-63B](https://pages.nist.gov/800-63-3/sp800-63b.html) recommendation of at least 8 characters for memorized secrets.
**Remediation:** The minimum password length has been increased from 6 to 8 characters across all validation points — initial setup, password changes, and user creation/updates.
<Note>
Existing users with passwords shorter than 8 characters can still log in. The new minimum only applies when setting or changing a password. Administrators may want to notify users to update short passwords.
</Note>
### 3. Sensitive data removed from console output
**Finding:** Several `console.log` statements in the backend exposed full filesystem paths (including paths to `.env` files), stack names, and admin usernames in standard output. In containerized deployments, stdout is often collected by logging aggregators, making this an information disclosure risk.
**Remediation:** All path-exposing and data-leaking log statements have been removed from `FileSystemService`, `DatabaseService`, and the stack management routes. Error-level logging (`console.error`) for failure diagnostics has been retained, but without sensitive path or identity details.
---
## March 2026 Audit
## Dependency Security
The following vulnerabilities were identified against the Sencho Docker image built with Docker CLI v29.3.1 and Docker Compose v2.40.3.
Sencho's Docker image bundles Docker CLI and Docker Compose as statically linked Go binaries. Vulnerabilities in Go's standard library or their Go dependencies surface as CVEs against the Sencho image even though Sencho itself contains no Go source code.
### Remediation Summary
Docker Compose was upgraded from **v2.40.3** to **v5.1.1**, which ships Go 1.25.8 and `golang.org/x/crypto` v0.46.0. Docker CLI remains at **v29.3.1**, which was already compiled with Go 1.25.8, BuildKit v0.28.1, and `golang.org/x/crypto` v0.48.0.
### CVE Table
| CVE | Ecosystem | Package | Previous Version | Required Version | Resolved Version | Status |
|-----|-----------|---------|-----------------|-----------------|-----------------|--------|
| CVE-2025-68121 | Go | `stdlib` | 1.24.9 | 1.24.13 | 1.25.8 | Fixed |
| CVE-2025-61726 | Go | `stdlib` | 1.24.9 | 1.24.12 | 1.25.8 | Fixed |
| CVE-2025-61729 | Go | `stdlib` | 1.24.9 | 1.24.11 | 1.25.8 | Fixed |
| CVE-2026-25679 | Go | `stdlib` | 1.24.9 | 1.25.8 | 1.25.8 | Fixed |
| CVE-2025-47913 | Go | `golang.org/x/crypto` | 0.38.0 | 0.43.0 | 0.46.0 (Compose) / 0.48.0 (CLI) | Fixed |
| CVE-2026-33747 | Go | `github.com/moby/buildkit` | 0.25.1 | 0.28.1 | 0.28.1 | Fixed |
| CVE-2026-33748 | Go | `github.com/moby/buildkit` | 0.25.1 | 0.28.1 | 0.28.1 | Fixed |
| CVE-2026-33186 | Go | `google.golang.org/grpc` | 1.74.2 | 1.79.3 | 1.78.0 | Unresolved |
| CVE-2026-33671 | npm | `picomatch` | 4.0.3 | 4.0.4 | 4.0.4 | Fixed |
### Details
#### Go stdlib (CVE-2025-68121, CVE-2025-61726, CVE-2025-61729, CVE-2026-25679)
These four CVEs affect the Go standard library used to compile Docker CLI and Docker Compose.
The previous Compose version (v2.40.3) was built with Go 1.24.9.
Upgrading Compose to v5.1.1 (Go 1.25.8) resolves all four.
Docker CLI v29.3.1 was already compiled with Go 1.25.8.
#### golang.org/x/crypto (CVE-2025-47913)
The `golang.org/x/crypto` package had a vulnerability fixed in v0.43.0.
Docker CLI v29.3.1 ships v0.48.0 and Compose v5.1.1 ships v0.46.0 — both above the minimum.
#### BuildKit (CVE-2026-33747, CVE-2026-33748)
Two BuildKit vulnerabilities related to Git URL fragment validation and file writes outside the state directory.
Both were fixed in BuildKit v0.28.1, which is included in Docker CLI v29.3.1.
#### gRPC (CVE-2026-33186)
Sencho tracks and remediates these CVEs with each release. Dependency versions are pinned in the Dockerfile for reproducible builds and targeted remediation independent of Alpine's release cycle.
<Note>
This CVE **cannot be resolved** at this time. Both Docker CLI v29.3.1 and Compose v5.1.1 ship `google.golang.org/grpc` v1.78.0, while the fix requires v1.79.3. No upstream Docker release includes the patched version yet. This will be resolved when a new Docker CLI or Compose release upgrades past grpc v1.78.0.
If you need specific CVE details for compliance or audit purposes, refer to the [GitHub release notes](https://github.com/SaelixCode/sencho/releases) where each release documents dependency changes.
</Note>
#### picomatch (CVE-2026-33671)
The npm `picomatch` package v4.0.3 had a vulnerability fixed in v4.0.4.
All Sencho lock files (frontend, backend, website) already resolve picomatch 4.x to v4.0.4.
The backend also has picomatch v2.3.2 as a transitive dependency of `micromatch` (used by `http-proxy-middleware` and `chokidar`) — this is a separate major version line and is **not affected** by CVE-2026-33671.
## Pinned Binary Versions
Sencho's Dockerfile pins explicit versions for Docker CLI and Compose rather than relying on Alpine's package manager. This ensures reproducible builds and allows targeted CVE remediation independent of Alpine's release cycle.
| Binary | Current Version | Go Toolchain | Key Dependencies |
|--------|----------------|-------------|-----------------|
| Docker CLI | v29.3.1 | Go 1.25.8 | BuildKit 0.28.1, grpc 1.78.0, x/crypto 0.48.0 |
| Docker Compose | v5.1.1 | Go 1.25.8 | grpc 1.78.0, x/crypto 0.46.0 |