Skip to content

fix: harden CrowdSec preset apply and hub data persistence - #1525

Merged
Wikid82 merged 26 commits into
developmentfrom
fix/crowdsec-preset-apply-hardening
Oct 9, 2026
Merged

Wikid82 merged 26 commits into
developmentfrom
fix/crowdsec-preset-apply-hardening

Conversation

@Wikid82

@Wikid82 Wikid82 commented Oct 9, 2026 •

Copy link
Copy Markdown
Owner

Summary

Follow-ups to #1513 (curated CrowdSec preset apply), delivered as one PR because they share one defect family: unsafe mutation and non-durable state in the persistent CrowdSec tree. Plan: docs/plans/current_spec.md; QA report: docs/reports/qa_report.md.

Closes #1514, closes #1515, closes #1516, closes #1517, closes #1523, closes #1524

Part of #1518 (the remaining Playwright-spec cleanup is tracked in #1526 and will be the next piece of work).

Testing

  • Backend: internal/crowdsec and internal/api/handlers pass; coverage 90.9% statements; full golangci-lint config clean (backend and agent).
  • Frontend: type-check, build and Vitest pass; coverage 91.4% lines.
  • Patch coverage: 93.9% overall locally.
  • Container: scripts/crowdsec_data_persistence_test.sh passes 11/11 on a rebuilt image, including recreate-with-same-volume.
  • Build assertion: a mismatched CROWDSEC_VERSION fails the build.
  • Hub behavior: with hub_branch: master, startup no longer queries the version lookup; offline, download commands still fail as expected.
  • E2E: the three CrowdSec security specs pass (27/27, --project=security-tests).
  • Security checks: govulncheck, Trivy (dependency files), Semgrep and all pre-commit hooks clean. CodeQL and the image scan run in CI.
  • Not verified locally: a running agent in the rebuilt container (fix: HubService.Apply renames the whole CrowdSec data dir as its backup #1515 end-to-end) and the Codecov change.

Note: the playwright-ci compose mount belongs to the separate upstream sidecar and is intentionally unchanged.

Claude Code was used to help produce this change.

Hub preset apply and configuration import now take a copy-based snapshot
instead of renaming the CrowdSec data directory, and restore it in place on
failure. Snapshots exclude engine-owned state (live database, data/ and
hub_cache/), are capped at 5 and pruned after every attempt, and preset
apply, import and file writes are serialized on one handler lock. File
writes back up only the replaced file (kept to the last 10).
Apply stricter file validation across the CrowdSec configuration file endpoints, with bounded, per-file backups and atomic writes.
Hub preset apply now surfaces the server result and error like curated presets, and file saves show the server's error message.
Redirect CrowdSec data_dir onto the persistent volume (migrating existing
installs), decide the hub install guard on the JSON installed flag instead of
the inspect exit code, and run a gated, bounded cscli hub upgrade only when
installed items are missing their data files. Adds a recreate integration test
wired into the CrowdSec CI job.
The crowdsec-inline stage injected the version through a symbol that
CrowdSec v1.8.1 does not define, so the linker silently ignored it and
cscli/crowdsec reported an empty version. Point both builds at
go-cs-lib/version.Version, the symbol upstream's own Makefile uses, and
correct the stale N5 comment.

Note: this changes the toolchain recipe key, so verify-toolchain-pin
stays red until the toolchain workflow pushes the new
CHARON_TOOLCHAIN_TAG/DIGEST pin bump to the branch. Those ARG lines
are bot-owned and are not edited here. The build-time version assertion
and the explicit cscli hub branch follow in the next commit.
@codecov

codecov Bot commented Oct 9, 2026 •

Copy link
Copy Markdown

Comment thread backend/internal/api/handlers/crowdsec_files.go Fixed
@github-advanced-security

Copy link
Copy Markdown
Contributor

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

What Enabling Code Scanning Means:

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

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

@github-actions

github-actions Bot commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor

✅ Supply Chain Verification Results

✅ PASSED

📦 SBOM Summary

  • Components: 1870

🔍 Vulnerability Scan

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

📎 Artifacts

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

Generated by Supply Chain Verification workflow • View Details

@Wikid82 Wikid82 self-assigned this Oct 9, 2026
… hub branch deterministic

Assert in the final-stage N5 check that cscli reports v${CROWDSEC_VERSION}
(ARG redeclared in the stage), and pin cscli.hub_branch to master in the
entrypoint-managed config.yaml so hub commands no longer depend on
version.crowdsec.net or a version-named hub-cdn branch. Operator-chosen
values are preserved; the setting is idempotent.
Enable the hub preset apply and file editor specs, replace the tolerant preset assertions in the CrowdSec config spec with deterministic ones, and anchor the file write route stub so it no longer shadows the file list endpoint.
Wikid82 and others added 12 commits October 9, 2026 10:34
…wdSec builds

The x/mod pin was a hard-coded downgrade (v0.40.0) whose go get cascade
dragged x/net, x/crypto and x/text back below the pinned versions in the
bundled caddy, crowdsec and cscli binaries. Make it a shared XMOD_VERSION
arg (v0.41.0), re-assert x/crypto and x/net after it, and fail each builder
stage if the built binaries embed x/net or x/crypto below the pinned
versions.
Enable codecov.notify.manual_trigger and add a notify-codecov job that
runs send-notifications after the backend, frontend and agent uploads,
so codecov/patch is no longer evaluated against a partial report.
…paths

Tighten archive extraction and configuration file endpoints: stricter
destination checks, truncating writes, bounded reads and generic error
responses. Tests added.
Codecov re-evaluates codecov/patch on every upload, so the quick agent and
frontend uploads turned the check red until the ~15 min backend upload
arrived; the manual_trigger/notify-codecov approach from 513440f did not
prevent this.

The backend, frontend and agent jobs now only stage their coverage file as a
1-day artifact. A final `upload-codecov` job downloads them and uploads the
three reports back to back with their original flags, so Codecov no longer
sees partial reports (only a seconds-wide window between the uploads
remains). codecov.notify.manual_trigger and the notify-codecov job are
removed.

To restore the previous behavior, revert this commit together with 513440f.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants