- Updated UsersPage tests to check for specific URL formats instead of regex patterns. - Increased timeout for Go coverage report generation to handle larger repositories. - Cleaned up generated artifacts before running CodeQL analysis to reduce false positives. - Removed outdated QA testing report for authentication fixes on the certificates page. - Added final report confirming successful resolution of authentication issues with certificate endpoints. - Deleted previous test output files to maintain a clean test results directory.
7.1 KiB
SSRF (go/request-forgery) Remediation — Supervisor-Aligned Plan
Status: Planning (active)
This plan remediates CodeQL’s go/request-forgery (CWE-918 / SSRF) in the Go backend by hardening remaining outbound network call sites and removing blanket suppressions.
Constraints (Supervisor requirements)
- Deny-by-default: Only allow outbound targets that are explicitly allowed by policy.
- Docker/service-name deployments: Internal dependencies (notably CrowdSec LAPI and Caddy Admin) may be reached via Docker service names (e.g.,
http://crowdsec:8085,http://caddy:2019), not justlocalhost. The plan must support this safely via explicit allowlists. - No mergeable intermediate state: The global CodeQL exclusion for
go/request-forgeryin .github/codeql/codeql-config.yml must be removed in the same PR as the fixes. - Ignore proxy environment variables: SSRF-sensitive clients must not inherit
HTTP_PROXY/HTTPS_PROXY/NO_PROXYbehavior. - Redirect policy must be explicit: Each call site must either disable redirects or validate each hop against the same SSRF policy.
- Keep TCP dialing scope minimal: Only touch TCP-dial endpoints if they are directly required for
go/request-forgeryremediation or explicitly called out by findings.
In-scope call sites (confirmed)
These are the known SSRF-relevant sinks discovered during recon:
- Uptime monitor HTTP checks:
(*UptimeService).checkMonitorin backend/internal/services/uptime_service.go - CrowdSec LAPI:
(*CrowdsecHandler).GetLAPIDecisionsand(*CrowdsecHandler).CheckLAPIHealthin backend/internal/api/handlers/crowdsec_handler.go - Caddy Admin API client:
caddy.NewClientand(*Client).Load/GetConfig/Pingin backend/internal/caddy/client.go - URL connectivity test path:
utils.TestURLConnectivityin backend/internal/utils/url_testing.go
Existing primitives (use, don’t duplicate)
- URL validation:
ValidateExternalURL(...)in backend/internal/security/url_validator.go - Dial-time checks + redirect controls:
NewSafeHTTPClient(...)in backend/internal/network/safeclient.go
Target security posture
Default outbound policy (external)
- Allow
httpsonly by default (allowhttponly where strictly needed). - Reject userinfo in URLs.
- Block private/reserved/link-local/loopback/multicast ranges for both IPv4/IPv6.
- Validate via DNS resolution and re-validate at connect time (DNS rebinding defense).
Internal service policy (explicit allowlist)
Some internal integrations must target non-public addresses in Docker or localhost scenarios. These are allowed only if:
- The destination hostname is in an explicit allowlist (exact matches; no wildcards).
- The port matches the expected service port.
- Redirects are disabled (recommended) or strictly hop-validated.
- Proxy env vars are ignored.
Implementation direction (plan-level):
- Introduce a single internal-service allowlist configuration surface (e.g., an env-backed list) used by both CrowdSec and Caddy admin client validation.
- Keep defaults strict: allow
localhost/127.0.0.1/::1only, and require explicit config to add Docker service hostnames (crowdsec,caddy).
Redirect policy (per call site)
- Uptime monitor HTTP checks: redirects should be disabled.
- CrowdSec LAPI calls: redirects should be disabled.
- Caddy Admin API calls: redirects should be disabled.
- URL connectivity test (
url_testing.go): keep the current explicit redirect validation behavior (hop-validated) or disable redirects; either is acceptable if CodeQL sees a safe path.
Proxy env var policy
- All SSRF-sensitive
http.Transportinstances used by the above call sites must setProxy: nil(or otherwise guarantee proxy env vars are not consulted). - backend/internal/utils/url_testing.go already demonstrates this; use it as a precedent to standardize behavior.
Phases
Phase 0 — Recon (local-only, not mergeable)
- Temporarily remove the
go/request-forgeryexclusion locally in .github/codeql/codeql-config.yml to surface the full finding list. - Run VS Code task:
shell: Security: CodeQL Go Scan (CI-Aligned) [~60s]. - Record findings with file/function mapping.
Exit criteria: A concrete list of findings drives Phase 1+. This phase alone must not be merged.
Phase 1 — Remediate uptime monitor outbound HTTP
- Update the uptime HTTP/HTTPS path to:
- Validate the URL via
ValidateExternalURL(and use the validated result, not the raw input). - Use a safe HTTP client (dial-time checks) with:
- proxy env vars ignored
- redirects disabled
- Validate the URL via
Acceptance criteria: CodeQL no longer flags the uptime monitor request path.
Phase 2 — Remediate CrowdSec handler direct LAPI calls
- Replace plain
http.Clientusage in:(*CrowdsecHandler).GetLAPIDecisions(*CrowdsecHandler).CheckLAPIHealth
With:
- strict validation of the configured LAPI base URL using the internal-service allowlist policy
- safe URL construction (
net/urlfor query strings) - safe HTTP client configuration:
- redirects disabled
- proxy env vars ignored
Acceptance criteria: CodeQL no longer flags these requests; behavior works for both localhost and Docker service-name deployments when explicitly allowlisted.
Phase 3 — Remediate Caddy admin client base URL and HTTP client
- Validate
adminAPIURLincaddy.NewClientusing the internal-service allowlist policy. - Use a safe HTTP client:
- redirects disabled
- proxy env vars ignored
- dial-time validation enabled
Acceptance criteria: Admin API client cannot be pointed at arbitrary destinations.
Phase 4 — Remove suppressions (atomic with phases 1–3)
- Remove the global query filter exclusion for
go/request-forgeryfrom .github/codeql/codeql-config.yml. - Remove any inline suppressions related to
go/request-forgerythat are no longer required (notably anylgtm [go/request-forgery]style comments).
Acceptance criteria: CodeQL Go scan passes without the global exclusion.
Tests
- Add deterministic unit tests for:
- URL validation rules in
ValidateExternalURL - redirect behavior (disabled vs hop-validated) where applicable
- internal-service allowlist behavior (localhost + explicit service-name allow)
- URL validation rules in
Do not rely on real DNS/network. Prefer httptest.Server and validation-only failure cases.
Definition of Done (DoD)
- VS Code task:
shell: Lint: Pre-commit (All Files)passes. - VS Code task:
shell: Test: Backend with Coveragepasses and backend coverage ≥ 85%. - VS Code task:
shell: Security: CodeQL Go Scan (CI-Aligned) [~60s]passes withgo/request-forgeryenabled (no global exclusion). - Proxy env var behavior is deterministic for SSRF-sensitive clients.
- Redirect behavior is explicit per call site (disabled or hop-validated).