Skip to content

Commit d46ae06

Browse files
committed
feat: csp nonce + replaced ansi-to-html with ansi_up - better class application
1 parent 347eef9 commit d46ae06

12 files changed

Lines changed: 320 additions & 152 deletions

File tree

.github/workflows/release-deploy.yml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,11 +129,14 @@ jobs:
129129
MAILJET_FROM_ADDRESS: ${{ secrets.MAILJET_FROM_ADDRESS }}
130130
MAILJET_HOST: ${{ secrets.MAILJET_HOST }}
131131
GRAFANA_ALERT_RECIPIENTS: ${{ secrets.GRAFANA_ALERT_RECIPIENTS }}
132+
REDIS_PASSWORD: ${{ secrets.REDIS_PASSWORD }}
133+
MONGO_ROOT_USER: ${{ secrets.MONGO_ROOT_USER }}
134+
MONGO_ROOT_PASSWORD: ${{ secrets.MONGO_ROOT_PASSWORD }}
132135
with:
133136
host: ${{ secrets.DEPLOY_HOST }}
134137
username: ${{ secrets.DEPLOY_USER }}
135138
key: ${{ secrets.DEPLOY_SSH_KEY }}
136-
envs: GHCR_TOKEN,GHCR_USER,IMAGE_TAG,GRAFANA_ADMIN_USER,GRAFANA_ADMIN_PASSWORD,MAILJET_API_KEY,MAILJET_SECRET_KEY,MAILJET_FROM_ADDRESS,MAILJET_HOST,GRAFANA_ALERT_RECIPIENTS
139+
envs: GHCR_TOKEN,GHCR_USER,IMAGE_TAG,GRAFANA_ADMIN_USER,GRAFANA_ADMIN_PASSWORD,MAILJET_API_KEY,MAILJET_SECRET_KEY,MAILJET_FROM_ADDRESS,MAILJET_HOST,GRAFANA_ALERT_RECIPIENTS,REDIS_PASSWORD,MONGO_ROOT_USER,MONGO_ROOT_PASSWORD
137140
command_timeout: 10m
138141
script: |
139142
set -e
@@ -153,6 +156,9 @@ jobs:
153156
export MAILJET_FROM_ADDRESS="$MAILJET_FROM_ADDRESS"
154157
export GF_SMTP_HOST="$MAILJET_HOST"
155158
export GRAFANA_ALERT_RECIPIENTS="$GRAFANA_ALERT_RECIPIENTS"
159+
export REDIS_PASSWORD="$REDIS_PASSWORD"
160+
export MONGO_ROOT_USER="$MONGO_ROOT_USER"
161+
export MONGO_ROOT_PASSWORD="$MONGO_ROOT_PASSWORD"
156162
docker compose pull
157163
docker compose up -d --remove-orphans --no-build --wait --wait-timeout 180
158164

docs/SECURITY.md

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,55 @@ Security patches go into `main` and the latest release. If you're running someth
44

55
## Reporting vulnerabilities
66

7-
Found a security issue? Don't open a public GitHub issue - email [max.azatian@gmail.com](mailto:max.azatian@gmail.com) instead.
7+
Found a security issue? Don't open a public GitHub issue - email [max.azatian@gmail.com](mailto:max.azatian@gmail.com)
8+
instead.
89

9-
Include what you can: vulnerability type, where it occurs, reproduction steps, PoC if you have one. You'll get an acknowledgment within 48 hours. If confirmed, we'll patch it and credit you in the disclosure (unless you prefer to stay anonymous).
10+
Include what you can: vulnerability type, where it occurs, reproduction steps, PoC if you have one. You'll get an
11+
acknowledgment within 48 hours. If confirmed, we'll patch it and credit you in the disclosure (unless you prefer to stay
12+
anonymous).
1013

1114
## Automated scanning
1215

13-
The CI pipeline runs [Bandit](https://bandit.readthedocs.io/) on the Python backend for static analysis, and [Dependabot](https://docs.github.com/en/code-security/dependabot) keeps dependencies patched across Python, npm, and Docker. For SBOM generation and vulnerability scanning, see [Supply Chain Security](security/supply-chain.md).
16+
The CI pipeline runs [Bandit](https://bandit.readthedocs.io/) on the Python backend for static analysis,
17+
and [Dependabot](https://docs.github.com/en/code-security/dependabot) keeps dependencies patched across Python, npm, and
18+
Docker. For SBOM generation and vulnerability scanning, see [Supply Chain Security](security/supply-chain.md).
19+
20+
## Frontend hardening
21+
22+
The frontend uses a nonce-based Content Security Policy:
23+
24+
- **`script-src 'nonce-...'`** — blocks injected `<script>` tags (XSS). Nonce is per-request, generated by nginx.
25+
- **`style-src-elem 'nonce-...'`** — blocks injected `<style>` tags.
26+
- **`style-src-attr 'unsafe-inline'`** — allows `style=""` attributes (required by Svelte transitions and CodeMirror).
27+
28+
Nonce injection is handled by nginx's `sub_filter` directive.
29+
See [Nginx Configuration](operations/nginx-configuration.md#nonce-injection) for the full mechanism.
1430

1531
## Runtime hardening
1632

17-
Executor pods run user code with non-root users, read-only filesystems, dropped capabilities, and no service account tokens. Network policies deny all traffic by default. Details in [Network Isolation](security/policies.md).
33+
Executor pods run user code with non-root users, read-only filesystems, dropped capabilities, user namespace isolation (
34+
`host_users: false`), and no service account tokens. An optional sandboxed runtime (e.g., gVisor) can be configured via
35+
`K8S_POD_RUNTIME_CLASS_NAME`.
36+
37+
At the namespace level, the k8s_worker automatically applies:
38+
39+
- **NetworkPolicy** — default-deny ingress + egress for executor pods (blocks lateral movement and exfiltration)
40+
- **ResourceQuota** — caps aggregate pod, CPU, and memory consumption
41+
- **Pod Security Admission**`restricted` profile enforced via namespace labels
42+
43+
Details in [Pod & Namespace Security](security/policies.md).
44+
45+
## Authentication
46+
47+
Password hashing uses `pwdlib` with `BcryptHasher` (configurable rounds). Authentication is cookie-based JWT with CSRF
48+
protection via the double-submit pattern. See [Authentication](architecture/authentication.md).
49+
50+
## Infrastructure
51+
52+
- Redis is password-protected (`--requirepass`)
53+
- MongoDB uses authentication (`authSource=admin`)
54+
- All database ports bound to `127.0.0.1` (not exposed to host network)
55+
- Docker image versions are pinned to specific patches
56+
- TLS everywhere (self-signed for development, generated by `cert-generator` container)
1857

19-
Secrets stay out of the repo - `.env` files and credentials are your responsibility to manage in deployment.
58+
Secrets stay out of the repo `.env` files and credentials are your responsibility to manage in deployment.

0 commit comments

Comments
 (0)