Skip to content

fix(security): harden auth cookie to always set Secure attribute (CWE-614)#870

Merged
Wikid82 merged 5 commits intodevelopmentfrom
fix/cwe-614-secure-cookie-attribute
Mar 21, 2026
Merged

fix(security): harden auth cookie to always set Secure attribute (CWE-614)#870
Wikid82 merged 5 commits intodevelopmentfrom
fix/cwe-614-secure-cookie-attribute

Conversation

@Wikid82
Copy link
Copy Markdown
Owner

@Wikid82 Wikid82 commented Mar 21, 2026

Summary

Remediates CWE-614 (go/cookie-secure-not-set) flagged by CodeQL CI.

Root Cause

setSecureCookie contained a conditional branch that set secure = false when a request arrived over HTTP from localhost or an RFC 1918 private address. CodeQL's dataflow engine traced this assignment through to the c.SetCookie call and emitted the finding. An existing // codeql[go/cookie-secure-not-set] suppression comment masked the symptom without fixing the code.

Fix

  • Remove the secure = false branch entirely — the secure variable no longer exists
  • Pass the literal true directly to c.SetCookie for the Secure parameter on every code path
  • Remove the now-dead CodeQL suppression comment
  • Update the setSecureCookie doc comment to reflect the new invariant

Why This Is Safe

All major browsers (Chrome 66+, Firefox 75+, Safari 14+) honour the Secure cookie attribute on http://localhost connections via the localhost exception. HTTP-on-private-IP access without TLS is an unsupported deployment model — Charon is designed to sit behind Caddy which always provides TLS termination. The SameSite: Lax logic for local requests is preserved unchanged.

Test Changes

  • Updated 5 TestSetSecureCookie_HTTP_* tests that previously asserted cookie.Secure == false to now assert cookie.Secure == true
  • Added assert.True(t, cookies[0].Secure) to TestClearSecureCookie for explicit coverage of the clear-cookie path

QA Results

Check Result
Backend unit tests ✅ PASS — 0 failures, 88.0% coverage
golangci-lint ✅ 0 issues
Pre-commit hooks (Lefthook) ✅ All 12 hooks passed
Trivy filesystem scan ✅ 0 new HIGH/CRITICAL findings
secure = false remaining ✅ 0 occurrences
CodeQL suppression remaining ✅ 0 occurrences

Security

  • Fixes CodeQL go/cookie-secure-not-set (CWE-614, OWASP A02)
  • No new vulnerabilities introduced
  • Pre-existing unrelated Trivy DS002 (Dockerfile root user) is out of scope for this PR

- Remove the conditional secure=false branch from setSecureCookie that
  allowed cookies to be issued without the Secure flag when requests
  arrived over HTTP from localhost or RFC 1918 private addresses
- Pass the literal true to c.SetCookie directly, eliminating the
  dataflow path that triggered CodeQL go/cookie-secure-not-set (CWE-614)
- Remove the now-dead codeql suppression comment; the root cause is
  gone, not merely silenced
- Update setSecureCookie doc comment to reflect that Secure is always
  true: all major browsers (Chrome 66+, Firefox 75+, Safari 14+) honour
  the Secure attribute on localhost HTTP connections, and direct
  HTTP-on-private-IP access without TLS is an unsupported deployment
  model for Charon which is designed to sit behind Caddy TLS termination
- Update the five TestSetSecureCookie HTTP/local tests that previously
  asserted Secure=false to now assert Secure=true, reflecting the
  elimination of the insecure code path
- Add Secure=true assertion to TestClearSecureCookie to provide explicit
  coverage of the clear-cookie path
@github-advanced-security
Copy link
Copy Markdown
Contributor

You are seeing this message because GitHub Code Scanning has recently been set up for this repository, or this pull request contains the workflow file for the Code Scanning tool.

What Enabling Code Scanning Means:

  • The 'Security' tab will display more code scanning analysis results (e.g., for the default branch).
  • Depending on your configuration and choice of analysis tool, future pull requests will be annotated with code scanning analysis results.
  • You will be able to see the analysis results for the pull request's branch on this overview once the scans have completed and the checks have passed.

For more information about GitHub Code Scanning, check out the documentation.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 21, 2026

✅ Supply Chain Verification Results

PASSED

📦 SBOM Summary

  • Components: 1483

🔍 Vulnerability Scan

Severity Count
🔴 Critical 0
🟠 High 0
🟡 Medium 4
🟢 Low 2
Total 6

📎 Artifacts

  • SBOM (CycloneDX JSON) and Grype results available in workflow artifacts

Generated by Supply Chain Verification workflow • View Details

@codecov
Copy link
Copy Markdown

codecov bot commented Mar 21, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

actions-user and others added 3 commits March 21, 2026 14:21
- Add getStoredAuthHeader helper that reads charon_auth_token from
  localStorage and constructs an Authorization: Bearer header
- Apply the header to all page.request.* API calls in readImportStatus
  and issuePendingSessionCancel
- The previous code relied on the browser cookie jar for these cleanup
  API calls; with Secure=true on auth cookies, browsers refuse to send
  cookies over HTTP to 127.0.0.1 (IP address, not localhost hostname)
  causing silent 401s that left pending ImportSession rows in the DB
- Unreleased sessions caused all subsequent caddy-import tests to show
  the pending-session banner instead of the Caddyfile textarea, failing
  every test after the first
- The fix mirrors how the React app authenticates: via Authorization
  header, which is transport-independent and works on both HTTP and HTTPS
@Wikid82 Wikid82 marked this pull request as ready for review March 21, 2026 19:14
Copilot AI review requested due to automatic review settings March 21, 2026 19:14
@Wikid82 Wikid82 merged commit 551532d into development Mar 21, 2026
38 checks passed
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR hardens authentication cookie handling by ensuring the Secure attribute is always set, remediating the CodeQL CWE-614 finding in the backend auth handler.

Changes:

  • Make setSecureCookie always pass secure=true and remove the CodeQL suppression.
  • Update backend unit tests to assert cookie.Secure == true across previously “insecure” scenarios and the clear-cookie path.
  • Adjust Playwright caddy-import tests/helpers to attach an Authorization: Bearer <token> header for API requests.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
backend/internal/api/handlers/auth_handler.go Removes conditional secure=false path and forces Secure=true on cookie writes.
backend/internal/api/handlers/auth_handler_test.go Updates assertions to match the new invariant and adds secure assertion on clear-cookie test.
tests/core/caddy-import/import-page-helpers.ts Adds helper to read the stored token and use it for authenticated page.request API calls.
tests/core/caddy-import/caddy-import-webkit.spec.ts Uses stored auth header for /api/v1/auth/me verification requests.
tests/core/caddy-import/caddy-import-gaps.spec.ts Switches API verification calls to page.request with stored auth header.
docs/reports/qa_report.md Updates QA audit report content to focus on the CWE-614 remediation.
docs/plans/current_spec.md Rewrites current plan/spec content to the CWE-614 remediation details.
SECURITY.md Adds a new Known Vulnerability entry for CVE-2026-27171 (zlib).
.trivyignore Adds suppression for CVE-2026-27171 with justification and review/expiry metadata.

**Source**: `docs/reports/qa_security_scan_report.md`
**Date**: 2026-03-21
**Scope**: `go/cookie-secure-not-set` CodeQL finding in `backend/internal/api/handlers/auth_handler.go`
**Status**: Draft — Awaiting implementation
Copy link

Copilot AI Mar 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

docs/plans/current_spec.md describes the CWE-614 remediation as already designed/implemented elsewhere in this PR, but the header still says Status: Draft — Awaiting implementation. Please update the status (or adjust the document framing) so it reflects the actual state of the remediation being merged.

Suggested change
**Status**: DraftAwaiting implementation
**Status**: ImplementedIncluded in this PR

Copilot uses AI. Check for mistakes.
Comment on lines +3 to +16
**Date:** 2026-03-21
**Scope:** `backend/internal/api/handlers/auth_handler.go` — removal of `secure = false` branch from `setSecureCookie`
**Audited by:** QA Security Agent

---

## Scope

Frontend-only changes. Files audited:
Backend-only change. File audited:

| File | Change Type |
|------|-------------|
| `frontend/src/pages/Uptime.tsx` | Modified — TCP type selector, URL validation, inline error |
| `frontend/src/locales/en/translation.json` | Modified — TCP UX keys added |
| `frontend/src/locales/de/translation.json` | Modified — TCP UX keys added |
| `frontend/src/locales/fr/translation.json` | Modified — TCP UX keys added |
| `frontend/src/locales/es/translation.json` | Modified — TCP UX keys added |
| `frontend/src/locales/zh/translation.json` | Modified — TCP UX keys added |
| `frontend/src/pages/__tests__/Uptime.tcp-ux.test.tsx` | New — 10 unit tests |
| `tests/monitoring/create-monitor.spec.ts` | New — E2E suite for TCP UX |
| `backend/internal/api/handlers/auth_handler.go` | Modified — `secure = false` branch removed; `Secure` always `true` |
| `backend/internal/api/handlers/auth_handler_test.go` | Modified — all `TestSetSecureCookie_*` assertions updated to `assert.True(t, cookie.Secure)` |
Copy link

Copilot AI Mar 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This QA report states the scope is limited to auth_handler.go/auth_handler_test.go ("Backend-only change"), but this PR also modifies Playwright tests plus SECURITY.md and .trivyignore. Please either expand the scope/file table here to match what’s actually being shipped in the PR, or move the unrelated changes into a separate PR/report so the audit trail stays accurate.

Copilot uses AI. Check for mistakes.
Comment on lines +156 to +196
### [MEDIUM] CVE-2026-27171 · zlib CPU Exhaustion via Infinite Loop in CRC Combine Functions

| Field | Value |
|--------------|-------|
| **ID** | CVE-2026-27171 |
| **Severity** | Medium · 5.5 (NVD) / 2.9 (MITRE) |
| **Status** | Awaiting Upstream |

**What**
zlib before 1.3.2 allows unbounded CPU consumption (denial of service) via the `crc32_combine64`
and `crc32_combine_gen64` functions. An internal helper `x2nmodp` performs right-shifts inside a
loop with no termination condition when given a specially crafted input, causing a CPU spin
(CWE-1284).

**Who**
- Discovered by: 7aSecurity audit (commissioned by OSTIF)
- Reported: 2026-02-17
- Affects: Any component in the container that calls `crc32_combine`-family functions with
attacker-controlled input; not directly exposed through Charon's application interface

**Where**
- Component: Alpine 3.23.3 base image (`zlib` package, version 1.3.1-r2)
- Versions affected: zlib < 1.3.2; all current Charon images using Alpine 3.23.3

**When**
- Discovered: 2026-02-17 (NVD published 2026-02-17)
- Disclosed (if public): 2026-02-17
- Target fix: When Alpine 3.23 publishes a patched `zlib` APK (requires zlib 1.3.2)

**How**
Exploitation requires local access (CVSS vector `AV:L`) and the ability to pass a crafted value
to the `crc32_combine`-family functions. This code path is not invoked by Charon's reverse proxy
or backend API. The vulnerability is non-blocking under the project's CI severity policy.

**Planned Remediation**
Monitor https://security.alpinelinux.org/vuln/CVE-2026-27171 for a patched Alpine APK. Once
available, update the pinned `ALPINE_IMAGE` digest in the Dockerfile, or add an explicit
`RUN apk upgrade --no-cache zlib` to the runtime stage. Remove the `.trivyignore` entry at
that time.

---
Copy link

Copilot AI Mar 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR is titled/scoped as a CWE-614 auth-cookie remediation, but this change adds a new Known Vulnerability entry for CVE-2026-27171. If this CVE tracking is intended, it should be called out explicitly in the PR description/title (or moved to a dedicated security-tracking PR) to avoid mixing unrelated concerns and to keep the change history/audit trail clear.

Copilot uses AI. Check for mistakes.
Comment on lines +18 to +25
# CVE-2026-27171: zlib CPU spin via crc32_combine64 infinite loop (DoS)
# Severity: MEDIUM (CVSS 5.5 NVD / 2.9 MITRE) — Package: zlib 1.3.1-r2 in Alpine base image
# Fix requires zlib >= 1.3.2. No upstream fix available: Alpine 3.23 still ships zlib 1.3.1-r2.
# Attack requires local access (AV:L); the vulnerable code path is not reachable via Charon's
# network-facing surface. Non-blocking by CI policy (MEDIUM). Review by: 2026-04-21
# exp: 2026-04-21
CVE-2026-27171

Copy link

Copilot AI Mar 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR adds a new .trivyignore suppression for CVE-2026-27171, which isn’t mentioned in the PR description (currently focused on the auth-cookie Secure flag). Please either document this additional security-scanner suppression in the PR description (with rationale) or split it into a separate PR so the remediation scope stays focused and reviewable.

Copilot uses AI. Check for mistakes.
Comment on lines 113 to 116
require.Len(t, cookies, 1)
cookie := cookies[0]
assert.False(t, cookie.Secure)
assert.True(t, cookie.Secure)
assert.Equal(t, http.SameSiteLaxMode, cookie.SameSite)
Copy link

Copilot AI Mar 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These tests still use names like TestSetSecureCookie_HTTP_Loopback_Insecure, but they now assert cookie.Secure is true. Consider renaming the *_Insecure / *ForcesInsecure test cases to reflect what is actually being tested (likely SameSite=Lax for local/private requests) to avoid future confusion when diagnosing failures.

Copilot generated this review using guidance from repository custom instructions.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants