Files
Charon/docs/reports/qa_report.md

7.9 KiB
Raw Blame History

QA/Security Audit Report — CVE Remediation (curl / binutils / libc-utils)

Date: 2026-03-13 Branch: feature/beta-release Scope: Full audit after removing curl, binutils, libc-utils from runtime image; substituting wget; updating .grype.yaml Auditor: QA Security Agent


Overall Verdict: PASS

All blocking gates cleared. The three HIGH CVEs targeted by this remediation are confirmed absent from the runtime image. One additional critical gap (docker-compose health checks still referencing the removed curl binary) was discovered and corrected during Step 1.


CVE Remediation Verification

Confirmed Eliminated

CVE Package Method Verified
CVE-2026-3805 (HIGH) curl 8.17.0-r1 Removed from apk add in runtime stage
CVE-2025-69650 (HIGH) binutils 2.45.1-r0 Removed from apk add in runtime stage
CVE-2025-69649 (HIGH) binutils 2.45.1-r0 Removed from apk add in runtime stage

Side-effect MEDIUMs eliminated: 8 (5× curl MEDIUMs, 3× binutils MEDIUMs).

.grype.yaml State

Entry Status
CVE-2026-22184 (zlib) Removed — resolved by upstream Alpine fix
GHSA-69x3-g4r3-p962 (nebula in caddy) Retained — extended to 2026-04-12; upstream still pinned to old nebula

Gate Summary

# Gate Result Details
1 E2E Container Rebuild PASS Built fresh; healthy in <5s after fixing compose health checks
2 E2E Playwright Tests PASS 868 passed, 1 pre-existing failure, 0 flaky
3 Local Patch Coverage Preflight PASS 93.1% overall (threshold: 90%)
4 Backend Unit Tests & Coverage PASS 88.2% line coverage (gate: ≥87%)
5 Frontend Unit Tests & Coverage PASS 89.73% line coverage
6 TypeScript Type Check PASS 0 errors
7 Pre-commit Hooks SKIP No .pre-commit-config.yaml in project
8 Trivy Filesystem Scan PASS 0 CRITICAL, 0 HIGH, 0 total
9 Docker Image Scan (Grype) PASS 0 CRITICAL, 0 HIGH
10 CodeQL (Go + JavaScript) PASS 0 errors, 0 warnings
11 Linting (ESLint + golangci-lint) PASS 0 errors; pre-existing warnings only

Step Details

1. E2E Container Rebuild

Image rebuilt from scratch (212s build time). Container reached healthy in <5s. Confirmed HEALTHCHECK passes against /api/v1/health using wget. Image SHA: ae066857e8c0.

See Incidental Findings — all five docker-compose files still had curl in their health check definitions; corrected before rebuild was confirmed healthy.

2. E2E Playwright Tests (Chromium + Firefox + WebKit)

Metric Count
Passed 868
Failed 1
Skipped 1007
Flaky 0
Duration ~30 min

Failure:

core/multi-component-workflows.spec.ts > Multi-Component Workflows
   User with proxy creation role is configured for proxy management [firefox]
  Error: invalid credentials

Pre-existing test-isolation flakiness with dynamically-created users. Not related to CVE changes. No regression introduced.

3. Local Patch Coverage Preflight

Scope Changed Lines Covered Lines Coverage
Overall 58 54 93.1%
Backend 52 48 92.3%
Frontend 6 6 100.0%

Uncovered: notification_service.go L462463, L466467 (dead code paths, accepted).

4. Backend Unit Tests & Coverage

Metric Value
Statement coverage 87.9%
Line coverage 88.2%
Gate (min) 87%
Status Met

5. Frontend Unit Tests & Coverage

Data from frontend/coverage/coverage-summary.json (2026-03-13 06:05). No frontend files were modified by this remediation.

Metric Value
Lines 89.73%
Statements 89.01%
Functions 86.18%
Branches 81.21%

6. TypeScript Type Check

tsc --noEmit  →  exit 0 (0 errors)

7. Pre-commit Hooks

SKIP — No .pre-commit-config.yaml exists in the project. Git hooks are managed via lefthook; ESLint and golangci-lint run explicitly in Step 11.

8. Trivy Filesystem Scan

Target Type CRITICAL HIGH MEDIUM LOW
backend/go.mod gomod 0 0 0 0
frontend/package-lock.json npm 0 0 0 0
package-lock.json npm 0 0 0 0

Scanners: vuln,secret. Zero findings.

9. Docker Image Scan (Grype)

Severity Count
🔴 CRITICAL 0
🟠 HIGH 0
🟡 MEDIUM 4
🟢 LOW 2

MEDIUM (non-blocking, no Alpine fix available):

CVE Package(s) Version
CVE-2025-60876 busybox, busybox-binsh, busybox-extras, ssl_client 1.37.0-r30

LOW (non-blocking):

ID Package Notes
GHSA-fw7p-63qq-7hpr filippo.io/edwards25519 v1.1.0 2 instances; fixed in v1.1.1

Suppressed (documented in .grype.yaml):

ID Package Expiry Justification
GHSA-69x3-g4r3-p962 nebula (embedded in caddy) 2026-04-12 smallstep/certificates still requires nebula v1.9.x; reviewed 2026-03-13

10. CodeQL Static Analysis

Language Errors Warnings Files Scanned
Go 0 0 Full backend
JavaScript/TypeScript 0 0 354/354 files

11. Linting

ESLint (frontend):

  • 0 errors, 857 warnings (all pre-existing non-blocking patterns)
  • Exit 0

golangci-lint (backend):

  • 0 errors, 53 warnings (all pre-existing)
    • gocritic×50, gosec×2, bodyclose×1
  • Pre-existing gosec findings (not introduced by this change):
    • mail_service.go:195 G203 — template.HTML() cast (no XSS vector in current usage)
    • docker_service_test.go:231 G306 — os.WriteFile(0o660) in test fixture
  • Exit 0

Incidental Findings

CRITICAL — Corrected During Audit

docker-compose health checks still referenced curl after CVE remediation

All five docker-compose files retained curl-based healthcheck.test definitions. Since curl is no longer present in the runtime image, any container started from these files would enter and remain in the unhealthy state. This was confirmed during Step 1 (container failed health checks immediately after first rebuild).

Root cause: The Dockerfile HEALTHCHECK and .docker/docker-entrypoint.sh were correctly migrated to wget, but the compose healthcheck overrides were not updated in the same commit.

Files corrected:

File Change
.docker/compose/docker-compose.playwright-local.yml curl -fsSwget -qO /dev/null
.docker/compose/docker-compose.playwright-ci.yml curl -sfwget -qO /dev/null
.docker/compose/docker-compose.test.yml ["CMD","curl","-f",...] → `["CMD-SHELL","wget -qO /dev/null ...
.docker/compose/docker-compose.local.yml curl -fsSwget -qO /dev/null
.docker/compose/docker-compose.yml curl -fsSwget -qO /dev/null

Minor — Corrected During Audit

Stale comment in Dockerfile

Removed comment # binutils provides objdump for debug symbol detection in docker-entrypoint.sh from Dockerfile — binutils is no longer installed; the comment was stale and misleading.


Remediation Confirmation

Blocker Status
CVE-2026-3805 (curl HIGH) Eliminated — curl removed from runtime image
CVE-2025-69650 (binutils HIGH) Eliminated — binutils removed from runtime image
CVE-2025-69649 (binutils HIGH) Eliminated — binutils removed from runtime image
libc-utils removed from runtime Confirmed absent
wget substituted everywhere curl was used Dockerfile, entrypoint, all 5 compose files