150 lines
6.3 KiB
Markdown
150 lines
6.3 KiB
Markdown
|
||
# Security Remediation Plan — DoD Failures (CodeQL + Trivy)
|
||
|
||
**Created:** 2026-01-09
|
||
|
||
This plan addresses the **HIGH/CRITICAL security findings** reported in [docs/reports/qa_report.md](docs/reports/qa_report.md).
|
||
|
||
> The prior Codecov patch-coverage plan was moved to [docs/plans/patch_coverage_spec.md](docs/plans/patch_coverage_spec.md).
|
||
|
||
## Goal
|
||
|
||
Restore DoD to ✅ PASS by eliminating **all HIGH/CRITICAL** findings from:
|
||
|
||
- CodeQL (Go + JS) results produced by **Security: CodeQL All (CI-Aligned)**
|
||
- Trivy results produced by **Security: Trivy Scan**
|
||
|
||
Hard constraints:
|
||
|
||
- Do **not** weaken gates (no suppressing findings unless a false-positive is proven and documented).
|
||
- Prefer minimal, targeted changes.
|
||
- Avoid adding new runtime dependencies.
|
||
|
||
## Scope
|
||
|
||
From the QA report:
|
||
|
||
### CodeQL Go
|
||
|
||
- Rule: `go/email-injection` (**CRITICAL**)
|
||
- Location: `backend/internal/services/mail_service.go` (reported around lines ~222, ~340, ~393)
|
||
|
||
### CodeQL JS
|
||
|
||
- Rule: `js/incomplete-hostname-regexp` (**HIGH**)
|
||
- Location: `frontend/src/pages/__tests__/ProxyHosts-extra.test.tsx` (reported around line ~252)
|
||
|
||
### Trivy
|
||
|
||
QA report note: Trivy filesystem scan may be picking up **workspace caches/artifacts** (e.g., `.cache/go/pkg/mod/...` and other generated directories) in addition to repo-tracked files, while the **image scan may already be clean**.
|
||
|
||
## Step 0 — Trivy triage (required first)
|
||
|
||
Objective: Re-run the current Trivy task and determine whether HIGH/CRITICAL findings are attributable to:
|
||
|
||
- **Repo-tracked paths** (e.g., `backend/go.mod`, `backend/go.sum`, `Dockerfile`, `frontend/`, etc.), or
|
||
- **Generated/cache paths** under the workspace (e.g., `.cache/`, `**/*.cover`, `codeql-db-*`, temporary build outputs).
|
||
|
||
Steps:
|
||
|
||
1. Run **Security: Trivy Scan**.
|
||
2. For each HIGH/CRITICAL item, record the affected file path(s) reported by Trivy.
|
||
3. Classify each finding:
|
||
- **Repo-tracked**: path is under version control (or clearly part of the shipped build artifact, e.g., the built `app/charon` binary or image layers).
|
||
- **Scan-scope noise**: path is a workspace cache/artifact directory not intended as deliverable input.
|
||
|
||
Decision outcomes:
|
||
|
||
- If HIGH/CRITICAL are **repo-tracked / shipped** → remediate by upgrading only the affected components to Trivy’s fixed versions (see Workstreams C/D).
|
||
- If HIGH/CRITICAL are **only cache/artifact paths** → treat as scan-scope noise and align Trivy scan scope to repo contents by excluding those directories (without disabling scanners or suppressing findings).
|
||
|
||
## Workstreams (by role)
|
||
|
||
### Workstream A — Backend (Backend_Dev): Fix `go/email-injection`
|
||
|
||
Objective: Ensure no untrusted data can inject additional headers/body content into SMTP `DATA`.
|
||
|
||
Implementation direction (minimal + CodeQL-friendly):
|
||
|
||
1. **Centralize email header construction** (avoid raw `fmt.Sprintf("%s: %s\r\n", ...)` with untrusted input).
|
||
2. **Reject** header values containing `\r` or `\n` (and other control characters if feasible).
|
||
3. Ensure email addresses are created using strict parsing/formatting (`net/mail`) and avoid concatenating raw address strings.
|
||
4. Add unit tests that attempt CRLF injection in subject/from/to and assert the send/build path rejects it.
|
||
|
||
Acceptance criteria:
|
||
|
||
- CodeQL Go scan shows **0** `go/email-injection` findings.
|
||
- Backend unit tests cover the rejection paths.
|
||
|
||
### Workstream B — Frontend (Frontend_Dev): Fix `js/incomplete-hostname-regexp`
|
||
|
||
Objective: Remove an “incomplete hostname regex” pattern flagged by CodeQL.
|
||
|
||
Preferred change:
|
||
|
||
- Replace hostname regex usage with an exact string match (or an anchored + escaped regex like `^link\.example\.com$`).
|
||
|
||
Acceptance criteria:
|
||
|
||
- CodeQL JS scan shows **0** `js/incomplete-hostname-regexp` findings.
|
||
|
||
### Workstream C — Container / embedded binaries (DevOps): Fix Trivy image finding
|
||
|
||
Objective: Ensure the built image does not ship `crowdsec`/`cscli` binaries that embed vulnerable `github.com/expr-lang/expr v1.17.2`.
|
||
|
||
Implementation direction:
|
||
|
||
1. If any changes are made to `Dockerfile` (including the CrowdSec build stage), rebuild the image (**no-cache recommended**) before validating.
|
||
2. Prefer **bumping the pinned CrowdSec version** in `Dockerfile` to a release that already depends on `expr >= 1.17.7`.
|
||
3. If no suitable CrowdSec release is available, patch the build in the CrowdSec build stage similarly to the existing Caddy stage override (force `expr@1.17.7` before building).
|
||
|
||
Acceptance criteria:
|
||
|
||
- Trivy image scan reports **0 HIGH/CRITICAL**.
|
||
|
||
### Workstream D — Go module upgrades (Backend_Dev + QA_Security): Fix Trivy repo scan findings
|
||
|
||
Objective: Eliminate Trivy filesystem-scan HIGH/CRITICAL findings without over-upgrading unrelated dependencies.
|
||
|
||
Implementation direction (conditional; driven by Step 0 triage):
|
||
|
||
1. If Trivy attributes HIGH/CRITICAL to `backend/go.mod` / `backend/go.sum` **or** to the built `app/charon` binary:
|
||
|
||
- Bump **only the specific Go modules Trivy flags** to Trivy’s fixed versions.
|
||
- Run `go mod tidy` and ensure builds/tests stay green.
|
||
|
||
1. If Trivy attributes HIGH/CRITICAL **only** to workspace caches / generated artifacts (e.g., `.cache/go/pkg/mod/...`):
|
||
|
||
- Treat as scan-scope noise and align Trivy’s filesystem scan scope to repo-tracked content by excluding those directories.
|
||
- This is **not** gate weakening: scanners stay enabled and the project must still achieve **0 HIGH/CRITICAL** in Trivy outputs.
|
||
|
||
Acceptance criteria:
|
||
|
||
- Trivy scan reports **0 HIGH/CRITICAL**.
|
||
|
||
## Validation (VS Code tasks)
|
||
|
||
Run tasks in this order (only run frontend ones if Workstream B changes anything under `frontend/`):
|
||
|
||
1. **Build: Backend**
|
||
2. **Test: Backend with Coverage**
|
||
3. **Security: CodeQL All (CI-Aligned)**
|
||
4. **Security: Trivy Scan** (explicitly verify **both** filesystem-scan and image-scan outputs are **0 HIGH/CRITICAL**)
|
||
5. **Lint: Pre-commit (All Files)**
|
||
|
||
If any changes are made to `Dockerfile` / CrowdSec build stage:
|
||
|
||
1. **Build & Run: Local Docker Image No-Cache** (recommended)
|
||
2. **Security: Trivy Scan** (re-verify image scan after rebuild)
|
||
|
||
If `frontend/` changes are made:
|
||
|
||
1. **Lint: TypeScript Check**
|
||
2. **Test: Frontend with Coverage**
|
||
3. **Lint: Frontend**
|
||
|
||
## Handoff checklist
|
||
|
||
- Attach updated `codeql-results-*.sarif` and Trivy artifacts for **both filesystem and image** outputs to the QA rerun.
|
||
- Confirm the QA report’s pass/fail criteria are satisfied (no HIGH/CRITICAL findings).
|