Compare commits

...

38 Commits

Author SHA1 Message Date
Jeremy
83b361ae57 Merge pull request #938 from Wikid82/nightly
Weekly: Promote nightly to main (2026-04-13)
2026-04-13 08:48:06 -04:00
Jeremy
7bd3a73bcf Merge pull request #935 from Wikid82/bot/update-geolite2-checksum
chore(docker): update GeoLite2-Country.mmdb checksum
2026-04-13 00:42:15 -04:00
Wikid82
00ba5b3650 chore(docker): update GeoLite2-Country.mmdb checksum
Automated checksum update for GeoLite2-Country.mmdb database.

Old: f5e80a9a3129d46e75c8cccd66bfac725b0449a6c89ba5093a16561d58f20bda
New: b018842033872f19ed9ccefb863ec954f8024db2ae913d0d4ea14e35ace4eba1

Auto-generated by: .github/workflows/update-geolite2.yml
2026-04-13 02:59:03 +00:00
Jeremy
062b86642d Merge pull request #927 from Wikid82/feature/beta-release
fix: dependency updates, CVE suppression management, and Renovate version constraints
2026-04-10 16:32:51 -04:00
GitHub Actions
a5724aecf9 fix: update indirect dependencies for golang.org/x/arch, modernc.org/libc, and modernc.org/sqlite to latest versions 2026-04-10 19:22:04 +00:00
GitHub Actions
53dccbe82b fix: update baseline-browser-mapping and call-bind versions for security and compatibility 2026-04-10 19:22:04 +00:00
Jeremy
8d6645415a Merge pull request #926 from Wikid82/renovate/feature/beta-release-non-major-updates
chore(deps): update non-major-updates (feature/beta-release)
2026-04-10 15:21:01 -04:00
renovate[bot]
4cfcc9aa02 chore(deps): update non-major-updates 2026-04-10 19:18:28 +00:00
Jeremy
5d384e4afa Merge pull request #925 from Wikid82/renovate/feature/beta-release-actions-github-script-9.x
chore(deps): update actions/github-script action to v9 (feature/beta-release)
2026-04-10 15:17:21 -04:00
Jeremy
5bf25fdebc Merge pull request #924 from Wikid82/renovate/feature/beta-release-non-major-updates
fix(deps): update non-major-updates (feature/beta-release)
2026-04-10 15:17:05 -04:00
Jeremy
253d1ddd29 Merge branch 'feature/beta-release' into renovate/feature/beta-release-actions-github-script-9.x 2026-04-10 11:58:09 -04:00
Jeremy
5eab41b559 Merge branch 'feature/beta-release' into renovate/feature/beta-release-non-major-updates 2026-04-10 11:57:50 -04:00
GitHub Actions
a076bb3265 chore(security): re-evaluate overdue CVE suppressions 2026-04-10 15:56:43 +00:00
Jeremy
9c85d9e737 Merge branch 'feature/beta-release' into renovate/feature/beta-release-actions-github-script-9.x 2026-04-10 11:41:55 -04:00
Jeremy
1de4ce6729 Merge branch 'feature/beta-release' into renovate/feature/beta-release-non-major-updates 2026-04-10 11:41:36 -04:00
GitHub Actions
8e0f88e8bd fix: add suppression for CVE-2026-32286 due to pgproto3/v2 buffer overflow vulnerability 2026-04-10 15:39:52 +00:00
GitHub Actions
36460a884e fix: enforce version constraints for pgx and go-jose modules to maintain compatibility 2026-04-10 15:26:36 +00:00
renovate[bot]
585ae9494d chore(deps): update actions/github-script action to v9 2026-04-10 15:11:56 +00:00
renovate[bot]
ed9d6fe5d8 fix(deps): update non-major-updates 2026-04-10 15:11:47 +00:00
Jeremy
f0147b1315 Merge pull request #921 from Wikid82/feature/beta-release
fix: resolve 5 HIGH-severity CVEs blocking nightly container image scan
2026-04-09 21:13:01 -04:00
GitHub Actions
615e5a95f5 fix: downgrade pgx/v4 to v4.18.3 to address buffer overflow vulnerability 2026-04-09 19:09:25 +00:00
Jeremy
5b85d18217 Merge pull request #923 from Wikid82/renovate/feature/beta-release-github.com-jackc-pgx-v4-5.x
chore(deps): update module github.com/jackc/pgx/v4 to v5 (feature/beta-release)
2026-04-09 14:31:42 -04:00
renovate[bot]
f05c24dd66 chore(deps): update module github.com/jackc/pgx/v4 to v5 2026-04-09 18:24:32 +00:00
GitHub Actions
fd11279aa3 fix: update security policy for CVE-2026-31790 and CVE-2026-2673 vulnerabilities 2026-04-09 17:59:56 +00:00
GitHub Actions
59282952b0 fix(ci): provide Go 1.26.2 toolchain for Renovate dependency lookups 2026-04-09 17:55:51 +00:00
GitHub Actions
8742c76d52 fix: add Grype ignore for unfixed Alpine OpenSSL CVE-2026-31790
No upstream fix available for libcrypto3/libssl3 in Alpine 3.23.3.
Accepted risk documented in SECURITY.md. Monitoring Alpine security
advisories for patch availability.
2026-04-09 17:52:04 +00:00
Jeremy
9c0193e812 Merge pull request #922 from Wikid82/renovate/feature/beta-release-non-major-updates
fix(deps): update non-major-updates (feature/beta-release)
2026-04-09 13:42:52 -04:00
renovate[bot]
64465e1cd9 fix(deps): update non-major-updates 2026-04-09 17:27:46 +00:00
GitHub Actions
580e20d573 fix: resolve 5 HIGH-severity CVEs blocking nightly container image scan
Patch vulnerable transitive dependencies across all three compiled
binaries in the Docker image (backend, Caddy, CrowdSec):

- go-jose/v3 and v4: JOSE/JWT validation bypass (CVE-2026-34986)
- otel/sdk: resource leak in OpenTelemetry SDK (CVE-2026-39883)
- pgproto3/v2: buffer overflow via pgx/v4 bump (CVE-2026-32286)
- AWS SDK v2: event stream injection in CrowdSec deps (GHSA-xmrv-pmrh-hhx2)
- OTel HTTP exporters: request smuggling (CVE-2026-39882)
- gRPC: bumped to v1.80.0 for transitive go-jose/v4 resolution

All Dockerfile patches include Renovate annotations for automated
future tracking. Renovate config extended to cover Go version and
GitHub Action refs in skill example workflows, preventing version
drift in non-CI files. SECURITY.md updated with pre-existing Alpine
base image CVE (no upstream fix available).

Nightly Go stdlib CVEs (1.26.1) self-heal on next development sync;
example workflow pinned to 1.26.2 for correctness.
2026-04-09 17:24:25 +00:00
GitHub Actions
bb496daae3 fix(ci): improve health check for Charon container in nightly build 2026-04-09 14:08:19 +00:00
GitHub Actions
4cd568b0e5 fix(deps): update multiple dependencies in package-lock.json 2026-04-09 14:04:00 +00:00
GitHub Actions
efd70cd651 fix(deps): update golang.org/x/text to v0.36.0 and other dependencies 2026-04-09 14:01:05 +00:00
GitHub Actions
3d4a63b515 fix(go): update Go version to 1.26.2 2026-04-09 13:58:24 +00:00
Jeremy
42cec9e8c3 Merge pull request #919 from Wikid82/renovate/feature/beta-release-non-major-updates
fix(deps): update non-major-updates (feature/beta-release)
2026-04-09 09:41:24 -04:00
renovate[bot]
73565e0e0d fix(deps): update non-major-updates 2026-04-09 09:20:57 +00:00
Jeremy
6dddc5db43 Merge pull request #918 from Wikid82/renovate/feature/beta-release-non-major-updates
fix(deps): update non-major-updates (feature/beta-release)
2026-04-06 20:30:42 -04:00
renovate[bot]
ef90d1c0d7 fix(deps): update non-major-updates 2026-04-06 21:48:29 +00:00
Jeremy
2d923246a9 Merge pull request #916 from Wikid82/development
Propagate changes from development into feature/beta-release
2026-04-06 01:24:35 -04:00
42 changed files with 1974 additions and 787 deletions

33
.github/renovate.json vendored
View File

@@ -232,9 +232,24 @@
"datasourceTemplate": "github-releases",
"versioningTemplate": "semver",
"extractVersionTemplate": "^v(?<version>.*)$"
},
{
"customType": "regex",
"description": "Track go-version in skill example workflows",
"managerFilePatterns": ["/^\\.github/skills/examples/.*\\.yml$/"],
"matchStrings": [
"go-version: [\"']?(?<currentValue>[\\d\\.]+)[\"']?"
],
"depNameTemplate": "golang/go",
"datasourceTemplate": "golang-version",
"versioningTemplate": "semver"
}
],
"github-actions": {
"fileMatch": ["^\\.github/skills/examples/.*\\.ya?ml$"]
},
"packageRules": [
{
"description": "THE MEGAZORD: Group ALL non-major updates (NPM, Docker, Go, Actions) into one PR",
@@ -277,6 +292,24 @@
"matchPackageNames": ["caddy"],
"allowedVersions": "<3.0.0"
},
{
"description": "Go: keep pgx within v4 (CrowdSec requires pgx/v4 module path)",
"matchDatasources": ["go"],
"matchPackageNames": ["github.com/jackc/pgx/v4"],
"allowedVersions": "<5.0.0"
},
{
"description": "Go: keep go-jose/v3 within v3 (v4 is a different Go module path)",
"matchDatasources": ["go"],
"matchPackageNames": ["github.com/go-jose/go-jose/v3"],
"allowedVersions": "<4.0.0"
},
{
"description": "Go: keep go-jose/v4 within v4 (v5 would be a different Go module path)",
"matchDatasources": ["go"],
"matchPackageNames": ["github.com/go-jose/go-jose/v4"],
"allowedVersions": "<5.0.0"
},
{
"description": "Safety: Keep MAJOR updates separate and require manual review",
"matchUpdateTypes": ["major"],

View File

@@ -25,7 +25,7 @@ jobs:
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: "1.26.1"
go-version: "1.26.2"
- name: Run GORM Security Scanner
id: gorm-scan

View File

@@ -35,7 +35,7 @@ fi
# Check Grype
if ! command -v grype >/dev/null 2>&1; then
log_error "Grype not found - install from: https://github.com/anchore/grype"
log_error "Installation: curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh | sh -s -- -b /usr/local/bin v0.110.0"
log_error "Installation: curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh | sh -s -- -b /usr/local/bin v0.111.0"
error_exit "Grype is required for vulnerability scanning" 2
fi
@@ -50,8 +50,8 @@ SYFT_INSTALLED_VERSION=$(syft version | grep -oP 'Version:\s*\Kv?[0-9]+\.[0-9]+\
GRYPE_INSTALLED_VERSION=$(grype version | grep -oP 'Version:\s*\Kv?[0-9]+\.[0-9]+\.[0-9]+' | head -1 || echo "unknown")
# Set defaults matching CI workflow
set_default_env "SYFT_VERSION" "v1.42.3"
set_default_env "GRYPE_VERSION" "v0.110.0"
set_default_env "SYFT_VERSION" "v1.42.4"
set_default_env "GRYPE_VERSION" "v0.111.0"
set_default_env "IMAGE_TAG" "charon:local"
set_default_env "FAIL_ON_SEVERITY" "Critical,High"

View File

@@ -24,6 +24,6 @@ jobs:
with:
ref: ${{ github.event.workflow_run.head_sha || github.sha }}
- name: Draft Release
uses: release-drafter/release-drafter@139054aeaa9adc52ab36ddf67437541f039b88e2 # v7
uses: release-drafter/release-drafter@5de93583980a40bd78603b6dfdcda5b4df377b32 # v7
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -18,7 +18,7 @@ jobs:
issues: write
steps:
- name: Auto-label based on title and body
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9
with:
script: |
const issue = context.payload.issue;

View File

@@ -12,7 +12,7 @@ concurrency:
cancel-in-progress: true
env:
GO_VERSION: '1.26.1'
GO_VERSION: '1.26.2'
GOTOOLCHAIN: auto
# Minimal permissions at workflow level; write permissions granted at job level for push only

View File

@@ -18,7 +18,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check for Caddy v3 and open issue
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9
with:
script: |
const upstream = { owner: 'caddyserver', repo: 'caddy' };

View File

@@ -23,7 +23,7 @@ concurrency:
cancel-in-progress: true
env:
GO_VERSION: '1.26.1'
GO_VERSION: '1.26.2'
NODE_VERSION: '24.12.0'
GOTOOLCHAIN: auto
@@ -139,7 +139,7 @@ jobs:
- name: Upload test output artifact
if: always()
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: backend-test-output
path: backend/test-output.txt

View File

@@ -15,7 +15,7 @@ concurrency:
env:
GOTOOLCHAIN: auto
GO_VERSION: '1.26.1'
GO_VERSION: '1.26.2'
permissions:
contents: read

View File

@@ -88,7 +88,7 @@ jobs:
- name: Upload GHCR prune artifacts
if: always()
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: prune-ghcr-log-${{ github.run_id }}
path: |
@@ -159,7 +159,7 @@ jobs:
- name: Upload Docker Hub prune artifacts
if: always()
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: prune-dockerhub-log-${{ github.run_id }}
path: |

View File

@@ -18,7 +18,7 @@ jobs:
issues: write
steps:
- name: Create all project labels
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9
with:
script: |
const labels = [

View File

@@ -347,7 +347,7 @@ jobs:
- name: Upload Image Artifact
if: success() && steps.skip.outputs.skip_build != 'true' && env.TRIGGER_EVENT == 'pull_request'
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: ${{ env.TRIGGER_EVENT == 'pull_request' && format('pr-image-{0}', env.TRIGGER_PR_NUMBER) || 'push-image' }}
path: /tmp/charon-pr-image.tar

View File

@@ -53,7 +53,7 @@ jobs:
- name: Detect changed files
id: changes
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9
env:
COMMIT_SHA: ${{ github.event.workflow_run.head_sha || github.sha }}
with:
@@ -95,7 +95,7 @@ jobs:
- name: Process issue files
id: process
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9
env:
DRY_RUN: ${{ github.event.inputs.dry_run || 'false' }}
with:

View File

@@ -83,7 +83,7 @@ on:
env:
NODE_VERSION: '20'
GO_VERSION: '1.26.1'
GO_VERSION: '1.26.2'
GOTOOLCHAIN: auto
DOCKERHUB_REGISTRY: docker.io
IMAGE_NAME: ${{ github.repository_owner }}/charon
@@ -175,7 +175,7 @@ jobs:
- name: Build Docker image
id: build-image
if: steps.resolve-image.outputs.image_source == 'build'
uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7
uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7
with:
context: .
file: ./Dockerfile
@@ -191,7 +191,7 @@ jobs:
- name: Upload Docker image artifact
if: steps.resolve-image.outputs.image_source == 'build'
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: docker-image
path: charon-e2e-image.tar
@@ -348,7 +348,7 @@ jobs:
- name: Upload HTML report (Chromium Security)
if: always()
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: playwright-report-chromium-security
path: playwright-report/
@@ -356,7 +356,7 @@ jobs:
- name: Upload Chromium Security coverage (if enabled)
if: always() && (inputs.playwright_coverage == 'true' || vars.PLAYWRIGHT_COVERAGE == '1')
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: e2e-coverage-chromium-security
path: coverage/e2e/
@@ -364,7 +364,7 @@ jobs:
- name: Upload test traces on failure
if: failure()
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: traces-chromium-security
path: test-results/**/*.zip
@@ -383,7 +383,7 @@ jobs:
- name: Upload diagnostics
if: always()
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: e2e-diagnostics-chromium-security
path: diagnostics/
@@ -396,7 +396,7 @@ jobs:
- name: Upload Docker logs on failure
if: failure()
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: docker-logs-chromium-security
path: docker-logs-chromium-security.txt
@@ -558,7 +558,7 @@ jobs:
- name: Upload HTML report (Firefox Security)
if: always()
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: playwright-report-firefox-security
path: playwright-report/
@@ -566,7 +566,7 @@ jobs:
- name: Upload Firefox Security coverage (if enabled)
if: always() && (inputs.playwright_coverage == 'true' || vars.PLAYWRIGHT_COVERAGE == '1')
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: e2e-coverage-firefox-security
path: coverage/e2e/
@@ -574,7 +574,7 @@ jobs:
- name: Upload test traces on failure
if: failure()
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: traces-firefox-security
path: test-results/**/*.zip
@@ -593,7 +593,7 @@ jobs:
- name: Upload diagnostics
if: always()
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: e2e-diagnostics-firefox-security
path: diagnostics/
@@ -606,7 +606,7 @@ jobs:
- name: Upload Docker logs on failure
if: failure()
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: docker-logs-firefox-security
path: docker-logs-firefox-security.txt
@@ -768,7 +768,7 @@ jobs:
- name: Upload HTML report (WebKit Security)
if: always()
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: playwright-report-webkit-security
path: playwright-report/
@@ -776,7 +776,7 @@ jobs:
- name: Upload WebKit Security coverage (if enabled)
if: always() && (inputs.playwright_coverage == 'true' || vars.PLAYWRIGHT_COVERAGE == '1')
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: e2e-coverage-webkit-security
path: coverage/e2e/
@@ -784,7 +784,7 @@ jobs:
- name: Upload test traces on failure
if: failure()
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: traces-webkit-security
path: test-results/**/*.zip
@@ -803,7 +803,7 @@ jobs:
- name: Upload diagnostics
if: always()
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: e2e-diagnostics-webkit-security
path: diagnostics/
@@ -816,7 +816,7 @@ jobs:
- name: Upload Docker logs on failure
if: failure()
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: docker-logs-webkit-security
path: docker-logs-webkit-security.txt
@@ -1004,7 +1004,7 @@ jobs:
- name: Upload HTML report (Chromium shard ${{ matrix.shard }})
if: always()
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: playwright-report-chromium-shard-${{ matrix.shard }}
path: playwright-report/
@@ -1012,7 +1012,7 @@ jobs:
- name: Upload Playwright output (Chromium shard ${{ matrix.shard }})
if: always()
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: playwright-output-chromium-shard-${{ matrix.shard }}
path: playwright-output/chromium-shard-${{ matrix.shard }}/
@@ -1020,7 +1020,7 @@ jobs:
- name: Upload Chromium coverage (if enabled)
if: always() && (inputs.playwright_coverage == 'true' || vars.PLAYWRIGHT_COVERAGE == '1')
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: e2e-coverage-chromium-shard-${{ matrix.shard }}
path: coverage/e2e/
@@ -1028,7 +1028,7 @@ jobs:
- name: Upload test traces on failure
if: failure()
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: traces-chromium-shard-${{ matrix.shard }}
path: test-results/**/*.zip
@@ -1047,7 +1047,7 @@ jobs:
- name: Upload diagnostics
if: always()
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: e2e-diagnostics-chromium-shard-${{ matrix.shard }}
path: diagnostics/
@@ -1060,7 +1060,7 @@ jobs:
- name: Upload Docker logs on failure
if: failure()
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: docker-logs-chromium-shard-${{ matrix.shard }}
path: docker-logs-chromium-shard-${{ matrix.shard }}.txt
@@ -1249,7 +1249,7 @@ jobs:
- name: Upload HTML report (Firefox shard ${{ matrix.shard }})
if: always()
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: playwright-report-firefox-shard-${{ matrix.shard }}
path: playwright-report/
@@ -1257,7 +1257,7 @@ jobs:
- name: Upload Playwright output (Firefox shard ${{ matrix.shard }})
if: always()
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: playwright-output-firefox-shard-${{ matrix.shard }}
path: playwright-output/firefox-shard-${{ matrix.shard }}/
@@ -1265,7 +1265,7 @@ jobs:
- name: Upload Firefox coverage (if enabled)
if: always() && (inputs.playwright_coverage == 'true' || vars.PLAYWRIGHT_COVERAGE == '1')
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: e2e-coverage-firefox-shard-${{ matrix.shard }}
path: coverage/e2e/
@@ -1273,7 +1273,7 @@ jobs:
- name: Upload test traces on failure
if: failure()
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: traces-firefox-shard-${{ matrix.shard }}
path: test-results/**/*.zip
@@ -1292,7 +1292,7 @@ jobs:
- name: Upload diagnostics
if: always()
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: e2e-diagnostics-firefox-shard-${{ matrix.shard }}
path: diagnostics/
@@ -1305,7 +1305,7 @@ jobs:
- name: Upload Docker logs on failure
if: failure()
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: docker-logs-firefox-shard-${{ matrix.shard }}
path: docker-logs-firefox-shard-${{ matrix.shard }}.txt
@@ -1494,7 +1494,7 @@ jobs:
- name: Upload HTML report (WebKit shard ${{ matrix.shard }})
if: always()
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: playwright-report-webkit-shard-${{ matrix.shard }}
path: playwright-report/
@@ -1502,7 +1502,7 @@ jobs:
- name: Upload Playwright output (WebKit shard ${{ matrix.shard }})
if: always()
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: playwright-output-webkit-shard-${{ matrix.shard }}
path: playwright-output/webkit-shard-${{ matrix.shard }}/
@@ -1510,7 +1510,7 @@ jobs:
- name: Upload WebKit coverage (if enabled)
if: always() && (inputs.playwright_coverage == 'true' || vars.PLAYWRIGHT_COVERAGE == '1')
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: e2e-coverage-webkit-shard-${{ matrix.shard }}
path: coverage/e2e/
@@ -1518,7 +1518,7 @@ jobs:
- name: Upload test traces on failure
if: failure()
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: traces-webkit-shard-${{ matrix.shard }}
path: test-results/**/*.zip
@@ -1537,7 +1537,7 @@ jobs:
- name: Upload diagnostics
if: always()
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: e2e-diagnostics-webkit-shard-${{ matrix.shard }}
path: diagnostics/
@@ -1550,7 +1550,7 @@ jobs:
- name: Upload Docker logs on failure
if: failure()
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: docker-logs-webkit-shard-${{ matrix.shard }}
path: docker-logs-webkit-shard-${{ matrix.shard }}.txt
@@ -1606,7 +1606,7 @@ jobs:
steps:
- name: Check test results
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9
env:
EFFECTIVE_BROWSER: ${{ inputs.browser || 'all' }}
EFFECTIVE_CATEGORY: ${{ inputs.test_category || 'all' }}

View File

@@ -15,7 +15,7 @@ on:
default: "false"
env:
GO_VERSION: '1.26.1'
GO_VERSION: '1.26.2'
NODE_VERSION: '24.12.0'
GOTOOLCHAIN: auto
GHCR_REGISTRY: ghcr.io
@@ -89,7 +89,7 @@ jobs:
contents: read
steps:
- name: Dispatch Missing Nightly Validation Workflows
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9
with:
script: |
const owner = context.repo.owner;
@@ -212,7 +212,7 @@ jobs:
- name: Build and push Docker image
id: build
uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7.0.0
uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0
with:
context: .
platforms: linux/amd64,linux/arm64
@@ -285,7 +285,7 @@ jobs:
echo "Primary SBOM generation failed or produced missing/invalid output; using deterministic Syft fallback"
SYFT_VERSION="v1.42.3"
SYFT_VERSION="v1.42.4"
OS="$(uname -s | tr '[:upper:]' '[:lower:]')"
ARCH="$(uname -m)"
case "$ARCH" in
@@ -328,7 +328,7 @@ jobs:
' sbom-nightly.json >/dev/null
- name: Upload SBOM artifact
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: sbom-nightly
path: sbom-nightly.json
@@ -394,14 +394,28 @@ jobs:
-p 8080:8080 \
"${IMAGE_REF}"
# Wait for container to start
sleep 10
# Wait for container to become healthy
echo "⏳ Waiting for Charon to be healthy..."
MAX_ATTEMPTS=30
ATTEMPT=0
while [[ ${ATTEMPT} -lt ${MAX_ATTEMPTS} ]]; do
ATTEMPT=$((ATTEMPT + 1))
echo "Attempt ${ATTEMPT}/${MAX_ATTEMPTS}..."
if docker exec charon-nightly wget -qO- http://127.0.0.1:8080/health > /dev/null 2>&1; then
echo "✅ Charon is healthy!"
docker exec charon-nightly wget -qO- http://127.0.0.1:8080/health
break
fi
sleep 2
done
# Check container is running
docker ps | grep charon-nightly
# Basic health check
curl -f http://localhost:8080/health || exit 1
if [[ ${ATTEMPT} -ge ${MAX_ATTEMPTS} ]]; then
echo "❌ Health check failed after ${MAX_ATTEMPTS} attempts"
docker logs charon-nightly
docker stop charon-nightly
docker rm charon-nightly
exit 1
fi
# Cleanup
docker stop charon-nightly

View File

@@ -25,7 +25,7 @@ jobs:
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- name: Validate PR checklist (only for history-rewrite changes)
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9
env:
PR_NUMBER: ${{ inputs.pr_number }}
with:

View File

@@ -33,7 +33,7 @@ jobs:
node-version: ${{ env.NODE_VERSION }}
- name: Propagate Changes
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9
env:
CURRENT_BRANCH: ${{ github.event.workflow_run.head_branch || github.ref_name }}
CURRENT_SHA: ${{ github.event.workflow_run.head_sha || github.sha }}

View File

@@ -16,7 +16,7 @@ permissions:
checks: write
env:
GO_VERSION: '1.26.1'
GO_VERSION: '1.26.2'
NODE_VERSION: '24.12.0'
GOTOOLCHAIN: auto
@@ -161,7 +161,7 @@ jobs:
- name: Upload test output artifact
if: always()
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: backend-test-output
path: backend/test-output.txt

View File

@@ -10,7 +10,7 @@ concurrency:
cancel-in-progress: false
env:
GO_VERSION: '1.26.1'
GO_VERSION: '1.26.2'
NODE_VERSION: '24.12.0'
GOTOOLCHAIN: auto

View File

@@ -14,6 +14,9 @@ permissions:
pull-requests: write
issues: write
env:
GO_VERSION: '1.26.2'
jobs:
renovate:
runs-on: ubuntu-latest
@@ -24,6 +27,11 @@ jobs:
with:
fetch-depth: 1
- name: Set up Go
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6
with:
go-version: ${{ env.GO_VERSION }}
- name: Run Renovate
uses: renovatebot/github-action@b67590ea780158ccd13192c22a3655a5231f869d # v46.1.8
with:

View File

@@ -30,7 +30,7 @@ jobs:
echo "GITHUB_TOKEN=${{ secrets.CHARON_TOKEN }}" >> "$GITHUB_ENV"
fi
- name: Prune renovate branches
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9
with:
github-token: ${{ env.GITHUB_TOKEN }}
script: |

View File

@@ -37,7 +37,7 @@ jobs:
- name: Upload health output
if: always()
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: repo-health-output
path: |

View File

@@ -80,7 +80,7 @@ jobs:
- name: Build Docker image (NO CACHE)
id: build
uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7
uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7
with:
context: .
platforms: linux/amd64
@@ -130,7 +130,7 @@ jobs:
version: 'v0.69.3'
- name: Upload Trivy JSON results
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: trivy-weekly-scan-${{ github.run_number }}
path: trivy-weekly-results.json

View File

@@ -285,7 +285,7 @@ jobs:
- name: Install Grype
if: steps.set-target.outputs.image_name != ''
run: |
curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh | sh -s -- -b /usr/local/bin v0.110.0
curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh | sh -s -- -b /usr/local/bin v0.111.0
- name: Scan for vulnerabilities
if: steps.set-target.outputs.image_name != ''

View File

@@ -144,7 +144,7 @@ jobs:
- name: Upload SBOM Artifact
if: steps.image-check.outputs.exists == 'true' && always()
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: sbom-${{ steps.tag.outputs.tag }}
path: sbom-verify.cyclonedx.json
@@ -324,7 +324,7 @@ jobs:
- name: Upload Vulnerability Scan Artifact
if: steps.validate-sbom.outputs.valid == 'true' && always()
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: vulnerability-scan-${{ steps.tag.outputs.tag }}
path: |
@@ -362,7 +362,7 @@ jobs:
if: |
github.event_name == 'pull_request' ||
(github.event_name == 'workflow_run' && github.event.workflow_run.event == 'pull_request')
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
result-encoding: string
script: |

View File

@@ -105,7 +105,7 @@ jobs:
- name: Create Pull Request
if: steps.checksum.outputs.needs_update == 'true'
uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v8.1.0
uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1
with:
title: "chore(docker): update GeoLite2-Country.mmdb checksum"
body: |
@@ -160,7 +160,7 @@ jobs:
- name: Report failure via GitHub Issue
if: failure()
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9
with:
script: |
const errorType = '${{ steps.checksum.outputs.error }}' || 'unknown';

View File

@@ -47,7 +47,7 @@ jobs:
steps:
- name: Check Nightly Workflow Status
id: check
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9
with:
script: |
const skipCheck = '${{ inputs.skip_workflow_check }}' === 'true';
@@ -274,7 +274,7 @@ jobs:
- name: Check for Existing PR
id: existing-pr
if: steps.check-diff.outputs.skipped != 'true'
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9
with:
script: |
const { data: pulls } = await github.rest.pulls.list({
@@ -297,7 +297,7 @@ jobs:
- name: Create Promotion PR
id: create-pr
if: steps.check-diff.outputs.skipped != 'true' && steps.existing-pr.outputs.exists != 'true'
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9
with:
script: |
const fs = require('fs');
@@ -399,7 +399,7 @@ jobs:
- name: Update Existing PR
if: steps.check-diff.outputs.skipped != 'true' && steps.existing-pr.outputs.exists == 'true'
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9
with:
script: |
const prNumber = ${{ steps.existing-pr.outputs.pr_number }};
@@ -425,7 +425,7 @@ jobs:
contents: read
steps:
- name: Dispatch missing required workflows on nightly head
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9
with:
script: |
const owner = context.repo.owner;
@@ -483,7 +483,7 @@ jobs:
steps:
- name: Create Failure Issue
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9
with:
script: |
const isHealthy = '${{ needs.check-nightly-health.outputs.is_healthy }}';

View File

@@ -77,6 +77,129 @@ ignore:
Risk accepted pending Alpine upstream patch.
expiry: "2026-05-18" # Extended 2026-04-04: see libcrypto3 entry above for action items.
# CVE-2026-31790: OpenSSL vulnerability in Alpine base image packages
# Severity: HIGH
# Packages: libcrypto3 3.5.5-r0 and libssl3 3.5.5-r0 (Alpine apk)
# Status: No upstream fix available — Alpine 3.23 still ships libcrypto3/libssl3 3.5.5-r0 as of 2026-04-09
#
# Root Cause (No Fix Available):
# - Alpine upstream has not published a patched libcrypto3/libssl3 for Alpine 3.23.
# - Checked: Alpine 3.23 still ships libcrypto3/libssl3 3.5.5-r0 as of 2026-04-09.
# - Fix path: once Alpine publishes a patched libcrypto3/libssl3, rebuild the Docker image
# and remove this suppression.
#
# Risk Assessment: ACCEPTED (No upstream fix; documented in SECURITY.md)
# - Charon terminates TLS at the Caddy layer — the Go backend does not act as a raw TLS server.
# - Container-level isolation reduces the attack surface further.
#
# Mitigation (active while suppression is in effect):
# - Monitor Alpine security advisories: https://security.alpinelinux.org/vuln/CVE-2026-31790
# - Weekly CI security rebuild (security-weekly-rebuild.yml) flags any new CVEs in the full image.
#
# Review:
# - Reviewed 2026-04-09 (initial suppression): no upstream fix available. Set 30-day review.
# - Next review: 2026-05-09. Remove suppression immediately once upstream fixes.
#
# Removal Criteria:
# - Alpine publishes a patched version of libcrypto3 and libssl3
# - Rebuild Docker image and verify CVE-2026-31790 no longer appears in grype-results.json
# - Remove both these entries and the corresponding .trivyignore entry simultaneously
#
# References:
# - CVE-2026-31790: https://nvd.nist.gov/vuln/detail/CVE-2026-31790
# - Alpine security tracker: https://security.alpinelinux.org/vuln/CVE-2026-31790
- vulnerability: CVE-2026-31790
package:
name: libcrypto3
version: "3.5.5-r0"
type: apk
reason: |
HIGH — OpenSSL vulnerability in libcrypto3 3.5.5-r0 (Alpine base image).
No upstream fix: Alpine 3.23 still ships libcrypto3 3.5.5-r0 as of 2026-04-09. Charon
terminates TLS at the Caddy layer; the Go backend does not act as a raw TLS server.
Risk accepted pending Alpine upstream patch. Documented in SECURITY.md.
expiry: "2026-05-09" # Reviewed 2026-04-09: no upstream fix available. Next review 2026-05-09.
# Action items when this suppression expires:
# 1. Check Alpine security tracker: https://security.alpinelinux.org/vuln/CVE-2026-31790
# 2. If a patched Alpine package is now available:
# a. Rebuild Docker image without suppression
# b. Run local security-scan-docker-image and confirm CVE is resolved
# c. Remove this suppression entry, the libssl3 entry below, and the .trivyignore entry
# 3. If no fix yet: Extend expiry by 1430 days and update the review comment above
# 4. If extended 3+ times: Open an issue to track the upstream status formally
# CVE-2026-31790 (libssl3) — see full justification in the libcrypto3 entry above
- vulnerability: CVE-2026-31790
package:
name: libssl3
version: "3.5.5-r0"
type: apk
reason: |
HIGH — OpenSSL vulnerability in libssl3 3.5.5-r0 (Alpine base image).
No upstream fix: Alpine 3.23 still ships libssl3 3.5.5-r0 as of 2026-04-09. Charon
terminates TLS at the Caddy layer; the Go backend does not act as a raw TLS server.
Risk accepted pending Alpine upstream patch. Documented in SECURITY.md.
expiry: "2026-05-09" # Reviewed 2026-04-09: see libcrypto3 entry above for action items.
# GHSA-69x3-g4r3-p962 / CVE-2026-25793: Nebula ECDSA Signature Malleability
# Severity: HIGH (CVSS 8.1)
# Package: github.com/slackhq/nebula v1.9.7 (embedded in /usr/bin/caddy via smallstep/certificates)
# Status: Fix exists in nebula v1.10.3 — smallstep/certificates cannot compile against v1.10+ APIs
#
# Vulnerability Details:
# - ECDSA signature malleability in nebula allows potential authentication bypass via
# crafted certificate signatures (CWE-347).
# - CVSSv3: AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N (CVSS 8.1)
#
# Root Cause (Third-Party Binary + Upstream API Incompatibility):
# - Charon does not use nebula directly. The library is compiled into the Caddy binary
# via the caddy-security plugin → smallstep/certificates dependency chain.
# - Nebula v1.10.3 patches the vulnerability but removes legacy APIs that
# smallstep/certificates (through v0.30.2) depends on, causing compile failures.
# - Fix path: once smallstep/certificates releases a version compatible with nebula >= v1.10.3,
# update the Dockerfile and remove this suppression.
#
# Risk Assessment: ACCEPTED (No direct use + upstream API incompatibility blocks fix)
# - Charon does not use Nebula VPN PKI by default. The vulnerable code path is only
# reachable if Nebula-based certificate provisioning is explicitly configured.
# - The attack requires network access and a crafted certificate, which is not part of
# standard Charon deployment.
#
# Mitigation (active while suppression is in effect):
# - Monitor smallstep/certificates releases: https://github.com/smallstep/certificates/releases
# - Monitor nebula releases: https://github.com/slackhq/nebula/releases
# - Weekly CI security rebuild flags the moment a compatible upstream ships.
#
# Review:
# - Reviewed 2026-02-19 (initial suppression in .trivyignore): certificates v0.27.5 pins nebula v1.9.x.
# - Re-evaluated 2026-04-10: nebula v1.10.3 has the fix but certificates (through v0.30.2)
# uses legacy APIs removed in v1.10+. Still blocked. Set 30-day review.
# - Next review: 2026-05-10. Remove suppression once certificates ships with nebula >= v1.10.3.
#
# Removal Criteria:
# - smallstep/certificates releases a version compatible with nebula >= v1.10.3
# - Update Dockerfile nebula pin, rebuild, run security-scan-docker-image, confirm resolved
# - Remove this entry and the corresponding .trivyignore entry simultaneously
#
# References:
# - GHSA-69x3-g4r3-p962: https://github.com/advisories/GHSA-69x3-g4r3-p962
# - CVE-2026-25793: https://nvd.nist.gov/vuln/detail/CVE-2026-25793
# - Nebula releases: https://github.com/slackhq/nebula/releases
# - smallstep/certificates releases: https://github.com/smallstep/certificates/releases
- vulnerability: CVE-2026-25793
package:
name: github.com/slackhq/nebula
version: "v1.9.7"
type: go-module
reason: |
HIGH — ECDSA signature malleability in nebula v1.9.7 embedded in /usr/bin/caddy.
Fix exists in nebula v1.10.3 but smallstep/certificates (through v0.30.2) uses legacy APIs
removed in v1.10+, causing compile failures. Charon does not use Nebula VPN PKI by default.
Risk accepted; no remediation until smallstep/certificates ships with nebula >= v1.10.3.
Re-evaluated 2026-04-10: still blocked by upstream API incompatibility.
expiry: "2026-05-10" # Re-evaluated 2026-04-10: certificates through v0.30.2 incompatible with nebula v1.10+.
# GHSA-6g7g-w4f8-9c9x: buger/jsonparser Delete panic on malformed JSON (DoS)
# Severity: HIGH (CVSS 7.5)
# Package: github.com/buger/jsonparser v1.1.1 (embedded in /usr/local/bin/crowdsec and /usr/local/bin/cscli)
@@ -288,6 +411,77 @@ ignore:
# 4. If not yet migrated: Extend expiry by 30 days and update the review comment above
# 5. If extended 3+ times: Open an upstream issue on crowdsecurity/crowdsec requesting pgx/v5 migration
# CVE-2026-32286: pgproto3/v2 buffer overflow in DataRow handling (DoS)
# Severity: HIGH (CVSS 7.5)
# Package: github.com/jackc/pgproto3/v2 v2.3.3 (embedded in /usr/local/bin/crowdsec and /usr/local/bin/cscli)
# Status: NO fix in pgproto3/v2 (archived/EOL) — fix path requires CrowdSec to migrate to pgx/v5
#
# Vulnerability Details:
# - Buffer overflow in pgproto3/v2 DataRow handling allows a malicious or compromised PostgreSQL
# server to trigger a denial of service via crafted protocol messages (CWE-120).
# - CVSSv3: AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H (CVSS 7.5)
#
# Root Cause (EOL Module + Third-Party Binary):
# - Same affected module as GHSA-jqcq-xjh3-6g23 and GHSA-x6gf-mpr2-68h6 — pgproto3/v2 v2.3.3
# is the final release (repository archived Jul 12, 2025). No fix will be released.
# - Charon does not use pgproto3/v2 directly nor communicate with PostgreSQL. The package
# is compiled into CrowdSec binaries for their internal database communication.
# - Fix exists only in pgproto3/v3 (used by pgx/v5). CrowdSec v1.7.7 (latest) still depends
# on pgx/v4 → pgproto3/v2. Dockerfile already applies best-effort mitigation (pgx/v4@v4.18.3).
# - Fix path: once CrowdSec migrates to pgx/v5, rebuild the Docker image and remove this suppression.
#
# Risk Assessment: ACCEPTED (Non-exploitable in Charon context + no upstream fix path)
# - The vulnerability requires a malicious PostgreSQL server response. Charon uses SQLite
# internally and does not run PostgreSQL. CrowdSec's database path is not exposed to
# external traffic in a standard Charon deployment.
# - CrowdSec's PostgreSQL code path is not directly exposed to untrusted network input in
# Charon's deployment.
#
# Mitigation (active while suppression is in effect):
# - Monitor CrowdSec releases for pgx/v5 migration:
# https://github.com/crowdsecurity/crowdsec/releases
# - Weekly CI security rebuild flags the moment a fixed image ships.
#
# Review:
# - Reviewed 2026-04-10 (initial suppression): pgproto3/v2 is EOL; no fix exists or will exist.
# Waiting on CrowdSec to migrate to pgx/v5. Set 90-day review.
# - Next review: 2026-07-09. Remove suppression once CrowdSec ships with pgx/v5.
#
# Removal Criteria:
# - Same as GHSA-jqcq-xjh3-6g23: CrowdSec releases a version with pgx/v5 replacing pgproto3/v2
# - Rebuild Docker image, run security-scan-docker-image, confirm all pgproto3/v2 advisories are resolved
# - Remove this entry, GHSA-jqcq-xjh3-6g23 entry, GHSA-x6gf-mpr2-68h6 entry, and all .trivyignore entries simultaneously
#
# References:
# - CVE-2026-32286: https://nvd.nist.gov/vuln/detail/CVE-2026-32286
# - pgproto3/v2 archive notice: https://github.com/jackc/pgproto3
# - pgx/v5 (replacement): https://github.com/jackc/pgx
# - CrowdSec releases: https://github.com/crowdsecurity/crowdsec/releases
- vulnerability: CVE-2026-32286
package:
name: github.com/jackc/pgproto3/v2
version: "v2.3.3"
type: go-module
reason: |
HIGH — Buffer overflow in pgproto3/v2 v2.3.3 DataRow handling, embedded in CrowdSec binaries.
pgproto3/v2 v2.3.3 is the final release (archived Jul 2025); no fix will be released.
Fix exists only in pgproto3/v3 (pgx/v5). CrowdSec v1.7.7 still depends on pgx/v4 → pgproto3/v2.
Charon uses SQLite, not PostgreSQL; this code path is not reachable in a standard deployment.
Risk accepted; no remediation until CrowdSec ships with pgx/v5.
Reviewed 2026-04-10: pgproto3/v2 EOL confirmed; CrowdSec has not migrated to pgx/v5 yet.
expiry: "2026-07-09" # Reviewed 2026-04-10: no fix path until CrowdSec migrates to pgx/v5. 90-day expiry.
# Action items when this suppression expires:
# 1. Check CrowdSec releases for pgx/v5 migration:
# https://github.com/crowdsecurity/crowdsec/releases
# 2. Verify with: `go version -m /path/to/crowdsec | grep pgproto3`
# Expected: pgproto3/v3 (or no pgproto3 reference if fully replaced)
# 3. If CrowdSec has migrated:
# a. Rebuild Docker image and run local security-scan-docker-image
# b. Remove this entry, GHSA-jqcq-xjh3-6g23 entry, GHSA-x6gf-mpr2-68h6 entry, and all .trivyignore entries
# 4. If not yet migrated: Extend expiry by 30 days and update the review comment above
# 5. If extended 3+ times: Open an upstream issue on crowdsecurity/crowdsec requesting pgx/v5 migration
# GHSA-x744-4wpc-v9h2 / CVE-2026-34040: Docker AuthZ plugin bypass via oversized request body
# Severity: HIGH (CVSS 8.8)
# CVSS Vector: CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H

View File

@@ -3,18 +3,13 @@ playwright/.auth/
# GHSA-69x3-g4r3-p962 / CVE-2026-25793: Nebula ECDSA Signature Malleability
# Severity: HIGH (CVSS 8.1) — Package: github.com/slackhq/nebula v1.9.7 in /usr/bin/caddy
# Cannot upgrade: smallstep/certificates v0.27.5 (latest stable as of 2026-02-19) still pins nebula v1.9.x.
# Charon does not use Nebula VPN PKI by default. Review by: 2026-03-05
# Fix exists in nebula v1.10.3, but smallstep/certificates (through v0.30.2) uses legacy nebula
# APIs removed in v1.10+, causing compile failures. Waiting on certificates upstream update.
# Charon does not use Nebula VPN PKI by default. Review by: 2026-05-10
# See also: .grype.yaml for full justification
# exp: 2026-05-10
CVE-2026-25793
# CVE-2026-22184: zlib Global Buffer Overflow in untgz utility
# Severity: CRITICAL (CVSS 9.8) — Package: zlib 1.3.1-r2 in Alpine base image
# No upstream fix available: Alpine 3.23 (including edge) still ships zlib 1.3.1-r2.
# Charon does not use untgz or process untrusted tar archives. Review by: 2026-03-14
# See also: .grype.yaml for full justification
CVE-2026-22184
# 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.
@@ -81,6 +76,17 @@ GHSA-jqcq-xjh3-6g23
# exp: 2026-05-21
GHSA-x6gf-mpr2-68h6
# CVE-2026-32286: pgproto3/v2 buffer overflow in DataRow handling (DoS)
# Severity: HIGH (CVSS 7.5) — Package: github.com/jackc/pgproto3/v2 v2.3.3, embedded in CrowdSec binaries
# pgproto3/v2 v2.3.3 is the final release — repository archived Jul 12, 2025. No fix will be released.
# Fix exists only in pgproto3/v3 (used by pgx/v5). CrowdSec v1.7.7 (latest) still depends on pgx/v4 → pgproto3/v2.
# Dockerfile already applies best-effort mitigation (pgx/v4@v4.18.3).
# Charon uses SQLite; the PostgreSQL code path is not reachable in a standard deployment.
# Review by: 2026-07-09
# See also: .grype.yaml for full justification
# exp: 2026-07-09
CVE-2026-32286
# CVE-2026-34040 / GHSA-x744-4wpc-v9h2: Docker AuthZ plugin bypass via oversized request body
# Severity: HIGH (CVSS 8.8) — Package: github.com/docker/docker v28.5.2+incompatible
# Incomplete fix for CVE-2024-41110. Fixed in moby/moby v29.3.1 but no fix for docker/docker import path.

View File

@@ -10,7 +10,7 @@ ARG BUILD_DEBUG=0
# ---- Pinned Toolchain Versions ----
# renovate: datasource=docker depName=golang versioning=docker
ARG GO_VERSION=1.26.1
ARG GO_VERSION=1.26.2
# renovate: datasource=docker depName=alpine versioning=docker
ARG ALPINE_IMAGE=alpine:3.23.3@sha256:25109184c71bdad752c8312a8623239686a9a2071e8825f20acb8f2198c3f659
@@ -25,7 +25,7 @@ ARG CROWDSEC_RELEASE_SHA256=704e37121e7ac215991441cef0d8732e33fa3b1a2b2b88b53a0b
# renovate: datasource=go depName=github.com/expr-lang/expr
ARG EXPR_LANG_VERSION=1.17.8
# renovate: datasource=go depName=golang.org/x/net
ARG XNET_VERSION=0.52.0
ARG XNET_VERSION=0.53.0
# renovate: datasource=go depName=github.com/smallstep/certificates
ARG SMALLSTEP_CERTIFICATES_VERSION=0.30.0
# renovate: datasource=npm depName=npm
@@ -282,11 +282,27 @@ RUN --mount=type=cache,target=/root/.cache/go-build \
# renovate: datasource=go depName=github.com/hslatman/ipstore
go get github.com/hslatman/ipstore@v0.4.0; \
go get golang.org/x/net@v${XNET_VERSION}; \
# CVE-2026-33186 (GHSA-p77j-4mvh-x3m3): gRPC-Go auth bypass via missing leading slash
# Fix available at v1.79.3. Pin here so the Caddy binary is patched immediately;
# remove once Caddy ships a release built with grpc >= v1.79.3.
# CVE-2026-33186: gRPC-Go auth bypass (fixed in v1.79.3)
# CVE-2026-34986: go-jose/v4 transitive fix (requires grpc >= v1.80.0)
# Pin here so the Caddy binary is patched immediately;
# remove once Caddy ships a release built with grpc >= v1.80.0.
# renovate: datasource=go depName=google.golang.org/grpc
go get google.golang.org/grpc@v1.79.3; \
go get google.golang.org/grpc@v1.80.0; \
# CVE-2026-34986: go-jose JOSE/JWT validation bypass
# renovate: datasource=go depName=github.com/go-jose/go-jose/v3
go get github.com/go-jose/go-jose/v3@v3.0.5; \
# renovate: datasource=go depName=github.com/go-jose/go-jose/v4
go get github.com/go-jose/go-jose/v4@v4.1.4; \
# CVE-2026-39883: OTel SDK resource leak
# renovate: datasource=go depName=go.opentelemetry.io/otel/sdk
go get go.opentelemetry.io/otel/sdk@v1.43.0; \
# CVE-2026-39882: OTel HTTP exporter request smuggling
# renovate: datasource=go depName=go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp
go get go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp@v0.19.0; \
# renovate: datasource=go depName=go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp
go get go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp@v1.43.0; \
# renovate: datasource=go depName=go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp
go get go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp@v1.43.0; \
# GHSA-479m-364c-43vc: goxmldsig XML signature validation bypass (loop variable capture)
# Fix available at v1.6.0. Pin here so the Caddy binary is patched immediately;
# remove once caddy-security ships a release built with goxmldsig >= v1.6.0.
@@ -365,6 +381,18 @@ RUN go get github.com/expr-lang/expr@v${EXPR_LANG_VERSION} && \
# remove once CrowdSec ships a release built with grpc >= v1.79.3.
# renovate: datasource=go depName=google.golang.org/grpc
go get google.golang.org/grpc@v1.80.0 && \
# CVE-2026-32286: pgproto3/v2 buffer overflow (no v2 fix exists; bump pgx/v4 to latest patch)
# renovate: datasource=go depName=github.com/jackc/pgx/v4
go get github.com/jackc/pgx/v4@v4.18.3 && \
# GHSA-xmrv-pmrh-hhx2: AWS SDK v2 event stream injection
# renovate: datasource=go depName=github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream
go get github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream@v1.7.8 && \
# renovate: datasource=go depName=github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs
go get github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs@v1.68.0 && \
# renovate: datasource=go depName=github.com/aws/aws-sdk-go-v2/service/kinesis
go get github.com/aws/aws-sdk-go-v2/service/kinesis@v1.43.5 && \
# renovate: datasource=go depName=github.com/aws/aws-sdk-go-v2/service/s3
go get github.com/aws/aws-sdk-go-v2/service/s3@v1.99.0 && \
go mod tidy
# Fix compatibility issues with expr-lang v1.17.7
@@ -458,7 +486,7 @@ SHELL ["/bin/ash", "-o", "pipefail", "-c"]
# Note: In production, users should provide their own MaxMind license key
# This uses the publicly available GeoLite2 database
# In CI, timeout quickly rather than retrying to save build time
ARG GEOLITE2_COUNTRY_SHA256=f5e80a9a3129d46e75c8cccd66bfac725b0449a6c89ba5093a16561d58f20bda
ARG GEOLITE2_COUNTRY_SHA256=b018842033872f19ed9ccefb863ec954f8024db2ae913d0d4ea14e35ace4eba1
RUN mkdir -p /app/data/geoip && \
if [ "$CI" = "true" ] || [ "$CI" = "1" ]; then \
echo "⏱️ CI detected - quick download (10s timeout, no retries)"; \

View File

@@ -27,49 +27,47 @@ public disclosure.
## Known Vulnerabilities
Last reviewed: 2026-04-04
Last reviewed: 2026-04-09
### [HIGH] CVE-2026-2673 · OpenSSL TLS 1.3 Key Exchange Group Downgrade
### [HIGH] CVE-2026-31790 · OpenSSL Vulnerability in Alpine Base Image
| Field | Value |
|--------------|-------|
| **ID** | CVE-2026-2673 (affects `libcrypto3` and `libssl3`) |
| **Severity** | High · 7.5 |
| **ID** | CVE-2026-31790 (affects `libcrypto3` and `libssl3`) |
| **Severity** | High · CVSS pending |
| **Status** | Awaiting Upstream |
**What**
An OpenSSL TLS 1.3 server may fail to negotiate the intended key exchange group when the
configuration includes the `DEFAULT` keyword, potentially allowing downgrade to weaker cipher
suites. Affects Alpine 3.23.3 packages `libcrypto3` and `libssl3` at version 3.5.5-r0.
An OpenSSL vulnerability in the Alpine base image system packages `libcrypto3` and `libssl3`.
This is a pre-existing issue in the Alpine base image and was not introduced by Charon.
**Who**
- Discovered by: Automated scan (Grype)
- Reported: 2026-03-20
- Affects: Container runtime environment; Caddy reverse proxy TLS negotiation could be affected
if default key group configuration is used
- Reported: 2026-04-09
- Affects: Container runtime environment; does not affect Charon application code directly
**Where**
- Component: Alpine 3.23.3 base image (`libcrypto3` 3.5.5-r0, `libssl3` 3.5.5-r0)
- Versions affected: Alpine 3.23.3 prior to a patched `openssl` APK release
- Component: Alpine base image (`libcrypto3`, `libssl3`)
- Versions affected: Current Alpine base image OpenSSL packages
**When**
- Discovered: 2026-03-20
- Disclosed (if public): 2026-03-13 (OpenSSL advisory)
- Target fix: When Alpine Security publishes a patched `openssl` APK
- Discovered: 2026-04-09
- Disclosed (if public): Public
- Target fix: When Alpine Security publishes a patched OpenSSL APK
**How**
When an OpenSSL TLS 1.3 server configuration uses the `DEFAULT` keyword for key exchange groups,
the negotiation logic may select a weaker group than intended. Charon's Caddy TLS configuration
does not use the `DEFAULT` keyword, which limits practical exploitability. The packages are
present in the base image regardless of Caddy's configuration.
The vulnerability resides in Alpine's system OpenSSL library and affects TLS operations at
the OS level. Charon's application code does not directly invoke these libraries. Practical
exploitability depends on direct TLS usage through the system OpenSSL, which is limited to
the container runtime environment.
**Planned Remediation**
Monitor <https://security.alpinelinux.org/vuln/CVE-2026-2673> 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 libcrypto3 libssl3` to the runtime stage.
Monitor <https://security.alpinelinux.org/> for a patched Alpine APK. No upstream fix
available as of 2026-04-09. Once available, update the pinned `ALPINE_IMAGE` digest in the
Dockerfile.
---
@@ -115,43 +113,47 @@ fix available. When a compatible module path exists, migrate the Docker SDK impo
---
### [MEDIUM] CVE-2025-60876 · BusyBox wget HTTP Request Smuggling
### [HIGH] CVE-2026-2673 · OpenSSL TLS 1.3 Key Exchange Group Downgrade
| Field | Value |
|--------------|-------|
| **ID** | CVE-2025-60876 |
| **Severity** | Medium · 6.5 |
| **ID** | CVE-2026-2673 (affects `libcrypto3` and `libssl3`) |
| **Severity** | High · 7.5 |
| **Status** | Awaiting Upstream |
**What**
BusyBox wget through 1.37 accepts raw CR/LF and other C0 control bytes in the HTTP
request-target, allowing request line splitting and header injection (CWE-284).
An OpenSSL TLS 1.3 server may fail to negotiate the intended key exchange group when the
configuration includes the `DEFAULT` keyword, potentially allowing downgrade to weaker cipher
suites. Affects Alpine 3.23.3 packages `libcrypto3` and `libssl3` at version 3.5.5-r0.
**Who**
- Discovered by: Automated scan (Grype)
- Reported: 2026-03-24
- Affects: Container runtime environment; Charon does not invoke busybox wget in application logic
- Reported: 2026-03-20
- Affects: Container runtime environment; Caddy reverse proxy TLS negotiation could be affected
if default key group configuration is used
**Where**
- Component: Alpine 3.23.3 base image (`busybox` 1.37.0-r30)
- Versions affected: All Charon images using Alpine 3.23.3 with busybox < patched version
- Component: Alpine 3.23.3 base image (`libcrypto3` 3.5.5-r0, `libssl3` 3.5.5-r0)
- Versions affected: Alpine 3.23.3 prior to a patched `openssl` APK release
**When**
- Discovered: 2026-03-24
- Disclosed (if public): Not yet publicly disclosed with fix
- Target fix: When Alpine Security publishes a patched busybox APK
- Discovered: 2026-03-20
- Disclosed (if public): 2026-03-13 (OpenSSL advisory)
- Target fix: When Alpine Security publishes a patched `openssl` APK
**How**
The vulnerable wget applet would need to be manually invoked inside the container with
attacker-controlled URLs. Charon's application logic does not use busybox wget. EPSS score is
0.00064 (0.20 percentile), indicating extremely low exploitation probability.
When an OpenSSL TLS 1.3 server configuration uses the `DEFAULT` keyword for key exchange groups,
the negotiation logic may select a weaker group than intended. Charon's Caddy TLS configuration
does not use the `DEFAULT` keyword, which limits practical exploitability. The packages are
present in the base image regardless of Caddy's configuration.
**Planned Remediation**
Monitor Alpine 3.23 for a patched busybox APK. No immediate action required. Practical risk to
Charon users is negligible since the vulnerable code path is not exercised.
Monitor <https://security.alpinelinux.org/vuln/CVE-2026-2673> 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 libcrypto3 libssl3` to the runtime stage.
---
@@ -197,6 +199,44 @@ available for the current `docker/docker` import path.
---
### [MEDIUM] CVE-2025-60876 · BusyBox wget HTTP Request Smuggling
| Field | Value |
|--------------|-------|
| **ID** | CVE-2025-60876 |
| **Severity** | Medium · 6.5 |
| **Status** | Awaiting Upstream |
**What**
BusyBox wget through 1.37 accepts raw CR/LF and other C0 control bytes in the HTTP
request-target, allowing request line splitting and header injection (CWE-284).
**Who**
- Discovered by: Automated scan (Grype)
- Reported: 2026-03-24
- Affects: Container runtime environment; Charon does not invoke busybox wget in application logic
**Where**
- Component: Alpine 3.23.3 base image (`busybox` 1.37.0-r30)
- Versions affected: All Charon images using Alpine 3.23.3 with busybox < patched version
**When**
- Discovered: 2026-03-24
- Disclosed (if public): Not yet publicly disclosed with fix
- Target fix: When Alpine Security publishes a patched busybox APK
**How**
The vulnerable wget applet would need to be manually invoked inside the container with
attacker-controlled URLs. Charon's application logic does not use busybox wget. EPSS score is
0.00064 (0.20 percentile), indicating extremely low exploitation probability.
**Planned Remediation**
Monitor Alpine 3.23 for a patched busybox APK. No immediate action required. Practical risk to
Charon users is negligible since the vulnerable code path is not exercised.
## Patched Vulnerabilities
### ✅ [LOW] CVE-2026-26958 · edwards25519 MultiScalarMult Invalid Results

View File

@@ -1,6 +1,6 @@
module github.com/Wikid82/charon/backend
go 1.26.1
go 1.26.2
require (
github.com/docker/docker v28.5.2+incompatible
@@ -10,15 +10,15 @@ require (
github.com/golang-jwt/jwt/v5 v5.3.1
github.com/google/uuid v1.6.0
github.com/gorilla/websocket v1.5.3
github.com/mattn/go-sqlite3 v1.14.40
github.com/mattn/go-sqlite3 v1.14.42
github.com/oschwald/geoip2-golang/v2 v2.1.0
github.com/prometheus/client_golang v1.23.2
github.com/robfig/cron/v3 v3.0.1
github.com/sirupsen/logrus v1.9.4
github.com/stretchr/testify v1.11.1
golang.org/x/crypto v0.49.0
golang.org/x/net v0.52.0
golang.org/x/text v0.35.0
golang.org/x/crypto v0.50.0
golang.org/x/net v0.53.0
golang.org/x/text v0.36.0
golang.org/x/time v0.15.0
gopkg.in/natefinch/lumberjack.v2 v2.2.1
gorm.io/driver/sqlite v1.6.0
@@ -58,7 +58,7 @@ require (
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
github.com/kylelemons/godebug v1.1.0 // indirect
github.com/leodido/go-urn v1.4.0 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-isatty v0.0.21 // indirect
github.com/moby/docker-image-spec v1.3.1 // indirect
github.com/moby/sys/atomicwriter v0.1.0 // indirect
github.com/moby/term v0.5.2 // indirect
@@ -84,20 +84,19 @@ require (
github.com/ugorji/go/codec v1.3.1 // indirect
go.mongodb.org/mongo-driver/v2 v2.5.0 // indirect
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.67.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0 // indirect
go.opentelemetry.io/otel v1.43.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.42.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.43.0 // indirect
go.opentelemetry.io/otel/metric v1.43.0 // indirect
go.opentelemetry.io/otel/trace v1.43.0 // indirect
go.yaml.in/yaml/v2 v2.4.4 // indirect
golang.org/x/arch v0.25.0 // indirect
golang.org/x/sys v0.42.0 // indirect
google.golang.org/grpc v1.79.3 // indirect
golang.org/x/arch v0.26.0 // indirect
golang.org/x/sys v0.43.0 // indirect
google.golang.org/protobuf v1.36.11 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
gotest.tools/v3 v3.5.2 // indirect
modernc.org/libc v1.70.0 // indirect
modernc.org/libc v1.72.0 // indirect
modernc.org/mathutil v1.7.1 // indirect
modernc.org/memory v1.11.0 // indirect
modernc.org/sqlite v1.48.1 // indirect
modernc.org/sqlite v1.48.2 // indirect
)

View File

@@ -99,10 +99,10 @@ github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-sqlite3 v1.14.40 h1:f7+saIsbq4EF86mUqe0uiecQOJYMOdfi5uATADmUG94=
github.com/mattn/go-sqlite3 v1.14.40/go.mod h1:pjEuOr8IwzLJP2MfGeTb0A35jauH+C2kbHKBr7yXKVQ=
github.com/mattn/go-isatty v0.0.21 h1:xYae+lCNBP7QuW4PUnNG61ffM4hVIfm+zUzDuSzYLGs=
github.com/mattn/go-isatty v0.0.21/go.mod h1:ZXfXG4SQHsB/w3ZeOYbR0PrPwLy+n6xiMrJlRFqopa4=
github.com/mattn/go-sqlite3 v1.14.42 h1:MigqEP4ZmHw3aIdIT7T+9TLa90Z6smwcthx+Azv4Cgo=
github.com/mattn/go-sqlite3 v1.14.42/go.mod h1:pjEuOr8IwzLJP2MfGeTb0A35jauH+C2kbHKBr7yXKVQ=
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
github.com/moby/sys/atomicwriter v0.1.0 h1:kw5D/EqkBwsBFi0ss9v1VG3wIkVhzGvLklJ+w3A14Sw=
@@ -177,55 +177,54 @@ go.mongodb.org/mongo-driver/v2 v2.5.0 h1:yXUhImUjjAInNcpTcAlPHiT7bIXhshCTL3jVBkF
go.mongodb.org/mongo-driver/v2 v2.5.0/go.mod h1:yOI9kBsufol30iFsl1slpdq1I0eHPzybRWdyYUs8K/0=
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.67.0 h1:OyrsyzuttWTSur2qN/Lm0m2a8yqyIjUVBZcxFPuXq2o=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.67.0/go.mod h1:C2NGBr+kAB4bk3xtMXfZ94gqFDtg/GkI7e9zqGh5Beg=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0 h1:CqXxU8VOmDefoh0+ztfGaymYbhdB/tT3zs79QaZTNGY=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0/go.mod h1:BuhAPThV8PBHBvg8ZzZ/Ok3idOdhWIodywz2xEcRbJo=
go.opentelemetry.io/otel v1.43.0 h1:mYIM03dnh5zfN7HautFE4ieIig9amkNANT+xcVxAj9I=
go.opentelemetry.io/otel v1.43.0/go.mod h1:JuG+u74mvjvcm8vj8pI5XiHy1zDeoCS2LB1spIq7Ay0=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.42.0 h1:THuZiwpQZuHPul65w4WcwEnkX2QIuMT+UFoOrygtoJw=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.42.0/go.mod h1:J2pvYM5NGHofZ2/Ru6zw/TNWnEQp5crgyDeSrYpXkAw=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.42.0 h1:uLXP+3mghfMf7XmV4PkGfFhFKuNWoCvvx5wP/wOXo0o=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.42.0/go.mod h1:v0Tj04armyT59mnURNUJf7RCKcKzq+lgJs6QSjHjaTc=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0 h1:88Y4s2C8oTui1LGM6bTWkw0ICGcOLCAI5l6zsD1j20k=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0/go.mod h1:Vl1/iaggsuRlrHf/hfPJPvVag77kKyvrLeD10kpMl+A=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.43.0 h1:3iZJKlCZufyRzPzlQhUIWVmfltrXuGyfjREgGP3UUjc=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.43.0/go.mod h1:/G+nUPfhq2e+qiXMGxMwumDrP5jtzU+mWN7/sjT2rak=
go.opentelemetry.io/otel/metric v1.43.0 h1:d7638QeInOnuwOONPp4JAOGfbCEpYb+K6DVWvdxGzgM=
go.opentelemetry.io/otel/metric v1.43.0/go.mod h1:RDnPtIxvqlgO8GRW18W6Z/4P462ldprJtfxHxyKd2PY=
go.opentelemetry.io/otel/sdk v1.42.0 h1:LyC8+jqk6UJwdrI/8VydAq/hvkFKNHZVIWuslJXYsDo=
go.opentelemetry.io/otel/sdk v1.42.0/go.mod h1:rGHCAxd9DAph0joO4W6OPwxjNTYWghRWmkHuGbayMts=
go.opentelemetry.io/otel/sdk/metric v1.42.0 h1:D/1QR46Clz6ajyZ3G8SgNlTJKBdGp84q9RKCAZ3YGuA=
go.opentelemetry.io/otel/sdk/metric v1.42.0/go.mod h1:Ua6AAlDKdZ7tdvaQKfSmnFTdHx37+J4ba8MwVCYM5hc=
go.opentelemetry.io/otel/sdk v1.43.0 h1:pi5mE86i5rTeLXqoF/hhiBtUNcrAGHLKQdhg4h4V9Dg=
go.opentelemetry.io/otel/sdk v1.43.0/go.mod h1:P+IkVU3iWukmiit/Yf9AWvpyRDlUeBaRg6Y+C58QHzg=
go.opentelemetry.io/otel/sdk/metric v1.43.0 h1:S88dyqXjJkuBNLeMcVPRFXpRw2fuwdvfCGLEo89fDkw=
go.opentelemetry.io/otel/sdk/metric v1.43.0/go.mod h1:C/RJtwSEJ5hzTiUz5pXF1kILHStzb9zFlIEe85bhj6A=
go.opentelemetry.io/otel/trace v1.43.0 h1:BkNrHpup+4k4w+ZZ86CZoHHEkohws8AY+WTX09nk+3A=
go.opentelemetry.io/otel/trace v1.43.0/go.mod h1:/QJhyVBUUswCphDVxq+8mld+AvhXZLhe+8WVFxiFff0=
go.opentelemetry.io/proto/otlp v1.9.0 h1:l706jCMITVouPOqEnii2fIAuO3IVGBRPV5ICjceRb/A=
go.opentelemetry.io/proto/otlp v1.9.0/go.mod h1:xE+Cx5E/eEHw+ISFkwPLwCZefwVjY+pqKg1qcK03+/4=
go.opentelemetry.io/proto/otlp v1.10.0 h1:IQRWgT5srOCYfiWnpqUYz9CVmbO8bFmKcwYxpuCSL2g=
go.opentelemetry.io/proto/otlp v1.10.0/go.mod h1:/CV4QoCR/S9yaPj8utp3lvQPoqMtxXdzn7ozvvozVqk=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y=
go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU=
go.yaml.in/yaml/v2 v2.4.4 h1:tuyd0P+2Ont/d6e2rl3be67goVK4R6deVxCUX5vyPaQ=
go.yaml.in/yaml/v2 v2.4.4/go.mod h1:gMZqIpDtDqOfM0uNfy0SkpRhvUryYH0Z6wdMYcacYXQ=
golang.org/x/arch v0.25.0 h1:qnk6Ksugpi5Bz32947rkUgDt9/s5qvqDPl/gBKdMJLE=
golang.org/x/arch v0.25.0/go.mod h1:0X+GdSIP+kL5wPmpK7sdkEVTt2XoYP0cSjQSbZBwOi8=
golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4=
golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA=
golang.org/x/mod v0.33.0 h1:tHFzIWbBifEmbwtGz65eaWyGiGZatSrT9prnU8DbVL8=
golang.org/x/mod v0.33.0/go.mod h1:swjeQEj+6r7fODbD2cqrnje9PnziFuw4bmLbBZFrQ5w=
golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0=
golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw=
golang.org/x/arch v0.26.0 h1:jZ6dpec5haP/fUv1kLCbuJy6dnRrfX6iVK08lZBFpk4=
golang.org/x/arch v0.26.0/go.mod h1:0X+GdSIP+kL5wPmpK7sdkEVTt2XoYP0cSjQSbZBwOi8=
golang.org/x/crypto v0.50.0 h1:zO47/JPrL6vsNkINmLoo/PH1gcxpls50DNogFvB5ZGI=
golang.org/x/crypto v0.50.0/go.mod h1:3muZ7vA7PBCE6xgPX7nkzzjiUq87kRItoJQM1Yo8S+Q=
golang.org/x/mod v0.34.0 h1:xIHgNUUnW6sYkcM5Jleh05DvLOtwc6RitGHbDk4akRI=
golang.org/x/mod v0.34.0/go.mod h1:ykgH52iCZe79kzLLMhyCUzhMci+nQj+0XkbXpNYtVjY=
golang.org/x/net v0.53.0 h1:d+qAbo5L0orcWAr0a9JweQpjXF19LMXJE8Ey7hwOdUA=
golang.org/x/net v0.53.0/go.mod h1:JvMuJH7rrdiCfbeHoo3fCQU24Lf5JJwT9W3sJFulfgs=
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo=
golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
golang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8=
golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA=
golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI=
golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg=
golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164=
golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U=
golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno=
golang.org/x/tools v0.42.0 h1:uNgphsn75Tdz5Ji2q36v/nsFSfR/9BRFvqhGBaJGd5k=
golang.org/x/tools v0.42.0/go.mod h1:Ma6lCIwGZvHK6XtgbswSoWroEkhugApmsXyrUmBhfr0=
google.golang.org/genproto/googleapis/api v0.0.0-20260209200024-4cfbd4190f57 h1:JLQynH/LBHfCTSbDWl+py8C+Rg/k1OVH3xfcaiANuF0=
google.golang.org/genproto/googleapis/api v0.0.0-20260209200024-4cfbd4190f57/go.mod h1:kSJwQxqmFXeo79zOmbrALdflXQeAYcUbgS7PbpMknCY=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260209200024-4cfbd4190f57 h1:mWPCjDEyshlQYzBpMNHaEof6UX1PmHcaUODUywQ0uac=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260209200024-4cfbd4190f57/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ=
google.golang.org/grpc v1.79.3 h1:sybAEdRIEtvcD68Gx7dmnwjZKlyfuc61Dyo9pGXXkKE=
google.golang.org/grpc v1.79.3/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ=
golang.org/x/tools v0.43.0 h1:12BdW9CeB3Z+J/I/wj34VMl8X+fEXBxVR90JeMX5E7s=
golang.org/x/tools v0.43.0/go.mod h1:uHkMso649BX2cZK6+RpuIPXS3ho2hZo4FVwfoy1vIk0=
google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9 h1:VPWxll4HlMw1Vs/qXtN7BvhZqsS9cdAittCNvVENElA=
google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9/go.mod h1:7QBABkRtR8z+TEnmXTqIqwJLlzrZKVfAUm7tY3yGv0M=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260401024825-9d38bb4040a9 h1:m8qni9SQFH0tJc1X0vmnpw/0t+AImlSvp30sEupozUg=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260401024825-9d38bb4040a9/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
google.golang.org/grpc v1.80.0 h1:Xr6m2WmWZLETvUNvIUmeD5OAagMw3FiKmMlTdViWsHM=
google.golang.org/grpc v1.80.0/go.mod h1:ho/dLnxwi3EDJA4Zghp7k2Ec1+c2jqup0bFkw07bwF4=
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
@@ -242,10 +241,10 @@ gorm.io/gorm v1.31.1 h1:7CA8FTFz/gRfgqgpeKIBcervUn3xSyPUmr6B2WXJ7kg=
gorm.io/gorm v1.31.1/go.mod h1:XyQVbO2k6YkOis7C2437jSit3SsDK72s7n7rsSHd+Gs=
gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q=
gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA=
modernc.org/cc/v4 v4.27.1 h1:9W30zRlYrefrDV2JE2O8VDtJ1yPGownxciz5rrbQZis=
modernc.org/cc/v4 v4.27.1/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0=
modernc.org/ccgo/v4 v4.32.0 h1:hjG66bI/kqIPX1b2yT6fr/jt+QedtP2fqojG2VrFuVw=
modernc.org/ccgo/v4 v4.32.0/go.mod h1:6F08EBCx5uQc38kMGl+0Nm0oWczoo1c7cgpzEry7Uc0=
modernc.org/cc/v4 v4.27.3 h1:uNCgn37E5U09mTv1XgskEVUJ8ADKpmFMPxzGJ0TSo+U=
modernc.org/cc/v4 v4.27.3/go.mod h1:3YjcbCqhoTTHPycJDRl2WZKKFj0nwcOIPBfEZK0Hdk8=
modernc.org/ccgo/v4 v4.32.4 h1:L5OB8rpEX4ZsXEQwGozRfJyJSFHbbNVOoQ59DU9/KuU=
modernc.org/ccgo/v4 v4.32.4/go.mod h1:lY7f+fiTDHfcv6YlRgSkxYfhs+UvOEEzj49jAn2TOx0=
modernc.org/fileutil v1.4.0 h1:j6ZzNTftVS054gi281TyLjHPp6CPHr2KCxEXjEbD6SM=
modernc.org/fileutil v1.4.0/go.mod h1:EqdKFDxiByqxLk8ozOxObDSfcVOv/54xDs/DUHdvCUU=
modernc.org/gc/v2 v2.6.5 h1:nyqdV8q46KvTpZlsw66kWqwXRHdjIlJOhG6kxiV/9xI=
@@ -254,8 +253,8 @@ modernc.org/gc/v3 v3.1.2 h1:ZtDCnhonXSZexk/AYsegNRV1lJGgaNZJuKjJSWKyEqo=
modernc.org/gc/v3 v3.1.2/go.mod h1:HFK/6AGESC7Ex+EZJhJ2Gni6cTaYpSMmU/cT9RmlfYY=
modernc.org/goabi0 v0.2.0 h1:HvEowk7LxcPd0eq6mVOAEMai46V+i7Jrj13t4AzuNks=
modernc.org/goabi0 v0.2.0/go.mod h1:CEFRnnJhKvWT1c1JTI3Avm+tgOWbkOu5oPA8eH8LnMI=
modernc.org/libc v1.70.0 h1:U58NawXqXbgpZ/dcdS9kMshu08aiA6b7gusEusqzNkw=
modernc.org/libc v1.70.0/go.mod h1:OVmxFGP1CI/Z4L3E0Q3Mf1PDE0BucwMkcXjjLntvHJo=
modernc.org/libc v1.72.0 h1:IEu559v9a0XWjw0DPoVKtXpO2qt5NVLAnFaBbjq+n8c=
modernc.org/libc v1.72.0/go.mod h1:tTU8DL8A+XLVkEY3x5E/tO7s2Q/q42EtnNWda/L5QhQ=
modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU=
modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg=
modernc.org/memory v1.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI=
@@ -264,8 +263,8 @@ modernc.org/opt v0.1.4 h1:2kNGMRiUjrp4LcaPuLY2PzUfqM/w9N23quVwhKt5Qm8=
modernc.org/opt v0.1.4/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns=
modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w=
modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE=
modernc.org/sqlite v1.48.1 h1:S85iToyU6cgeojybE2XJlSbcsvcWkQ6qqNXJHtW5hWA=
modernc.org/sqlite v1.48.1/go.mod h1:hWjRO6Tj/5Ik8ieqxQybiEOUXy0NJFNp2tpvVpKlvig=
modernc.org/sqlite v1.48.2 h1:5CnW4uP8joZtA0LedVqLbZV5GD7F/0x91AXeSyjoh5c=
modernc.org/sqlite v1.48.2/go.mod h1:hWjRO6Tj/5Ik8ieqxQybiEOUXy0NJFNp2tpvVpKlvig=
modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0=
modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A=
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=

View File

@@ -0,0 +1,159 @@
# CrowdSec Hub Bootstrapping on Container Startup
## Problem Statement
After a container rebuild, CrowdSec has **zero collections installed** and a **stale hub index**. When users (or the backend) attempt to install collections, they encounter hash mismatch errors because the hub index bundled in the image at build time is outdated by the time the container runs.
The root cause is twofold:
1. `cscli hub update` in the entrypoint only runs if `.index.json` is missing — not if it is stale.
2. `install_hub_items.sh` (which does call `cscli hub update`) is gated behind `SECURITY_CROWDSEC_MODE=local`, an env var that is **deprecated** and no longer set by default. The entrypoint checks `$SECURITY_CROWDSEC_MODE`, but the backend reads `CERBERUS_SECURITY_CROWDSEC_MODE` / `CHARON_SECURITY_CROWDSEC_MODE` — a naming mismatch that means the entrypoint gate never opens.
## Current State Analysis
### Dockerfile (build-time)
| Aspect | What Happens |
|---|---|
| CrowdSec binaries | Built from source in `crowdsec-builder` stage, copied to `/usr/local/bin/{crowdsec,cscli}` |
| Config template | Source config copied to `/etc/crowdsec.dist/` |
| Hub index | **Not pre-populated** — no `cscli hub update` at build time |
| Collections | **Not installed** at build time |
| Symlink | `/etc/crowdsec``/app/data/crowdsec/config` created as root before `USER charon` |
| Helper scripts | `install_hub_items.sh` and `register_bouncer.sh` copied to `/usr/local/bin/` |
### Entrypoint (`.docker/docker-entrypoint.sh`, runtime)
| Step | What Happens | Problem |
|---|---|---|
| Config init | Copies `/etc/crowdsec.dist/*``/app/data/crowdsec/config/` on first run | Works correctly |
| Symlink verify | Confirms `/etc/crowdsec``/app/data/crowdsec/config` | Works correctly |
| LAPI port fix | `sed` replaces `:8080``:8085` in config files | Works correctly |
| Hub update (L313-315) | `cscli hub update` runs **only if** `/etc/crowdsec/hub/.index.json` does not exist | **Bug**: stale index is never refreshed |
| Machine registration | `cscli machines add -a --force` | Works correctly |
| Hub items install (L325-328) | Calls `install_hub_items.sh` **only if** `$SECURITY_CROWDSEC_MODE = "local"` | **Bug**: env var is deprecated, never set; wrong var name vs backend |
| Ownership fix | `chown -R charon:charon` on CrowdSec dirs | Works correctly |
### `install_hub_items.sh` (when invoked)
The script itself is well-structured — it calls `cscli hub update` then installs individual parsers, scenarios, and two collections (`crowdsecurity/http-cve`, `crowdsecurity/base-http-scenarios`). It does **not** install `crowdsecurity/caddy`.
### Backend (`crowdsec_startup.go`)
`ReconcileCrowdSecOnStartup()` checks the database for CrowdSec mode and starts the process if needed. It does **not** call `cscli hub update` or install collections. The `HubService.runCSCLI()` method in `hub_sync.go` does call `cscli hub update` before individual item installs, but this is only triggered by explicit GUI actions (Pull/Apply), not at startup.
## Proposed Changes
### File: `.docker/docker-entrypoint.sh`
**Change 1: Always refresh the hub index**
Replace the conditional hub update (current L313-315):
```sh
# CURRENT (broken):
if [ ! -f "/etc/crowdsec/hub/.index.json" ]; then
echo "Updating CrowdSec hub index..."
timeout 60s cscli hub update 2>/dev/null || echo "⚠️ Hub update timed out or failed, continuing..."
fi
```
With an unconditional update:
```sh
# NEW: Always refresh hub index on startup (stale index causes hash mismatch errors)
echo "Updating CrowdSec hub index..."
if ! timeout 60s cscli hub update 2>&1; then
echo "⚠️ Hub index update failed (network issue?). Collections may fail to install."
echo " CrowdSec will still start with whatever index is cached."
fi
```
**Change 2: Always install required collections (remove env var gate)**
Replace the conditional hub items install (current L322-328):
```sh
# CURRENT (broken — env var never set):
if [ "$SECURITY_CROWDSEC_MODE" = "local" ]; then
echo "Installing CrowdSec hub items..."
if [ -x /usr/local/bin/install_hub_items.sh ]; then
/usr/local/bin/install_hub_items.sh 2>/dev/null || echo "Warning: Some hub items may not have installed"
fi
fi
```
With unconditional execution:
```sh
# NEW: Always ensure required collections are present.
# This is idempotent — already-installed items are skipped by cscli.
# Collections are needed regardless of whether CrowdSec is GUI-enabled,
# because the user can enable CrowdSec at any time via the dashboard
# and expects it to work immediately.
echo "Ensuring CrowdSec hub items are installed..."
if [ -x /usr/local/bin/install_hub_items.sh ]; then
/usr/local/bin/install_hub_items.sh || echo "⚠️ Some hub items may not have installed. CrowdSec can still start."
fi
```
### File: `configs/crowdsec/install_hub_items.sh`
**Change 3: Add `crowdsecurity/caddy` collection**
Add after the existing `crowdsecurity/base-http-scenarios` install:
```sh
# Install Caddy collection (parser + scenarios for Caddy access logs)
echo "Installing Caddy collection..."
cscli collections install crowdsecurity/caddy --force 2>/dev/null || true
```
**Change 4: Remove redundant individual parser installs that are included in collections**
The `crowdsecurity/base-http-scenarios` collection already includes `crowdsecurity/http-logs` and several of the individually installed scenarios. The `crowdsecurity/caddy` collection includes `crowdsecurity/caddy-logs`. Keep the individual installs as fallbacks (they are idempotent), but add a comment noting the overlap. No lines need deletion — the `--force` flag and idempotency make this safe.
### Summary of File Changes
| File | Change | Lines |
|---|---|---|
| `.docker/docker-entrypoint.sh` | Unconditional `cscli hub update` | ~L313-315 |
| `.docker/docker-entrypoint.sh` | Remove `SECURITY_CROWDSEC_MODE` gate on hub items install | ~L322-328 |
| `configs/crowdsec/install_hub_items.sh` | Add `crowdsecurity/caddy` collection install | After L60 |
## Edge Cases
| Scenario | Handling |
|---|---|
| **No network at startup** | `cscli hub update` fails with timeout. The `install_hub_items.sh` also fails. Entrypoint continues — CrowdSec starts with whatever is cached (or no collections). User can retry via GUI. |
| **Hub CDN returns 5xx** | Same as no network — timeout + fallback. |
| **Collections already installed** | `--force` flag makes `cscli collections install` idempotent. It updates to latest if newer version available. |
| **First boot (no prior data volume)** | Config gets copied from `.dist`, hub update runs, collections install. Clean bootstrap path. |
| **Existing data volume (upgrade)** | Config already exists (skips copy), hub update refreshes stale index, collections install/upgrade. |
| **`install_hub_items.sh` missing/not executable** | `-x` check in entrypoint skips it with a log message. CrowdSec starts without collections. |
| **CrowdSec disabled in GUI** | Collections are still installed (they are just config files). No process runs until user enables via GUI. Zero runtime cost. |
## Startup Time Impact
- `cscli hub update`: ~2-5s (single HTTPS request to hub CDN)
- `install_hub_items.sh`: ~10-15s (multiple `cscli` invocations, each checking/installing)
- Total additional startup time: **~12-20s** (first boot) / **~5-10s** (subsequent boots, items cached)
This is acceptable for a container that runs long-lived.
## Acceptance Criteria
1. After `docker compose up` with a fresh data volume, `cscli collections list` shows `crowdsecurity/caddy`, `crowdsecurity/base-http-scenarios`, and `crowdsecurity/http-cve` installed.
2. After `docker compose up` with an existing data volume (stale index), hub index is refreshed and collections remain installed.
3. If the container starts with no network, CrowdSec initialization logs warnings but does not crash or block startup.
4. No env var (`SECURITY_CROWDSEC_MODE`) is required for collections to be installed.
5. Startup time increase is < 30 seconds.
## Commit Slicing Strategy
**Decision**: Single PR. Scope is small (3 files, ~15 lines changed), low risk, and all changes are tightly coupled.
**PR-1**: CrowdSec hub bootstrapping fix
- **Scope**: `.docker/docker-entrypoint.sh`, `configs/crowdsec/install_hub_items.sh`
- **Validation**: Manual docker rebuild + verify collections with `cscli collections list`
- **Rollback**: Revert PR; behavior returns to current (broken) state — no data loss risk

View File

@@ -1,159 +1,432 @@
# CrowdSec Hub Bootstrapping on Container Startup
# Nightly Build Vulnerability Remediation Plan
## Problem Statement
**Date**: 2026-04-09
**Status**: Draft — Awaiting Approval
**Scope**: Dependency security patches for 5 HIGH + 3 MEDIUM vulnerability groups
**Target**: Single PR — all changes ship together
**Archived**: Previous plan (CrowdSec Hub Bootstrapping) → `docs/plans/archive/crowdsec-hub-bootstrap-spec.md`
After a container rebuild, CrowdSec has **zero collections installed** and a **stale hub index**. When users (or the backend) attempt to install collections, they encounter hash mismatch errors because the hub index bundled in the image at build time is outdated by the time the container runs.
---
The root cause is twofold:
## 1. Problem Statement
1. `cscli hub update` in the entrypoint only runs if `.index.json` is missing — not if it is stale.
2. `install_hub_items.sh` (which does call `cscli hub update`) is gated behind `SECURITY_CROWDSEC_MODE=local`, an env var that is **deprecated** and no longer set by default. The entrypoint checks `$SECURITY_CROWDSEC_MODE`, but the backend reads `CERBERUS_SECURITY_CROWDSEC_MODE` / `CHARON_SECURITY_CROWDSEC_MODE` — a naming mismatch that means the entrypoint gate never opens.
The Charon nightly build is failing container image vulnerability scans with **5 HIGH-severity** and **multiple MEDIUM-severity** findings. These vulnerabilities exist across three compiled binaries embedded in the container image:
## Current State Analysis
1. **Charon backend** (`/app/charon`) — Go binary built from `backend/go.mod`
2. **Caddy** (`/usr/bin/caddy`) — Built via xcaddy in the Dockerfile Caddy builder stage
3. **CrowdSec** (`/usr/local/bin/crowdsec`, `/usr/local/bin/cscli`) — Built from source in the Dockerfile CrowdSec builder stage
### Dockerfile (build-time)
Additionally, the **nightly branch** was synced from development before the Go 1.26.2 bump landed, so the nightly image was compiled with Go 1.26.1 (confirmed in `ci_failure.log` line 55: `GO_VERSION: 1.26.1`).
| Aspect | What Happens |
|---|---|
| CrowdSec binaries | Built from source in `crowdsec-builder` stage, copied to `/usr/local/bin/{crowdsec,cscli}` |
| Config template | Source config copied to `/etc/crowdsec.dist/` |
| Hub index | **Not pre-populated** — no `cscli hub update` at build time |
| Collections | **Not installed** at build time |
| Symlink | `/etc/crowdsec``/app/data/crowdsec/config` created as root before `USER charon` |
| Helper scripts | `install_hub_items.sh` and `register_bouncer.sh` copied to `/usr/local/bin/` |
---
### Entrypoint (`.docker/docker-entrypoint.sh`, runtime)
## 2. Research Findings
| Step | What Happens | Problem |
|---|---|---|
| Config init | Copies `/etc/crowdsec.dist/*``/app/data/crowdsec/config/` on first run | Works correctly |
| Symlink verify | Confirms `/etc/crowdsec``/app/data/crowdsec/config` | Works correctly |
| LAPI port fix | `sed` replaces `:8080``:8085` in config files | Works correctly |
| Hub update (L313-315) | `cscli hub update` runs **only if** `/etc/crowdsec/hub/.index.json` does not exist | **Bug**: stale index is never refreshed |
| Machine registration | `cscli machines add -a --force` | Works correctly |
| Hub items install (L325-328) | Calls `install_hub_items.sh` **only if** `$SECURITY_CROWDSEC_MODE = "local"` | **Bug**: env var is deprecated, never set; wrong var name vs backend |
| Ownership fix | `chown -R charon:charon` on CrowdSec dirs | Works correctly |
### 2.1 Go Version Audit
### `install_hub_items.sh` (when invoked)
All files on `development` / `main` already reference **Go 1.26.2**:
The script itself is well-structured — it calls `cscli hub update` then installs individual parsers, scenarios, and two collections (`crowdsecurity/http-cve`, `crowdsecurity/base-http-scenarios`). It does **not** install `crowdsecurity/caddy`.
| File | Current Value | Status |
|------|---------------|--------|
| `backend/go.mod` | `go 1.26.2` | ✅ Current |
| `go.work` | `go 1.26.2` | ✅ Current |
| `Dockerfile` (`ARG GO_VERSION`) | `1.26.2` | ✅ Current |
| `.github/workflows/nightly-build.yml` | `'1.26.2'` | ✅ Current |
| `.github/workflows/codecov-upload.yml` | `'1.26.2'` | ✅ Current |
| `.github/workflows/quality-checks.yml` | `'1.26.2'` | ✅ Current |
| `.github/workflows/codeql.yml` | `'1.26.2'` | ✅ Current |
| `.github/workflows/benchmark.yml` | `'1.26.2'` | ✅ Current |
| `.github/workflows/release-goreleaser.yml` | `'1.26.2'` | ✅ Current |
| `.github/workflows/e2e-tests-split.yml` | `'1.26.2'` | ✅ Current |
| `.github/skills/examples/gorm-scanner-ci-workflow.yml` | `'1.26.1'` | ❌ **Stale** |
| `scripts/install-go-1.26.0.sh` | `1.26.0` | ⚠️ Old install script (not used in CI/Docker builds) |
### Backend (`crowdsec_startup.go`)
**Root Cause of Go stdlib CVEs**: The nightly branch's last sync predated the 1.26.2 bump. The next nightly sync from development will propagate 1.26.2 automatically. The only file requiring a fix is the example workflow.
`ReconcileCrowdSecOnStartup()` checks the database for CrowdSec mode and starts the process if needed. It does **not** call `cscli hub update` or install collections. The `HubService.runCSCLI()` method in `hub_sync.go` does call `cscli hub update` before individual item installs, but this is only triggered by explicit GUI actions (Pull/Apply), not at startup.
### 2.2 Vulnerability Inventory
## Proposed Changes
#### HIGH Severity (must fix — merge-blocking)
### File: `.docker/docker-entrypoint.sh`
| # | CVE / GHSA | Package | Current | Fix | Binary | Dep Type |
|---|-----------|---------|---------|-----|--------|----------|
| 1 | CVE-2026-39883 | `go.opentelemetry.io/otel/sdk` | v1.40.0 | v1.43.0 | Caddy | Transitive (Caddy plugins → otelhttp → otel/sdk) |
| 2 | CVE-2026-34986 | `github.com/go-jose/go-jose/v3` | v3.0.4 | **v3.0.5** | Caddy | Transitive (caddy-security → JWT/JOSE stack) |
| 3 | CVE-2026-34986 | `github.com/go-jose/go-jose/v4` | v4.1.3 | **v4.1.4** | Caddy | Transitive (grpc v1.79.3 → go-jose/v4) |
| 4 | CVE-2026-32286 | `github.com/jackc/pgproto3/v2` | v2.3.3 | pgx/v4 v4.18.3 ¹ | CrowdSec | Transitive (CrowdSec → pgx/v4 v4.18.2 → pgproto3/v2) |
**Change 1: Always refresh the hub index**
¹ pgproto3/v2 has **no patched release**. Fix requires upstream migration to pgx/v5 (uses pgproto3/v3). See §5 Risk Assessment.
Replace the conditional hub update (current L313-315):
#### MEDIUM Severity (fix in same pass)
```sh
# CURRENT (broken):
if [ ! -f "/etc/crowdsec/hub/.index.json" ]; then
echo "Updating CrowdSec hub index..."
timeout 60s cscli hub update 2>/dev/null || echo "⚠️ Hub update timed out or failed, continuing..."
fi
| # | CVE / GHSA | Package(s) | Current | Fix | Binary | Dep Type |
|---|-----------|------------|---------|-----|--------|----------|
| 5 | GHSA-xmrv-pmrh-hhx2 | AWS SDK v2: `eventstream` v1.7.1, `cloudwatchlogs` v1.57.2, `kinesis` v1.40.1, `s3` v1.87.3 | See left | Bump all | CrowdSec | Direct deps of CrowdSec v1.7.7 |
| 6 | CVE-2026-32281, -32288, -32289 | Go stdlib | 1.26.1 | **1.26.2** | All (nightly image) | Toolchain |
| 7 | CVE-2026-39882 | OTel HTTP exporters: `otlploghttp` v0.16.0, `otlpmetrichttp` v1.40.0, `otlptracehttp` v1.40.0 | See left | Bump all | Caddy | Transitive (Caddy plugins → OTel exporters) |
### 2.3 Dependency Chain Analysis
#### Backend (`backend/go.mod`)
```
charon/backend (direct)
└─ docker/docker v28.5.2+incompatible (direct)
└─ otelhttp v0.68.0 (indirect)
└─ otel/sdk v1.43.0 (indirect) — already at latest
└─ grpc v1.79.3 (indirect)
└─ otlptracehttp v1.42.0 (indirect) ── CVE-2026-39882
```
With an unconditional update:
Backend resolved versions (verified via `go list -m -json`):
```sh
# NEW: Always refresh hub index on startup (stale index causes hash mismatch errors)
echo "Updating CrowdSec hub index..."
if ! timeout 60s cscli hub update 2>&1; then
echo "⚠️ Hub index update failed (network issue?). Collections may fail to install."
echo " CrowdSec will still start with whatever index is cached."
fi
| Package | Version | Type |
|---------|---------|------|
| `go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp` | v1.42.0 | indirect |
| `google.golang.org/grpc` | v1.79.3 | indirect |
| `go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp` | v0.68.0 | indirect |
**Not present in backend**: go-jose/v3, go-jose/v4, otel/sdk, pgproto3/v2, AWS SDK, otlploghttp, otlpmetrichttp.
#### CrowdSec Binary (Dockerfile `crowdsec-builder` stage)
Source: CrowdSec v1.7.7 `go.mod` (verified via `git clone --depth 1 --branch v1.7.7`):
```
crowdsec v1.7.7
└─ pgx/v4 v4.18.2 (direct) → pgproto3/v2 v2.3.3 (indirect) ── CVE-2026-32286
└─ aws-sdk-go-v2/service/s3 v1.87.3 (direct) ── GHSA-xmrv-pmrh-hhx2
└─ aws-sdk-go-v2/service/cloudwatchlogs v1.57.2 (direct) ── GHSA-xmrv-pmrh-hhx2
└─ aws-sdk-go-v2/service/kinesis v1.40.1 (direct) ── GHSA-xmrv-pmrh-hhx2
└─ aws-sdk-go-v2/aws/protocol/eventstream v1.7.1 (indirect) ── GHSA-xmrv-pmrh-hhx2
└─ otel v1.39.0, otel/metric v1.39.0, otel/trace v1.39.0 (indirect)
```
**Change 2: Always install required collections (remove env var gate)**
Confirmed by Trivy image scan (`trivy-image-report.json`): pgproto3/v2 v2.3.3 flagged in `usr/local/bin/crowdsec` and `usr/local/bin/cscli`.
Replace the conditional hub items install (current L322-328):
#### Caddy Binary (Dockerfile `caddy-builder` stage)
```sh
# CURRENT (broken — env var never set):
if [ "$SECURITY_CROWDSEC_MODE" = "local" ]; then
echo "Installing CrowdSec hub items..."
if [ -x /usr/local/bin/install_hub_items.sh ]; then
/usr/local/bin/install_hub_items.sh 2>/dev/null || echo "Warning: Some hub items may not have installed"
fi
fi
Built via xcaddy with plugins. go.mod is generated at build time. Vulnerable packages enter via:
```
xcaddy build (Caddy v2.11.2 + plugins)
└─ caddy-security v1.1.61 → go-jose/v3 (JWT auth stack) ── CVE-2026-34986
└─ grpc (patched to v1.79.3 in Dockerfile) → go-jose/v4 v4.1.3 ── CVE-2026-34986
└─ Caddy/plugins → otel/sdk v1.40.0 ── CVE-2026-39883
└─ Caddy/plugins → otlploghttp v0.16.0, otlpmetrichttp v1.40.0, otlptracehttp v1.40.0 ── CVE-2026-39882
```
With unconditional execution:
---
```sh
# NEW: Always ensure required collections are present.
# This is idempotent — already-installed items are skipped by cscli.
# Collections are needed regardless of whether CrowdSec is GUI-enabled,
# because the user can enable CrowdSec at any time via the dashboard
# and expects it to work immediately.
echo "Ensuring CrowdSec hub items are installed..."
if [ -x /usr/local/bin/install_hub_items.sh ]; then
/usr/local/bin/install_hub_items.sh || echo "⚠️ Some hub items may not have installed. CrowdSec can still start."
fi
## 3. Technical Specifications
### 3.1 Backend go.mod Changes
**File**: `backend/go.mod` (+ `backend/go.sum` auto-generated)
```bash
cd backend
# Upgrade grpc to v1.80.0 (security patches for transitive deps)
go get google.golang.org/grpc@v1.80.0
# CVE-2026-39882: OTel HTTP exporter (backend only has otlptracehttp)
go get go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp@v1.43.0
go mod tidy
```
### File: `configs/crowdsec/install_hub_items.sh`
Expected `go.mod` diff:
- `google.golang.org/grpc` v1.79.3 → v1.80.0
- `go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp` v1.42.0 → v1.43.0
**Change 3: Add `crowdsecurity/caddy` collection**
### 3.2 Dockerfile — Caddy Builder Stage Patches
Add after the existing `crowdsecurity/base-http-scenarios` install:
**File**: `Dockerfile`, within the caddy-builder `RUN bash -c '...'` block, in the **Stage 2: Apply security patches** section.
```sh
# Install Caddy collection (parser + scenarios for Caddy access logs)
echo "Installing Caddy collection..."
cscli collections install crowdsecurity/caddy --force 2>/dev/null || true
Add after the existing `go get golang.org/x/net@v${XNET_VERSION};` line:
```bash
# CVE-2026-34986: go-jose JOSE/JWT validation bypass
# Fix in v3.0.5 and v4.1.4. Pin here until caddy-security ships fix.
# renovate: datasource=go depName=github.com/go-jose/go-jose/v3
go get github.com/go-jose/go-jose/v3@v3.0.5; \
# renovate: datasource=go depName=github.com/go-jose/go-jose/v4
go get github.com/go-jose/go-jose/v4@v4.1.4; \
# CVE-2026-39883: OTel SDK resource leak
# Fix in v1.43.0. Pin here until Caddy ships with updated OTel.
# renovate: datasource=go depName=go.opentelemetry.io/otel/sdk
go get go.opentelemetry.io/otel/sdk@v1.43.0; \
# CVE-2026-39882: OTel HTTP exporter request smuggling
# renovate: datasource=go depName=go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp
go get go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp@v0.19.0; \
# renovate: datasource=go depName=go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp
go get go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp@v1.43.0; \
# renovate: datasource=go depName=go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp
go get go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp@v1.43.0; \
```
**Change 4: Remove redundant individual parser installs that are included in collections**
Update existing grpc patch line from `v1.79.3``v1.80.0`:
The `crowdsecurity/base-http-scenarios` collection already includes `crowdsecurity/http-logs` and several of the individually installed scenarios. The `crowdsecurity/caddy` collection includes `crowdsecurity/caddy-logs`. Keep the individual installs as fallbacks (they are idempotent), but add a comment noting the overlap. No lines need deletion — the `--force` flag and idempotency make this safe.
```bash
# Before:
go get google.golang.org/grpc@v1.79.3; \
# After:
# CVE-2026-33186: gRPC-Go auth bypass (fixed in v1.79.3)
# CVE-2026-34986: go-jose/v4 transitive fix (requires grpc >= v1.80.0)
# renovate: datasource=go depName=google.golang.org/grpc
go get google.golang.org/grpc@v1.80.0; \
```
### Summary of File Changes
### 3.3 Dockerfile — CrowdSec Builder Stage Patches
| File | Change | Lines |
|---|---|---|
| `.docker/docker-entrypoint.sh` | Unconditional `cscli hub update` | ~L313-315 |
| `.docker/docker-entrypoint.sh` | Remove `SECURITY_CROWDSEC_MODE` gate on hub items install | ~L322-328 |
| `configs/crowdsec/install_hub_items.sh` | Add `crowdsecurity/caddy` collection install | After L60 |
**File**: `Dockerfile`, within the crowdsec-builder `RUN` block that patches dependencies.
## Edge Cases
Add after the existing `go get golang.org/x/net@v${XNET_VERSION}` line:
| Scenario | Handling |
|---|---|
| **No network at startup** | `cscli hub update` fails with timeout. The `install_hub_items.sh` also fails. Entrypoint continues — CrowdSec starts with whatever is cached (or no collections). User can retry via GUI. |
| **Hub CDN returns 5xx** | Same as no network — timeout + fallback. |
| **Collections already installed** | `--force` flag makes `cscli collections install` idempotent. It updates to latest if newer version available. |
| **First boot (no prior data volume)** | Config gets copied from `.dist`, hub update runs, collections install. Clean bootstrap path. |
| **Existing data volume (upgrade)** | Config already exists (skips copy), hub update refreshes stale index, collections install/upgrade. |
| **`install_hub_items.sh` missing/not executable** | `-x` check in entrypoint skips it with a log message. CrowdSec starts without collections. |
| **CrowdSec disabled in GUI** | Collections are still installed (they are just config files). No process runs until user enables via GUI. Zero runtime cost. |
```bash
# CVE-2026-32286: pgproto3/v2 buffer overflow (no v2 fix exists; bump pgx/v4 to latest patch)
# renovate: datasource=go depName=github.com/jackc/pgx/v4
go get github.com/jackc/pgx/v4@v4.18.3 && \
# GHSA-xmrv-pmrh-hhx2: AWS SDK v2 event stream injection
# renovate: datasource=go depName=github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream
go get github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream@v1.7.8 && \
# renovate: datasource=go depName=github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs
go get github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs@v1.68.0 && \
# renovate: datasource=go depName=github.com/aws/aws-sdk-go-v2/service/kinesis
go get github.com/aws/aws-sdk-go-v2/service/kinesis@v1.43.5 && \
# renovate: datasource=go depName=github.com/aws/aws-sdk-go-v2/service/s3
go get github.com/aws/aws-sdk-go-v2/service/s3@v1.99.0 && \
```
## Startup Time Impact
CrowdSec grpc already at v1.80.0 — no change needed.
- `cscli hub update`: ~2-5s (single HTTPS request to hub CDN)
- `install_hub_items.sh`: ~10-15s (multiple `cscli` invocations, each checking/installing)
- Total additional startup time: **~12-20s** (first boot) / **~5-10s** (subsequent boots, items cached)
### 3.4 Example Workflow Fix
This is acceptable for a container that runs long-lived.
**File**: `.github/skills/examples/gorm-scanner-ci-workflow.yml` (line 28)
## Acceptance Criteria
```yaml
# Before:
go-version: "1.26.1"
# After:
go-version: "1.26.2"
```
1. After `docker compose up` with a fresh data volume, `cscli collections list` shows `crowdsecurity/caddy`, `crowdsecurity/base-http-scenarios`, and `crowdsecurity/http-cve` installed.
2. After `docker compose up` with an existing data volume (stale index), hub index is refreshed and collections remain installed.
3. If the container starts with no network, CrowdSec initialization logs warnings but does not crash or block startup.
4. No env var (`SECURITY_CROWDSEC_MODE`) is required for collections to be installed.
5. Startup time increase is < 30 seconds.
### 3.5 Go Stdlib CVEs (nightly branch — no code change needed)
## Commit Slicing Strategy
The nightly workflow syncs `development → nightly` via `git merge --ff-only`. Since `development` already has Go 1.26.2 everywhere:
- Dockerfile `ARG GO_VERSION=1.26.2`
- All CI workflows `GO_VERSION: '1.26.2'`
- `backend/go.mod` `go 1.26.2`
**Decision**: Single PR. Scope is small (3 files, ~15 lines changed), low risk, and all changes are tightly coupled.
The next nightly run at 09:00 UTC will automatically propagate Go 1.26.2 to the nightly branch and rebuild the image.
**PR-1**: CrowdSec hub bootstrapping fix
- **Scope**: `.docker/docker-entrypoint.sh`, `configs/crowdsec/install_hub_items.sh`
- **Validation**: Manual docker rebuild + verify collections with `cscli collections list`
- **Rollback**: Revert PR; behavior returns to current (broken) state — no data loss risk
---
## 4. Implementation Plan
### Phase 1: Playwright Tests (N/A)
No UI/UX changes — this is a dependency-only update. Existing E2E tests validate runtime behavior.
### Phase 2: Backend Implementation
| Task | File(s) | Action |
|------|---------|--------|
| 2.1 | `backend/go.mod`, `backend/go.sum` | Run `go get` commands from §3.1 |
| 2.2 | Verify build | `cd backend && go build ./cmd/api` |
| 2.3 | Verify vet | `cd backend && go vet ./...` |
| 2.4 | Verify tests | `cd backend && go test ./...` |
| 2.5 | Verify vulns | `cd backend && govulncheck ./...` |
### Phase 3: Dockerfile Implementation
| Task | File(s) | Action |
|------|---------|--------|
| 3.1 | `Dockerfile` (caddy-builder, ~L258-280) | Add go-jose v3/v4, OTel SDK, OTel exporter patches per §3.2 |
| 3.2 | `Dockerfile` (caddy-builder, ~L270) | Update grpc patch v1.79.3 → v1.80.0 |
| 3.3 | `Dockerfile` (crowdsec-builder, ~L360-370) | Add pgx, AWS SDK patches per §3.3 |
| 3.3a | CrowdSec binaries | After patching deps, run `go build` on CrowdSec binaries before full Docker build for faster compilation feedback |
| 3.4 | `Dockerfile` | Verify `docker build .` completes successfully (amd64) |
### Phase 4: CI / Misc Fixes
| Task | File(s) | Action |
|------|---------|--------|
| 4.1 | `.github/skills/examples/gorm-scanner-ci-workflow.yml` | Bump Go version 1.26.1 → 1.26.2 |
### Phase 5: Validation
| Task | Validation |
|------|------------|
| 5.1 | `cd backend && go build ./cmd/api` — compiles cleanly |
| 5.2 | `cd backend && go test ./...` — all tests pass |
| 5.3 | `cd backend && go vet ./...` — no issues |
| 5.4 | `cd backend && govulncheck ./...` — 0 findings |
| 5.5 | `docker build -t charon:vuln-fix .` — image builds for amd64 |
| 5.6 | Trivy scan on built image: `docker run --rm -v /var/run/docker.sock:/var/run/docker.sock aquasec/trivy:latest image --severity CRITICAL,HIGH charon:vuln-fix` — 0 HIGH (pgproto3/v2 excepted) |
| 5.7 | Container health: `docker run -d -p 8080:8080 charon:vuln-fix && curl -f http://localhost:8080/health` |
| 5.8 | E2E Playwright tests pass against rebuilt container |
---
## 5. Risk Assessment
### Low Risk
| Change | Risk | Rationale |
|--------|------|-----------|
| `go-jose/v3` v3.0.4 → v3.0.5 | Low | Security patch release only |
| `go-jose/v4` v4.1.3 → v4.1.4 | Low | Security patch release only |
| `otel/sdk` v1.40.0 → v1.43.0 (Caddy) | Low | Minor bumps, backwards compatible |
| `otlptracehttp` v1.42.0 → v1.43.0 (backend) | Low | Minor bump |
| OTel exporters (Caddy) | Low | Minor/patch bumps |
| Go version example fix | None | Non-runtime file |
### Medium Risk
| Change | Risk | Mitigation |
|--------|------|------------|
| `grpc` v1.79.3 → v1.80.0 | Medium | Minor version bump. gRPC is indirect — Charon doesn't use gRPC directly. Run full test suite. Verify Caddy and CrowdSec still compile. |
| AWS SDK major bumps (s3 v1.87→v1.99, cloudwatchlogs v1.57→v1.68, kinesis v1.40→v1.43) | Medium | CrowdSec build may fail if internal APIs changed between versions. Mitigate: run `go mod tidy` after patches and verify CrowdSec binaries compile. **Note:** AWS SDK Go v2 packages use independent semver within the `v1.x.x` line — these are minor version bumps, not major API breaks. |
| `pgx/v4` v4.18.2 → v4.18.3 | Medium | Patch release should be safe. May not fully resolve pgproto3/v2 since no patched v2 exists. |
### Known Limitation: pgproto3/v2 (CVE-2026-32286)
The `pgproto3/v2` module has **no patched release** — the fix exists only in `pgproto3/v3` (used by `pgx/v5`). CrowdSec v1.7.7 uses `pgx/v4` which depends on `pgproto3/v2`. Remediation:
1. Bump `pgx/v4` to v4.18.3 (latest v4 patch) — may transitively resolve the issue
2. If scanner still flags pgproto3/v2 after the bump: document as **accepted risk with upstream tracking**
3. Monitor CrowdSec releases for `pgx/v5` migration
4. Consider upgrading `CROWDSEC_VERSION` ARG if a newer CrowdSec release ships with pgx/v5
---
## 6. Acceptance Criteria
- [ ] `cd backend && go build ./cmd/api` succeeds with zero warnings
- [ ] `cd backend && go test ./...` passes with zero failures
- [ ] `cd backend && go vet ./...` reports zero issues
- [ ] `cd backend && govulncheck ./...` reports zero findings
- [ ] Docker image builds successfully for amd64
- [ ] Trivy/Grype scan of built image shows 0 new HIGH findings (pgproto3/v2 excepted if upstream unpatched)
- [ ] Container starts, health check passes on port 8080
- [ ] Existing E2E Playwright tests pass against rebuilt container
- [ ] No new compile errors in Caddy or CrowdSec builder stages
- [ ] `backend/go.mod` shows updated versions for grpc, otlptracehttp
---
## 7. Commit Slicing Strategy
### Decision: Single PR
**Rationale**: All changes are dependency version bumps with no feature or behavioral changes. They address a single concern (security vulnerability remediation) and should be reviewed and merged atomically to avoid partial-fix states.
**Trigger reasons for single PR**:
- All changes are security patches — cannot ship partial fixes
- Changes span backend + Dockerfile + CI config — logically coupled
- No risk of one slice breaking another
- Total diff is small (go.mod/go.sum + Dockerfile patch lines + 1 YAML fix)
### PR-1: Nightly Build Vulnerability Remediation
**Scope**: All changes in §3.1§3.4
**Files modified**:
| File | Change Type |
|------|-------------|
| `backend/go.mod` | Dependency version bumps (grpc, otlptracehttp) |
| `backend/go.sum` | Auto-generated checksum updates |
| `Dockerfile` | Add `go get` patches in caddy-builder and crowdsec-builder stages |
| `.github/skills/examples/gorm-scanner-ci-workflow.yml` | Go version 1.26.1 → 1.26.2 |
**Dependencies**: None (standalone)
**Validation gates**:
1. `go build` / `go test` / `go vet` / `govulncheck` pass
2. Docker image builds for amd64
3. Trivy/Grype scan passes (0 new HIGH)
4. E2E tests pass
**Rollback**: Revert PR. All changes are version pins — reverting restores previous state with no data migration needed.
### Post-merge Actions
1. Nightly build will automatically sync development → nightly and rebuild the image with all patches
2. Monitor next nightly scan for zero HIGH findings
3. If pgproto3/v2 still flagged: open tracking issue for CrowdSec pgx/v5 upstream migration
4. If any AWS SDK bump breaks CrowdSec compilation: pin to intermediate version and document
---
## 8. CI Failure Amendment: pgx/v4 Module Path Mismatch
**Date**: 2026-04-09
**Failure**: PR #921 `build-and-push` job, step `crowdsec-builder 7/11`
**Error**: `go: github.com/jackc/pgx/v4@v5.9.1: invalid version: go.mod has non-.../v4 module path "github.com/jackc/pgx/v5" (and .../v4/go.mod does not exist) at revision v5.9.1`
### Root Cause
Dockerfile line 386 specifies `go get github.com/jackc/pgx/v4@v5.9.1`. This mixes the v4 module path with a v5 version tag. Go's semantic import versioning rejects this because tag `v5.9.1` declares module path `github.com/jackc/pgx/v5` in its go.mod.
### Fix
**Dockerfile line 386** — change:
```dockerfile
go get github.com/jackc/pgx/v4@v5.9.1 && \
```
to:
```dockerfile
go get github.com/jackc/pgx/v4@v4.18.3 && \
```
No changes needed to the Renovate annotation (line 385) or the CVE comment (line 384) — both are already correct.
### Why v4.18.3
- CrowdSec v1.7.7 uses `github.com/jackc/pgx/v4 v4.18.2` (direct dependency)
- v4.18.3 is the latest and likely final v4 release
- pgproto3/v2 is archived at v2.3.3 (July 2025) — no fix will be released in the v2 line
- The CVE (pgproto3/v2 buffer overflow) can only be fully resolved by CrowdSec migrating to pgx/v5 upstream
- Bumping pgx/v4 to v4.18.3 gets the latest v4 maintenance patch; the CVE remains an accepted risk per §5
### Validation
The same `docker build` that previously failed at step 7/11 should now pass through the CrowdSec dependency patching stage and proceed to compilation (steps 8-11).
---
## 9. Commands Reference
```bash
# === Backend dependency upgrades ===
cd /projects/Charon/backend
go get google.golang.org/grpc@v1.80.0
go get go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp@v1.43.0
go mod tidy
# === Validate backend ===
go build ./cmd/api
go test ./...
go vet ./...
govulncheck ./...
# === Docker build (after Dockerfile edits) ===
cd /projects/Charon
docker build -t charon:vuln-fix .
# === Scan built image ===
docker run --rm \
-v /var/run/docker.sock:/var/run/docker.sock \
aquasec/trivy:latest image \
--severity CRITICAL,HIGH \
charon:vuln-fix
# === Quick container health check ===
docker run -d --name charon-vuln-test -p 8080:8080 charon:vuln-fix
sleep 10
curl -f http://localhost:8080/health
docker stop charon-vuln-test && docker rm charon-vuln-test
```

View File

@@ -1,3 +1,128 @@
# QA Audit Report — Nightly Build Vulnerability Remediation
**Date**: 2026-04-09
**Scope**: Dependency-only update — no feature or UI changes
**Image Under Test**: `charon:vuln-fix` (built 2026-04-09 14:53 UTC, 632MB)
**Branch**: Current working tree (pre-PR)
---
## Gate Results Summary
| # | Gate | Status | Details |
|---|------|--------|---------|
| 1 | E2E Playwright (Firefox 4/4 shards + Chromium spot check) | PASS | 19 passed, 20 skipped (security suite), 0 failed |
| 2 | Backend Tests + Coverage | PASS | All tests pass, 88.2% statements / 88.4% lines (gate: 87%) |
| 3 | Frontend Tests + Coverage | PASS | 791 passed, 41 skipped, 89.38% stmts / 90.13% lines (gate: 87%) |
| 4 | Local Patch Coverage Report | PASS | 0 changed lines (dependency-only), 100% patch coverage |
| 5 | Frontend Type Check (tsc --noEmit) | PASS | Zero TypeScript errors |
| 6 | Pre-commit Hooks (lefthook) | PASS | All hooks passed (shellcheck, actionlint, dockerfile-check, YAML, EOF/whitespace) |
| 7a | Trivy Filesystem Scan (CRITICAL/HIGH) | PASS | 0 vulnerabilities in source |
| 7b | govulncheck (backend) | INFO | 2 findings — both `docker/docker` v28.5.2 with no upstream fix (pre-existing, documented in SECURITY.md) |
| 7c | Docker Image Scan (Grype) | PASS | 0 CRITICAL, 2 HIGH (both unfixed Alpine OpenSSL), all target CVEs resolved |
| 8 | Linting (make lint-fast) | PASS | 0 issues |
| 9 | GORM Security Scan (--check) | PASS | 0 CRITICAL, 0 HIGH, 2 INFO suggestions |
**Overall Status: PASS**
---
## Vulnerability Remediation Verification
### Target CVEs — All Resolved
All CVEs identified in the spec (`docs/plans/current_spec.md`) were verified as absent from the `charon:vuln-fix` image:
| CVE / GHSA | Package | Was | Now | Status |
|-----------|---------|-----|-----|--------|
| CVE-2026-39883 | otel/sdk | v1.40.0 | v1.43.0 | Resolved |
| CVE-2026-34986 | go-jose/v3 | v3.0.4 | v3.0.5 | Resolved |
| CVE-2026-34986 | go-jose/v4 | v4.1.3 | v4.1.4 | Resolved |
| CVE-2026-32286 | pgproto3/v2 | v2.3.3 | Not detected | Resolved |
| GHSA-xmrv-pmrh-hhx2 | AWS SDK v2 (multiple) | various | Patched | Resolved |
| CVE-2026-39882 | OTel HTTP exporters | v1.40.0v1.42.0 | v1.43.0 | Resolved |
| CVE-2026-32281/32288/32289 | Go stdlib | 1.26.1 | 1.26.2 | Resolved (via Dockerfile ARG) |
### Remaining Vulnerabilities in Docker Image (Pre-existing, Unfixed Upstream)
| Severity | CVE | Package | Version | Status |
|----------|-----|---------|---------|--------|
| HIGH | CVE-2026-31790 | libcrypto3, libssl3 | 3.5.5-r0 | Awaiting Alpine patch |
| Medium | CVE-2025-60876 | busybox | 1.37.0-r30 | Awaiting Alpine patch |
| Medium | GHSA-6jwv-w5xf-7j27 | go.etcd.io/bbolt | v1.4.3 | CrowdSec transitive dep |
| Unknown | CVE-2026-28387/28388/28389/28390/31789 | libcrypto3, libssl3 | 3.5.5-r0 | Awaiting Alpine NVD scoring + patch |
**Note**: CVE-2026-31790 (HIGH, OpenSSL) is a **new finding** not previously documented in SECURITY.md. It affects the Alpine 3.23.3 base image and has no fix available. It is **not introduced by this PR** — it would be present in any image built on Alpine 3.23.3. Recommend adding to SECURITY.md known vulnerabilities section.
### govulncheck Findings (Backend Source — Pre-existing)
| ID | Module | Fixed In | Notes |
|----|--------|----------|-------|
| GO-2026-4887 (CVE-2026-34040) | docker/docker v28.5.2 | N/A | Already in SECURITY.md |
| GO-2026-4883 (CVE-2026-33997) | docker/docker v28.5.2 | N/A | Already in SECURITY.md |
---
## Coverage Details
### Backend (Go)
- Statement coverage: **88.2%**
- Line coverage: **88.4%**
- Gate threshold: 87% — **PASSED**
### Frontend (React/TypeScript)
- Statements: **89.38%**
- Branches: **81.86%**
- Functions: **86.71%**
- Lines: **90.13%**
- Gate threshold: 87% — **PASSED**
### Patch Coverage
- Changed source lines: **0** (dependency-only update)
- Patch coverage: **100%**
---
## E2E Test Details
Tests executed against `charon:vuln-fix` container on `http://127.0.0.1:8080`:
| Browser | Shards | Passed | Skipped | Failed |
|---------|--------|--------|---------|--------|
| Firefox | 4/4 | 11 | 20 | 0 |
| Chromium | 1/4 (spot) | 8 | 0 | 0 |
Skipped tests are from the security suite (separate project configuration). No test failures observed. The full 3-browser suite will run in CI.
---
## GORM Scanner Details
- Scanned: 43 Go files (2401 lines)
- CRITICAL: 0
- HIGH: 0
- MEDIUM: 0
- INFO: 2 (missing indexes on `UserPermittedHost` foreign keys — pre-existing, non-blocking)
---
## Recommendations
1. **Add CVE-2026-31790 to SECURITY.md** — New HIGH OpenSSL vulnerability in Alpine base image. No fix available. Monitor Alpine security advisories.
2. **Monitor docker/docker module migration** — 2 govulncheck findings with no upstream fix. Track moby/moby/v2 stabilization.
3. **Monitor bbolt GHSA-6jwv-w5xf-7j27** — Medium severity in CrowdSec transitive dependency. Track CrowdSec updates.
4. **Full CI E2E suite** — Local validation passed on Firefox + Chromium spot check. The complete 3-browser suite should run in CI pipeline.
---
## Conclusion
All audit gates **PASS**. The dependency-only changes successfully remediate all 5 HIGH and 3 MEDIUM vulnerability groups identified in the spec. No regressions detected in tests, type safety, linting, or security scans. The remaining HIGH finding (CVE-2026-31790) is a pre-existing Alpine base image issue unrelated to this PR.
**Verdict: Clear to merge.**
# QA Security Audit Report
| Field | Value |

View File

@@ -0,0 +1,322 @@
# QA Security Audit Report
| Field | Value |
|-------------|--------------------------------|
| **Date** | 2026-03-24 |
| **Image** | `charon:local` (Alpine 3.23.3) |
| **Go** | 1.26.1 |
| **Grype** | 0.110.0 |
| **Trivy** | 0.69.1 |
| **CodeQL** | Latest (SARIF v2.1.0) |
---
## Executive Summary
The current `charon:local` image built on 2026-03-24 shows a significantly improved
security posture compared to the CI baseline. Three previously tracked SECURITY.md
vulnerabilities are now **resolved** due to Go 1.26.1 compilation and Alpine package
updates. Two new medium/low findings emerged. No CRITICAL or HIGH active
vulnerabilities remain in the unignored scan results.
| Category | Critical | High | Medium | Low | Total |
|------------------------|----------|------|--------|-----|-------|
| **Active (unignored)** | 0 | 0 | 4 | 2 | 6 |
| **Ignored (documented)**| 0 | 4 | 0 | 0 | 4 |
| **Resolved since last audit** | 1 | 4 | 1 | 0 | 6 |
---
## Scans Executed
| # | Scan | Tool | Result |
|---|-------------------------------|-----------|----------------------|
| 1 | Trivy Filesystem | Trivy | 0 findings (no lang-specific files detected) |
| 2 | Docker Image (SBOM + Grype) | Syft/Grype| 6 active, 8 ignored |
| 3 | Trivy Image Report | Trivy | 1 HIGH (stale Feb 25 report; resolved in current build) |
| 4 | CodeQL Go | CodeQL | 1 finding (false positive — see below) |
| 5 | CodeQL JavaScript | CodeQL | 0 findings |
| 6 | GORM Security Scanner | Custom | PASSED (0 issues, 2 info) |
| 7 | Lefthook / Pre-commit | Lefthook | Configured (project uses `lefthook.yml`, not `.pre-commit-config.yaml`) |
---
## Active Findings (Unignored)
### CVE-2025-60876 — BusyBox wget HTTP Request Smuggling
| Field | Value |
|------------------|-------|
| **Severity** | Medium (CVSS 6.5) |
| **Package** | `busybox` 1.37.0-r30 (Alpine APK) |
| **Affected** | `busybox`, `busybox-binsh`, `busybox-extras`, `ssl_client` (4 matches) |
| **Fix Available** | No |
| **Classification** | AWAITING UPSTREAM |
| **EPSS** | 0.00064 (0.20 percentile) |
**Description**: BusyBox wget through 1.37 accepts raw CR/LF and other C0 control bytes
in the HTTP request-target, allowing request line splitting and header injection (CWE-284).
**Risk Assessment**: Low practical risk. Charon does not invoke `busybox wget` in its
application logic. The vulnerable `wget` applet would need to be manually invoked inside
the container with attacker-controlled URLs.
**Remediation**: Monitor Alpine 3.23 for a patched `busybox` APK. No action required
until upstream ships a fix.
---
### CVE-2026-26958 / GHSA-fw7p-63qq-7hpr — edwards25519 MultiScalarMult Invalid Results
| Field | Value |
|------------------|-------|
| **Severity** | Low (CVSS 1.7) |
| **Package** | `filippo.io/edwards25519` v1.1.0 |
| **Location** | CrowdSec binaries (`/usr/local/bin/crowdsec`, `/usr/local/bin/cscli`) |
| **Fix Available** | v1.1.1 |
| **Classification** | AWAITING UPSTREAM |
| **EPSS** | 0.00018 (0.04 percentile) |
**Description**: `MultiScalarMult` produces invalid results or undefined behavior if
the receiver is not the identity point. This is a rarely used, advanced API.
**Risk Assessment**: Minimal. CrowdSec does not directly expose edwards25519
`MultiScalarMult` to external input. The fix exists at v1.1.1 but requires CrowdSec
to rebuild with the updated dependency.
**Remediation**: Awaiting CrowdSec upstream release with updated dependency. No
action available for Charon maintainers.
---
## Ignored Findings (Documented with Justification)
These findings are suppressed in the Grype configuration with documented risk
acceptance rationale. All are in third-party binaries bundled in the container;
none are in Charon's own code.
### CVE-2026-2673 — OpenSSL TLS 1.3 Key Exchange Group Downgrade
| Field | Value |
|------------------|-------|
| **Severity** | High (CVSS 7.5) |
| **Package** | `libcrypto3` / `libssl3` 3.5.5-r0 |
| **Matches** | 2 (libcrypto3, libssl3) |
| **Classification** | ALREADY DOCUMENTED · AWAITING UPSTREAM |
Charon terminates TLS at the Caddy layer; the Go backend does not act as a raw
TLS 1.3 server. Alpine 3.23 still ships 3.5.5-r0. Risk accepted pending Alpine patch.
---
### GHSA-6g7g-w4f8-9c9x — DoS in buger/jsonparser (CrowdSec)
| Field | Value |
|------------------|-------|
| **Severity** | High (CVSS 7.5) |
| **Package** | `github.com/buger/jsonparser` v1.1.1 |
| **Matches** | 2 (crowdsec, cscli binaries) |
| **Fix Available** | v1.1.2 |
| **Classification** | ALREADY DOCUMENTED · AWAITING UPSTREAM |
Charon does not use this package directly. The vector requires reaching CrowdSec's
internal JSON processing pipeline. Risk accepted pending CrowdSec upstream fix.
---
### GHSA-jqcq-xjh3-6g23 / GHSA-x6gf-mpr2-68h6 / CVE-2026-4427 — DoS in pgproto3/v2 (CrowdSec)
| Field | Value |
|------------------|-------|
| **Severity** | High (CVSS 7.5) |
| **Package** | `github.com/jackc/pgproto3/v2` v2.3.3 |
| **Matches** | 4 (2 GHSAs × 2 binaries) |
| **Fix Available** | No (v2 is archived/EOL) |
| **Classification** | ALREADY DOCUMENTED · AWAITING UPSTREAM |
pgproto3/v2 is archived with no fix planned. CrowdSec must migrate to pgx/v5.
Charon uses SQLite, not PostgreSQL; this code path is unreachable in standard
deployment.
---
## Resolved Findings (Since Last SECURITY.md Update)
The following vulnerabilities documented in SECURITY.md are no longer detected in the
current image build. **SECURITY.md should be updated to move these to "Patched
Vulnerabilities".**
### CVE-2025-68121 — Go Stdlib Critical in CrowdSec (RESOLVED)
| Field | Value |
|------------------|-------|
| **Previous Severity** | Critical |
| **Resolution** | CrowdSec binaries now compiled with Go 1.26.1 (was Go 1.25.6) |
| **Verified** | Not detected in Grype scan of current image |
---
### CHARON-2025-001 — CrowdSec Go Stdlib CVE Cluster (RESOLVED)
| Field | Value |
|------------------|-------|
| **Previous Severity** | High |
| **Aliases** | CVE-2025-58183, CVE-2025-58186, CVE-2025-58187, CVE-2025-61729, CVE-2026-25679, CVE-2025-61732, CVE-2026-27142, CVE-2026-27139 |
| **Resolution** | CrowdSec binaries now compiled with Go 1.26.1 |
| **Verified** | None of the aliased CVEs detected in Grype scan |
---
### CVE-2026-27171 — zlib CPU Exhaustion (RESOLVED)
| Field | Value |
|------------------|-------|
| **Previous Severity** | Medium |
| **Resolution** | Alpine now ships `zlib` 1.3.2-r0 (fix threshold: 1.3.2) |
| **Verified** | Not detected in Grype scan; zlib 1.3.2-r0 confirmed in SBOM |
---
### CVE-2026-33186 — gRPC-Go Authorization Bypass (RESOLVED)
| Field | Value |
|------------------|-------|
| **Previous Severity** | Critical |
| **Packages** | `google.golang.org/grpc` v1.74.2 (CrowdSec), v1.79.1 (Caddy) |
| **Resolution** | Upstream releases now include patched gRPC (>= v1.79.3) |
| **Verified** | Not detected in Grype scan; ignore rule present but no match |
---
### GHSA-69x3-g4r3-p962 / CVE-2026-25793 — Nebula ECDSA Malleability (RESOLVED)
| Field | Value |
|------------------|-------|
| **Previous Severity** | High |
| **Package** | `github.com/slackhq/nebula` v1.9.7 in Caddy |
| **Resolution** | Caddy now ships with nebula >= v1.10.3 |
| **Verified** | Not detected in Grype scan; Trivy image report from Feb 25 had this but current build does not |
> **Note**: The stale Trivy image report (`trivy-image-report.json`, dated 2026-02-25) still
> shows CVE-2026-25793. This report predates the current build and should be regenerated.
---
### GHSA-479m-364c-43vc — goxmldsig XML Signature Bypass (RESOLVED)
| Field | Value |
|------------------|-------|
| **Previous Severity** | High |
| **Package** | `github.com/russellhaering/goxmldsig` v1.5.0 in Caddy |
| **Resolution** | Caddy now ships with goxmldsig >= v1.6.0 |
| **Verified** | Not detected in Grype scan; ignore rule present but no match |
---
## CodeQL Analysis
### go/cookie-secure-not-set — FALSE POSITIVE
| Field | Value |
|------------------|-------|
| **Severity** | Medium (CodeQL) |
| **File** | `backend/internal/api/handlers/auth_handler.go:152` |
| **Classification** | FALSE POSITIVE (stale SARIF) |
**Finding**: CodeQL reports "Cookie does not set Secure attribute to true" at line 152.
**Verification**: The `setSecureCookie` function at line 148-156 calls `c.SetCookie()`
with `secure: true` (6th positional argument). The Secure attribute IS set correctly.
This SARIF was generated from a previous code version and does not reflect the current
source. **The CodeQL SARIF files should be regenerated.**
### JavaScript / JS
No findings. Both `codeql-results-javascript.sarif` and `codeql-results-js.sarif` contain
0 results.
---
## GORM Security Scanner
| Metric | Value |
|------------|-------|
| **Result** | PASSED |
| **Files** | 43 Go files (2,396 lines) |
| **Critical** | 0 |
| **High** | 0 |
| **Medium** | 0 |
| **Info** | 2 (missing indexes on foreign keys in `UserPermittedHost`) |
The 2 informational suggestions (`UserID` and `ProxyHostID` missing `gorm:"index"` in
`backend/internal/models/user.go:130-131`) are performance recommendations, not security
issues. They do not block this audit.
---
## CI vs Local Scan Discrepancy
The CI reported **3 Critical, 5 High, 1 Medium**. The local scan on the freshly built
image reports **0 Critical, 0 High, 4 Medium, 2 Low** (active) plus **4 High** (ignored).
**Root causes for the discrepancy:**
1. **Resolved vulnerabilities**: 3 Critical and 4 High findings were resolved by Go 1.26.1
compilation and upstream Caddy/CrowdSec dependency updates since the CI image was built.
2. **Grype ignore rules**: The local scan applies documented risk acceptance rules that
suppress 4 High findings in third-party binaries. CI (Trivy) does not use these rules.
3. **Stale CI artifacts**: The `trivy-image-report.json` dates from 2026-02-25 and does
not reflect the current image state. The `codeql-results-go.sarif` references code that
has since been fixed.
---
## Recommended Actions
### Immediate (This Sprint)
1. **Update SECURITY.md**: Move CVE-2025-68121, CHARON-2025-001, and CVE-2026-27171 to
a "Patched Vulnerabilities" section. Add CVE-2025-60876 and CVE-2026-26958 as new
known vulnerabilities.
2. **Regenerate stale scan artifacts**: Re-run Trivy image scan and CodeQL analysis to
produce current SARIF/JSON files. The existing files predate fixes and produce
misleading CI results.
3. **Clean up Grype ignore rules**: Remove ignore entries for vulnerabilities that are
no longer detected (CVE-2026-33186, GHSA-69x3-g4r3-p962, GHSA-479m-364c-43vc).
Stale ignore rules obscure the actual security posture.
### Next Release
4. **Monitor Alpine APK updates**: Watch for patched `busybox` (CVE-2025-60876) and
`openssl` (CVE-2026-2673) packages in Alpine 3.23.
5. **Monitor CrowdSec releases**: Watch for CrowdSec builds with updated
`filippo.io/edwards25519` >= v1.1.1, `buger/jsonparser` >= v1.1.2, and
`pgx/v5` migration (replacing pgproto3/v2).
6. **Monitor Go 1.26.2-alpine**: When available, bump `GO_VERSION` to pick up any
remaining stdlib patches.
### Informational (Non-Blocking)
7. **GORM indexes**: Consider adding `gorm:"index"` to `UserID` and `ProxyHostID` in
`UserPermittedHost` for query performance.
---
## Gotify Token Review
Verified: No Gotify application tokens appear in scan output, log artifacts, test results,
API examples, or URL query parameters. All diagnostic output is clean.
---
## Conclusion
The Charon container image security posture has materially improved. Six previously known
vulnerabilities are now resolved through Go toolchain and dependency updates. The remaining
active findings are medium/low severity, reside in Alpine base packages and CrowdSec
third-party binaries, and have no available fixes. No vulnerabilities exist in Charon's
own application code. GORM and CodeQL scans confirm the backend code is clean.

File diff suppressed because it is too large Load Diff

View File

@@ -33,16 +33,16 @@
"@radix-ui/react-select": "^2.2.6",
"@radix-ui/react-tabs": "^1.1.13",
"@radix-ui/react-tooltip": "^1.2.8",
"@tanstack/react-query": "^5.96.2",
"axios": "1.14.0",
"@tanstack/react-query": "^5.97.0",
"axios": "1.15.0",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"date-fns": "^4.1.0",
"i18next": "^26.0.3",
"i18next": "^26.0.4",
"i18next-browser-languagedetector": "^8.2.1",
"lucide-react": "^1.7.0",
"react": "^19.2.4",
"react-dom": "^19.2.4",
"lucide-react": "^1.8.0",
"react": "^19.2.5",
"react-dom": "^19.2.5",
"react-hook-form": "^7.72.1",
"react-hot-toast": "^2.6.0",
"react-i18next": "^17.0.2",
@@ -62,17 +62,17 @@
"@testing-library/react": "^16.3.2",
"@testing-library/user-event": "^14.6.1",
"@types/eslint-plugin-jsx-a11y": "^6.10.1",
"@types/node": "^25.5.2",
"@types/node": "^25.6.0",
"@types/react": "^19.2.14",
"@types/react-dom": "^19.2.3",
"@typescript-eslint/eslint-plugin": "^8.58.0",
"@typescript-eslint/parser": "^8.58.0",
"@typescript-eslint/utils": "^8.58.0",
"@typescript-eslint/eslint-plugin": "^8.58.1",
"@typescript-eslint/parser": "^8.58.1",
"@typescript-eslint/utils": "^8.58.1",
"@vitejs/plugin-react": "^6.0.1",
"@vitest/coverage-istanbul": "^4.1.2",
"@vitest/coverage-v8": "^4.1.2",
"@vitest/eslint-plugin": "^1.6.14",
"@vitest/ui": "^4.1.2",
"@vitest/coverage-istanbul": "^4.1.4",
"@vitest/coverage-v8": "^4.1.4",
"@vitest/eslint-plugin": "^1.6.15",
"@vitest/ui": "^4.1.4",
"autoprefixer": "^10.4.27",
"eslint": "^10.2.0",
"eslint-import-resolver-typescript": "^4.4.4",
@@ -88,14 +88,14 @@
"eslint-plugin-testing-library": "^7.16.2",
"eslint-plugin-unicorn": "^64.0.0",
"eslint-plugin-unused-imports": "^4.4.1",
"jsdom": "29.0.1",
"knip": "^6.3.0",
"postcss": "^8.5.8",
"jsdom": "29.0.2",
"knip": "^6.3.1",
"postcss": "^8.5.9",
"tailwindcss": "^4.2.2",
"typescript": "^6.0.2",
"typescript-eslint": "^8.58.0",
"vite": "^8.0.3",
"vitest": "^4.1.2",
"typescript-eslint": "^8.58.1",
"vite": "^8.0.8",
"vitest": "^4.1.4",
"zod-validation-error": "^5.0.0"
},
"overrides": {
@@ -110,7 +110,7 @@
"eslint": "^10.2.0"
},
"@vitejs/plugin-react": {
"vite": "8.0.3"
"vite": "8.0.8"
}
}
}

View File

@@ -1,3 +1,3 @@
go 1.26.1
go 1.26.2
use ./backend

211
package-lock.json generated
View File

@@ -13,14 +13,14 @@
"@bgotink/playwright-coverage": "^0.3.2",
"@playwright/test": "^1.59.1",
"@types/eslint-plugin-jsx-a11y": "^6.10.1",
"@types/node": "^25.5.2",
"@types/node": "^25.6.0",
"dotenv": "^17.4.1",
"markdownlint-cli2": "^0.22.0",
"prettier": "^3.8.1",
"prettier": "^3.8.2",
"prettier-plugin-tailwindcss": "^0.7.2",
"tar": "^7.5.13",
"typescript": "^6.0.2",
"vite": "^8.0.3"
"vite": "^8.0.8"
}
},
"node_modules/@bcoe/v8-coverage": {
@@ -58,7 +58,6 @@
"dev": true,
"license": "MIT",
"optional": true,
"peer": true,
"dependencies": {
"@emnapi/wasi-threads": "1.2.1",
"tslib": "^2.4.0"
@@ -71,7 +70,6 @@
"dev": true,
"license": "MIT",
"optional": true,
"peer": true,
"dependencies": {
"tslib": "^2.4.0"
}
@@ -83,7 +81,6 @@
"dev": true,
"license": "MIT",
"optional": true,
"peer": true,
"dependencies": {
"tslib": "^2.4.0"
}
@@ -326,9 +323,9 @@
}
},
"node_modules/@napi-rs/wasm-runtime": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.2.tgz",
"integrity": "sha512-sNXv5oLJ7ob93xkZ1XnxisYhGYXfaG9f65/ZgYuAu3qt7b3NadcOEhLvx28hv31PgX8SZJRYrAIPQilQmFpLVw==",
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.3.tgz",
"integrity": "sha512-xK9sGVbJWYb08+mTJt3/YV24WxvxpXcXtP6B172paPZ+Ts69Re9dAr7lKwJoeIx8OoeuimEiRZ7umkiUVClmmQ==",
"dev": true,
"license": "MIT",
"optional": true,
@@ -383,9 +380,9 @@
}
},
"node_modules/@oxc-project/types": {
"version": "0.122.0",
"resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.122.0.tgz",
"integrity": "sha512-oLAl5kBpV4w69UtFZ9xqcmTi+GENWOcPF7FCrczTiBbmC0ibXxCwyvZGbO39rCVEuLGAZM84DH0pUIyyv/YJzA==",
"version": "0.124.0",
"resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.124.0.tgz",
"integrity": "sha512-VBFWMTBvHxS11Z5Lvlr3IWgrwhMTXV+Md+EQF0Xf60+wAdsGFTBx7X7K/hP4pi8N7dcm1RvcHwDxZ16Qx8keUg==",
"dev": true,
"license": "MIT",
"funding": {
@@ -409,9 +406,9 @@
}
},
"node_modules/@rolldown/binding-android-arm64": {
"version": "1.0.0-rc.12",
"resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-rc.12.tgz",
"integrity": "sha512-pv1y2Fv0JybcykuiiD3qBOBdz6RteYojRFY1d+b95WVuzx211CRh+ytI/+9iVyWQ6koTh5dawe4S/yRfOFjgaA==",
"version": "1.0.0-rc.15",
"resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-rc.15.tgz",
"integrity": "sha512-YYe6aWruPZDtHNpwu7+qAHEMbQ/yRl6atqb/AhznLTnD3UY99Q1jE7ihLSahNWkF4EqRPVC4SiR4O0UkLK02tA==",
"cpu": [
"arm64"
],
@@ -426,9 +423,9 @@
}
},
"node_modules/@rolldown/binding-darwin-arm64": {
"version": "1.0.0-rc.12",
"resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-rc.12.tgz",
"integrity": "sha512-cFYr6zTG/3PXXF3pUO+umXxt1wkRK/0AYT8lDwuqvRC+LuKYWSAQAQZjCWDQpAH172ZV6ieYrNnFzVVcnSflAg==",
"version": "1.0.0-rc.15",
"resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-rc.15.tgz",
"integrity": "sha512-oArR/ig8wNTPYsXL+Mzhs0oxhxfuHRfG7Ikw7jXsw8mYOtk71W0OkF2VEVh699pdmzjPQsTjlD1JIOoHkLP1Fg==",
"cpu": [
"arm64"
],
@@ -443,9 +440,9 @@
}
},
"node_modules/@rolldown/binding-darwin-x64": {
"version": "1.0.0-rc.12",
"resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-rc.12.tgz",
"integrity": "sha512-ZCsYknnHzeXYps0lGBz8JrF37GpE9bFVefrlmDrAQhOEi4IOIlcoU1+FwHEtyXGx2VkYAvhu7dyBf75EJQffBw==",
"version": "1.0.0-rc.15",
"resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-rc.15.tgz",
"integrity": "sha512-YzeVqOqjPYvUbJSWJ4EDL8ahbmsIXQpgL3JVipmN+MX0XnXMeWomLN3Fb+nwCmP/jfyqte5I3XRSm7OfQrbyxw==",
"cpu": [
"x64"
],
@@ -460,9 +457,9 @@
}
},
"node_modules/@rolldown/binding-freebsd-x64": {
"version": "1.0.0-rc.12",
"resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-rc.12.tgz",
"integrity": "sha512-dMLeprcVsyJsKolRXyoTH3NL6qtsT0Y2xeuEA8WQJquWFXkEC4bcu1rLZZSnZRMtAqwtrF/Ib9Ddtpa/Gkge9Q==",
"version": "1.0.0-rc.15",
"resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-rc.15.tgz",
"integrity": "sha512-9Erhx956jeQ0nNTyif1+QWAXDRD38ZNjr//bSHrt6wDwB+QkAfl2q6Mn1k6OBPerznjRmbM10lgRb1Pli4xZPw==",
"cpu": [
"x64"
],
@@ -477,9 +474,9 @@
}
},
"node_modules/@rolldown/binding-linux-arm-gnueabihf": {
"version": "1.0.0-rc.12",
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-rc.12.tgz",
"integrity": "sha512-YqWjAgGC/9M1lz3GR1r1rP79nMgo3mQiiA+Hfo+pvKFK1fAJ1bCi0ZQVh8noOqNacuY1qIcfyVfP6HoyBRZ85Q==",
"version": "1.0.0-rc.15",
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-rc.15.tgz",
"integrity": "sha512-cVwk0w8QbZJGTnP/AHQBs5yNwmpgGYStL88t4UIaqcvYJWBfS0s3oqVLZPwsPU6M0zlW4GqjP0Zq5MnAGwFeGA==",
"cpu": [
"arm"
],
@@ -494,9 +491,9 @@
}
},
"node_modules/@rolldown/binding-linux-arm64-gnu": {
"version": "1.0.0-rc.12",
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-rc.12.tgz",
"integrity": "sha512-/I5AS4cIroLpslsmzXfwbe5OmWvSsrFuEw3mwvbQ1kDxJ822hFHIx+vsN/TAzNVyepI/j/GSzrtCIwQPeKCLIg==",
"version": "1.0.0-rc.15",
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-rc.15.tgz",
"integrity": "sha512-eBZ/u8iAK9SoHGanqe/jrPnY0JvBN6iXbVOsbO38mbz+ZJsaobExAm1Iu+rxa4S1l2FjG0qEZn4Rc6X8n+9M+w==",
"cpu": [
"arm64"
],
@@ -511,9 +508,9 @@
}
},
"node_modules/@rolldown/binding-linux-arm64-musl": {
"version": "1.0.0-rc.12",
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-rc.12.tgz",
"integrity": "sha512-V6/wZztnBqlx5hJQqNWwFdxIKN0m38p8Jas+VoSfgH54HSj9tKTt1dZvG6JRHcjh6D7TvrJPWFGaY9UBVOaWPw==",
"version": "1.0.0-rc.15",
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-rc.15.tgz",
"integrity": "sha512-ZvRYMGrAklV9PEkgt4LQM6MjQX2P58HPAuecwYObY2DhS2t35R0I810bKi0wmaYORt6m/2Sm+Z+nFgb0WhXNcQ==",
"cpu": [
"arm64"
],
@@ -528,9 +525,9 @@
}
},
"node_modules/@rolldown/binding-linux-ppc64-gnu": {
"version": "1.0.0-rc.12",
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.0-rc.12.tgz",
"integrity": "sha512-AP3E9BpcUYliZCxa3w5Kwj9OtEVDYK6sVoUzy4vTOJsjPOgdaJZKFmN4oOlX0Wp0RPV2ETfmIra9x1xuayFB7g==",
"version": "1.0.0-rc.15",
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.0-rc.15.tgz",
"integrity": "sha512-VDpgGBzgfg5hLg+uBpCLoFG5kVvEyafmfxGUV0UHLcL5irxAK7PKNeC2MwClgk6ZAiNhmo9FLhRYgvMmedLtnQ==",
"cpu": [
"ppc64"
],
@@ -545,9 +542,9 @@
}
},
"node_modules/@rolldown/binding-linux-s390x-gnu": {
"version": "1.0.0-rc.12",
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.0-rc.12.tgz",
"integrity": "sha512-nWwpvUSPkoFmZo0kQazZYOrT7J5DGOJ/+QHHzjvNlooDZED8oH82Yg67HvehPPLAg5fUff7TfWFHQS8IV1n3og==",
"version": "1.0.0-rc.15",
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.0-rc.15.tgz",
"integrity": "sha512-y1uXY3qQWCzcPgRJATPSOUP4tCemh4uBdY7e3EZbVwCJTY3gLJWnQABgeUetvED+bt1FQ01OeZwvhLS2bpNrAQ==",
"cpu": [
"s390x"
],
@@ -562,9 +559,9 @@
}
},
"node_modules/@rolldown/binding-linux-x64-gnu": {
"version": "1.0.0-rc.12",
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-rc.12.tgz",
"integrity": "sha512-RNrafz5bcwRy+O9e6P8Z/OCAJW/A+qtBczIqVYwTs14pf4iV1/+eKEjdOUta93q2TsT/FI0XYDP3TCky38LMAg==",
"version": "1.0.0-rc.15",
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-rc.15.tgz",
"integrity": "sha512-023bTPBod7J3Y/4fzAN6QtpkSABR0rigtrwaP+qSEabUh5zf6ELr9Nc7GujaROuPY3uwdSIXWrvhn1KxOvurWA==",
"cpu": [
"x64"
],
@@ -579,9 +576,9 @@
}
},
"node_modules/@rolldown/binding-linux-x64-musl": {
"version": "1.0.0-rc.12",
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-rc.12.tgz",
"integrity": "sha512-Jpw/0iwoKWx3LJ2rc1yjFrj+T7iHZn2JDg1Yny1ma0luviFS4mhAIcd1LFNxK3EYu3DHWCps0ydXQ5i/rrJ2ig==",
"version": "1.0.0-rc.15",
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-rc.15.tgz",
"integrity": "sha512-witB2O0/hU4CgfOOKUoeFgQ4GktPi1eEbAhaLAIpgD6+ZnhcPkUtPsoKKHRzmOoWPZue46IThdSgdo4XneOLYw==",
"cpu": [
"x64"
],
@@ -596,9 +593,9 @@
}
},
"node_modules/@rolldown/binding-openharmony-arm64": {
"version": "1.0.0-rc.12",
"resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-rc.12.tgz",
"integrity": "sha512-vRugONE4yMfVn0+7lUKdKvN4D5YusEiPilaoO2sgUWpCvrncvWgPMzK00ZFFJuiPgLwgFNP5eSiUlv2tfc+lpA==",
"version": "1.0.0-rc.15",
"resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-rc.15.tgz",
"integrity": "sha512-UCL68NJ0Ud5zRipXZE9dF5PmirzJE4E4BCIOOssEnM7wLDsxjc6Qb0sGDxTNRTP53I6MZpygyCpY8Aa8sPfKPg==",
"cpu": [
"arm64"
],
@@ -613,9 +610,9 @@
}
},
"node_modules/@rolldown/binding-wasm32-wasi": {
"version": "1.0.0-rc.12",
"resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-rc.12.tgz",
"integrity": "sha512-ykGiLr/6kkiHc0XnBfmFJuCjr5ZYKKofkx+chJWDjitX+KsJuAmrzWhwyOMSHzPhzOHOy7u9HlFoa5MoAOJ/Zg==",
"version": "1.0.0-rc.15",
"resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-rc.15.tgz",
"integrity": "sha512-ApLruZq/ig+nhaE7OJm4lDjayUnOHVUa77zGeqnqZ9pn0ovdVbbNPerVibLXDmWeUZXjIYIT8V3xkT58Rm9u5Q==",
"cpu": [
"wasm32"
],
@@ -623,16 +620,18 @@
"license": "MIT",
"optional": true,
"dependencies": {
"@napi-rs/wasm-runtime": "^1.1.1"
"@emnapi/core": "1.9.2",
"@emnapi/runtime": "1.9.2",
"@napi-rs/wasm-runtime": "^1.1.3"
},
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/@rolldown/binding-win32-arm64-msvc": {
"version": "1.0.0-rc.12",
"resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-rc.12.tgz",
"integrity": "sha512-5eOND4duWkwx1AzCxadcOrNeighiLwMInEADT0YM7xeEOOFcovWZCq8dadXgcRHSf3Ulh1kFo/qvzoFiCLOL1Q==",
"version": "1.0.0-rc.15",
"resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-rc.15.tgz",
"integrity": "sha512-KmoUoU7HnN+Si5YWJigfTws1jz1bKBYDQKdbLspz0UaqjjFkddHsqorgiW1mxcAj88lYUE6NC/zJNwT+SloqtA==",
"cpu": [
"arm64"
],
@@ -647,9 +646,9 @@
}
},
"node_modules/@rolldown/binding-win32-x64-msvc": {
"version": "1.0.0-rc.12",
"resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-rc.12.tgz",
"integrity": "sha512-PyqoipaswDLAZtot351MLhrlrh6lcZPo2LSYE+VDxbVk24LVKAGOuE4hb8xZQmrPAuEtTZW8E6D2zc5EUZX4Lw==",
"version": "1.0.0-rc.15",
"resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-rc.15.tgz",
"integrity": "sha512-3P2A8L+x75qavWLe/Dll3EYBJLQmtkJN8rfh+U/eR3MqMgL/h98PhYI+JFfXuDPgPeCB7iZAKiqii5vqOvnA0g==",
"cpu": [
"x64"
],
@@ -664,9 +663,9 @@
}
},
"node_modules/@rolldown/pluginutils": {
"version": "1.0.0-rc.12",
"resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.12.tgz",
"integrity": "sha512-HHMwmarRKvoFsJorqYlFeFRzXZqCt2ETQlEDOb9aqssrnVBB1/+xgTGtuTrIk5vzLNX1MjMtTf7W9z3tsSbrxw==",
"version": "1.0.0-rc.15",
"resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.15.tgz",
"integrity": "sha512-UromN0peaE53IaBRe9W7CjrZgXl90fqGpK+mIZbA3qSTeYqg3pqpROBdIPvOG3F5ereDHNwoHBI2e50n1BDr1g==",
"dev": true,
"license": "MIT"
},
@@ -750,13 +749,13 @@
"license": "MIT"
},
"node_modules/@types/node": {
"version": "25.5.2",
"resolved": "https://registry.npmjs.org/@types/node/-/node-25.5.2.tgz",
"integrity": "sha512-tO4ZIRKNC+MDWV4qKVZe3Ql/woTnmHDr5JD8UI5hn2pwBrHEwOEMZK7WlNb5RKB6EoJ02gwmQS9OrjuFnZYdpg==",
"version": "25.6.0",
"resolved": "https://registry.npmjs.org/@types/node/-/node-25.6.0.tgz",
"integrity": "sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"undici-types": "~7.18.0"
"undici-types": "~7.19.0"
}
},
"node_modules/@types/unist": {
@@ -1912,9 +1911,9 @@
}
},
"node_modules/katex": {
"version": "0.16.44",
"resolved": "https://registry.npmjs.org/katex/-/katex-0.16.44.tgz",
"integrity": "sha512-EkxoDTk8ufHqHlf9QxGwcxeLkWRR3iOuYfRpfORgYfqc8s13bgb+YtRY59NK5ZpRaCwq1kqA6a5lpX8C/eLphQ==",
"version": "0.16.45",
"resolved": "https://registry.npmjs.org/katex/-/katex-0.16.45.tgz",
"integrity": "sha512-pQpZbdBu7wCTmQUh7ufPmLr0pFoObnGUoL/yhtwJDgmmQpbkg/0HSVti25Fu4rmd1oCR6NGWe9vqTWuWv3GcNA==",
"dev": true,
"funding": [
"https://opencollective.com/katex",
@@ -3175,9 +3174,9 @@
}
},
"node_modules/postcss": {
"version": "8.5.8",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.8.tgz",
"integrity": "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==",
"version": "8.5.9",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.9.tgz",
"integrity": "sha512-7a70Nsot+EMX9fFU3064K/kdHWZqGVY+BADLyXc8Dfv+mTLLVl6JzJpPaCZ2kQL9gIJvKXSLMHhqdRRjwQeFtw==",
"dev": true,
"funding": [
{
@@ -3213,9 +3212,9 @@
}
},
"node_modules/prettier": {
"version": "3.8.1",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.1.tgz",
"integrity": "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==",
"version": "3.8.2",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.2.tgz",
"integrity": "sha512-8c3mgTe0ASwWAJK+78dpviD+A8EqhndQPUBpNUIPt6+xWlIigCwfN01lWr9MAede4uqXGTEKeQWTvzb3vjia0Q==",
"dev": true,
"license": "MIT",
"bin": {
@@ -3393,14 +3392,14 @@
}
},
"node_modules/rolldown": {
"version": "1.0.0-rc.12",
"resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.0-rc.12.tgz",
"integrity": "sha512-yP4USLIMYrwpPHEFB5JGH1uxhcslv6/hL0OyvTuY+3qlOSJvZ7ntYnoWpehBxufkgN0cvXxppuTu5hHa/zPh+A==",
"version": "1.0.0-rc.15",
"resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.0-rc.15.tgz",
"integrity": "sha512-Ff31guA5zT6WjnGp0SXw76X6hzGRk/OQq2hE+1lcDe+lJdHSgnSX6nK3erbONHyCbpSj9a9E+uX/OvytZoWp2g==",
"dev": true,
"license": "MIT",
"dependencies": {
"@oxc-project/types": "=0.122.0",
"@rolldown/pluginutils": "1.0.0-rc.12"
"@oxc-project/types": "=0.124.0",
"@rolldown/pluginutils": "1.0.0-rc.15"
},
"bin": {
"rolldown": "bin/cli.mjs"
@@ -3409,21 +3408,21 @@
"node": "^20.19.0 || >=22.12.0"
},
"optionalDependencies": {
"@rolldown/binding-android-arm64": "1.0.0-rc.12",
"@rolldown/binding-darwin-arm64": "1.0.0-rc.12",
"@rolldown/binding-darwin-x64": "1.0.0-rc.12",
"@rolldown/binding-freebsd-x64": "1.0.0-rc.12",
"@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.12",
"@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.12",
"@rolldown/binding-linux-arm64-musl": "1.0.0-rc.12",
"@rolldown/binding-linux-ppc64-gnu": "1.0.0-rc.12",
"@rolldown/binding-linux-s390x-gnu": "1.0.0-rc.12",
"@rolldown/binding-linux-x64-gnu": "1.0.0-rc.12",
"@rolldown/binding-linux-x64-musl": "1.0.0-rc.12",
"@rolldown/binding-openharmony-arm64": "1.0.0-rc.12",
"@rolldown/binding-wasm32-wasi": "1.0.0-rc.12",
"@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.12",
"@rolldown/binding-win32-x64-msvc": "1.0.0-rc.12"
"@rolldown/binding-android-arm64": "1.0.0-rc.15",
"@rolldown/binding-darwin-arm64": "1.0.0-rc.15",
"@rolldown/binding-darwin-x64": "1.0.0-rc.15",
"@rolldown/binding-freebsd-x64": "1.0.0-rc.15",
"@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.15",
"@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.15",
"@rolldown/binding-linux-arm64-musl": "1.0.0-rc.15",
"@rolldown/binding-linux-ppc64-gnu": "1.0.0-rc.15",
"@rolldown/binding-linux-s390x-gnu": "1.0.0-rc.15",
"@rolldown/binding-linux-x64-gnu": "1.0.0-rc.15",
"@rolldown/binding-linux-x64-musl": "1.0.0-rc.15",
"@rolldown/binding-openharmony-arm64": "1.0.0-rc.15",
"@rolldown/binding-wasm32-wasi": "1.0.0-rc.15",
"@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.15",
"@rolldown/binding-win32-x64-msvc": "1.0.0-rc.15"
}
},
"node_modules/run-parallel": {
@@ -3645,14 +3644,14 @@
}
},
"node_modules/tinyglobby": {
"version": "0.2.15",
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
"integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==",
"version": "0.2.16",
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz",
"integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==",
"dev": true,
"license": "MIT",
"dependencies": {
"fdir": "^6.5.0",
"picomatch": "^4.0.3"
"picomatch": "^4.0.4"
},
"engines": {
"node": ">=12.0.0"
@@ -3774,9 +3773,9 @@
"license": "MIT"
},
"node_modules/undici-types": {
"version": "7.18.2",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz",
"integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==",
"version": "7.19.2",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.19.2.tgz",
"integrity": "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg==",
"dev": true,
"license": "MIT"
},
@@ -3825,16 +3824,16 @@
}
},
"node_modules/vite": {
"version": "8.0.3",
"resolved": "https://registry.npmjs.org/vite/-/vite-8.0.3.tgz",
"integrity": "sha512-B9ifbFudT1TFhfltfaIPgjo9Z3mDynBTJSUYxTjOQruf/zHH+ezCQKcoqO+h7a9Pw9Nm/OtlXAiGT1axBgwqrQ==",
"version": "8.0.8",
"resolved": "https://registry.npmjs.org/vite/-/vite-8.0.8.tgz",
"integrity": "sha512-dbU7/iLVa8KZALJyLOBOQ88nOXtNG8vxKuOT4I2mD+Ya70KPceF4IAmDsmU0h1Qsn5bPrvsY9HJstCRh3hG6Uw==",
"dev": true,
"license": "MIT",
"dependencies": {
"lightningcss": "^1.32.0",
"picomatch": "^4.0.4",
"postcss": "^8.5.8",
"rolldown": "1.0.0-rc.12",
"rolldown": "1.0.0-rc.15",
"tinyglobby": "^0.2.15"
},
"bin": {
@@ -3852,7 +3851,7 @@
"peerDependencies": {
"@types/node": "^20.19.0 || >=22.12.0",
"@vitejs/devtools": "^0.1.0",
"esbuild": "^0.27.0",
"esbuild": "^0.27.0 || ^0.28.0",
"jiti": ">=1.21.0",
"less": "^4.0.0",
"sass": "^1.70.0",

View File

@@ -21,13 +21,13 @@
"@types/eslint-plugin-jsx-a11y": "^6.10.1",
"@bgotink/playwright-coverage": "^0.3.2",
"@playwright/test": "^1.59.1",
"@types/node": "^25.5.2",
"@types/node": "^25.6.0",
"dotenv": "^17.4.1",
"markdownlint-cli2": "^0.22.0",
"prettier": "^3.8.1",
"prettier": "^3.8.2",
"prettier-plugin-tailwindcss": "^0.7.2",
"tar": "^7.5.13",
"typescript": "^6.0.2",
"vite": "^8.0.3"
"vite": "^8.0.8"
}
}