feat: add nightly branch workflow
This commit is contained in:
@@ -14,38 +14,45 @@ This document tracks security vulnerabilities that have been assessed and accept
|
||||
**CVSS**: TBD
|
||||
|
||||
#### Affected Components
|
||||
|
||||
- **busybox**: 1.37.0-r20
|
||||
- **busybox-binsh**: 1.37.0-r20
|
||||
- **ssl_client**: 1.37.0-r20
|
||||
|
||||
#### Vulnerability Description
|
||||
|
||||
CVE-2025-60876 affects multiple busybox utilities in Alpine Linux 3.21. As of 2026-01-11, no patch is available from Alpine Security Team.
|
||||
|
||||
#### Risk Assessment
|
||||
|
||||
**Exploitability**: Low
|
||||
|
||||
- Requires local shell access or specific network conditions
|
||||
- Not directly exposed through application APIs
|
||||
- Container isolation limits attack surface
|
||||
|
||||
**Impact**: Limited
|
||||
|
||||
- busybox provides minimal shell utilities used for healthchecks and diagnostics
|
||||
- ssl_client used internally by Alpine package manager
|
||||
- No direct user input processing through these utilities
|
||||
|
||||
**Mitigation Strategies**:
|
||||
|
||||
1. **Container Isolation**: Running in containerized environment limits local access
|
||||
2. **Network Policies**: Ingress/egress rules restrict network-based exploitation
|
||||
3. **Non-Privileged Container**: Runs as non-root user (caddy user)
|
||||
4. **Read-Only Filesystem**: Application code and binaries mounted read-only where possible
|
||||
|
||||
#### Monitoring Plan
|
||||
|
||||
- **Frequency**: Daily checks of Alpine Security advisories
|
||||
- **Source**: https://security.alpinelinux.org/vuln
|
||||
- **Source**: <https://security.alpinelinux.org/vuln>
|
||||
- **Alert Trigger**: Patch release for CVE-2025-60876
|
||||
- **Action**: Rebuild Docker image with updated Alpine base
|
||||
|
||||
#### Remediation Timeline
|
||||
|
||||
- **Expected Upstream Fix**: TBD (monitoring Alpine Security Team)
|
||||
- **Automatic Remediation**: Will be included in next Docker rebuild after Alpine patch
|
||||
- **Review Date**: 2026-02-11 (30 days) or upon patch release, whichever is sooner
|
||||
@@ -60,37 +67,44 @@ CVE-2025-60876 affects multiple busybox utilities in Alpine Linux 3.21. As of 20
|
||||
**CVSS**: TBD
|
||||
|
||||
#### Affected Components
|
||||
|
||||
- **curl**: 8.14.1-r2
|
||||
- **libcurl**: 8.14.1-r2 (implicit)
|
||||
|
||||
#### Vulnerability Description
|
||||
|
||||
CVE-2025-10966 affects libcurl in Alpine Linux 3.21. As of 2026-01-11, no patch is available from Alpine Security Team.
|
||||
|
||||
#### Risk Assessment
|
||||
|
||||
**Exploitability**: Medium
|
||||
|
||||
- Requires network access and specific request patterns
|
||||
- curl used only in healthcheck scripts and manual debugging
|
||||
- Not exposed directly to user input
|
||||
|
||||
**Impact**: Limited
|
||||
|
||||
- curl invoked only for internal health monitoring
|
||||
- No user-controlled URLs passed to curl
|
||||
- Healthcheck scripts use hardcoded localhost endpoints
|
||||
|
||||
**Mitigation Strategies**:
|
||||
|
||||
1. **Limited Usage**: curl only used for internal healthchecks (`http://localhost:8080/api/v1/health`)
|
||||
2. **No User Input**: All curl invocations use hardcoded, internal URLs
|
||||
3. **Container Isolation**: Network policies restrict external access
|
||||
4. **Alternative Available**: Application can fall back to TCP socket checks
|
||||
|
||||
#### Monitoring Plan
|
||||
|
||||
- **Frequency**: Daily checks of Alpine Security advisories
|
||||
- **Source**: https://security.alpinelinux.org/vuln
|
||||
- **Source**: <https://security.alpinelinux.org/vuln>
|
||||
- **Alert Trigger**: Patch release for CVE-2025-10966
|
||||
- **Action**: Rebuild Docker image with updated Alpine base
|
||||
|
||||
#### Remediation Timeline
|
||||
|
||||
- **Expected Upstream Fix**: TBD (monitoring Alpine Security Team)
|
||||
- **Automatic Remediation**: Will be included in next Docker rebuild after Alpine patch
|
||||
- **Review Date**: 2026-02-11 (30 days) or upon patch release, whichever is sooner
|
||||
@@ -100,16 +114,19 @@ CVE-2025-10966 affects libcurl in Alpine Linux 3.21. As of 2026-01-11, no patch
|
||||
## Review Schedule
|
||||
|
||||
### Quarterly Security Review
|
||||
|
||||
- **Next Review**: 2026-04-11
|
||||
- **Scope**: Re-assess all accepted risks, evaluate alternative base images
|
||||
- **Attendees**: Security team, DevOps, Engineering Director
|
||||
|
||||
### Monthly Monitoring
|
||||
|
||||
- **Frequency**: First Monday of each month
|
||||
- **Scope**: Check Alpine and upstream security advisories
|
||||
- **Action**: Update this document if status changes
|
||||
|
||||
### Continuous Monitoring
|
||||
|
||||
- **Automated**: GitHub Dependabot, Renovate Bot
|
||||
- **Manual**: Daily check of Alpine security feed during active incident periods
|
||||
|
||||
@@ -130,15 +147,18 @@ Accepted risks will be escalated to immediate remediation if:
|
||||
## Alternative Mitigation Considered
|
||||
|
||||
### Switch to Distroless Base Image
|
||||
|
||||
**Status**: Under Evaluation
|
||||
**Timeline**: Q1 2026
|
||||
|
||||
**Pros**:
|
||||
|
||||
- Minimal attack surface (no shell, no package manager)
|
||||
- Faster security patches from Google
|
||||
- Smaller image size
|
||||
|
||||
**Cons**:
|
||||
|
||||
- Debugging challenges (no shell access)
|
||||
- May require custom healthcheck mechanisms
|
||||
- Migration effort required
|
||||
@@ -154,6 +174,7 @@ Accepted risks will be escalated to immediate remediation if:
|
||||
**Review Scheduled**: 2026-02-11
|
||||
|
||||
**Rationale**: The assessed risk from these Medium-severity Alpine CVEs is acceptable given:
|
||||
|
||||
1. Low exploitability in containerized environment
|
||||
2. No upstream patches available
|
||||
3. Effective mitigation strategies in place
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
Server-Side Request Forgery (SSRF) is a critical web security vulnerability where an attacker can abuse server functionality to access or manipulate internal resources. Charon implements comprehensive defense-in-depth SSRF protection across all features that accept user-controlled URLs.
|
||||
|
||||
**Status**: ✅ **CodeQL CWE-918 Resolved** (PR #450)
|
||||
|
||||
- Taint chain break verified via static analysis
|
||||
- Test coverage: 90.2% for URL validation utilities
|
||||
- Zero security vulnerabilities (Trivy, govulncheck clean)
|
||||
@@ -91,10 +92,12 @@ Charon validates all user-controlled URLs in the following features:
|
||||
**Protection**: All webhook URLs are validated before saving to prevent SSRF attacks when security events trigger notifications.
|
||||
|
||||
**Validation on**:
|
||||
|
||||
- Configuration save (fail-fast)
|
||||
- Notification delivery (defense-in-depth)
|
||||
|
||||
**Example Valid URL**:
|
||||
|
||||
```json
|
||||
{
|
||||
"webhook_url": "https://hooks.slack.com/services/T00/B00/XXX"
|
||||
@@ -102,6 +105,7 @@ Charon validates all user-controlled URLs in the following features:
|
||||
```
|
||||
|
||||
**Blocked URLs**:
|
||||
|
||||
- Private IPs: `http://192.168.1.1/admin`
|
||||
- Cloud metadata: `http://169.254.169.254/latest/meta-data/`
|
||||
- Internal hostnames: `http://internal-db.local:3306/`
|
||||
@@ -117,6 +121,7 @@ Charon validates all user-controlled URLs in the following features:
|
||||
**Use Case**: Send notifications to Discord, Slack, or custom monitoring systems.
|
||||
|
||||
**Example Valid URL**:
|
||||
|
||||
```json
|
||||
{
|
||||
"webhook_url": "https://discord.com/api/webhooks/123456/abcdef"
|
||||
@@ -134,6 +139,7 @@ Charon validates all user-controlled URLs in the following features:
|
||||
**Admin Access Required**: Yes (prevents abuse by non-privileged users)
|
||||
|
||||
**Example Usage**:
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8080/api/v1/settings/test-url \
|
||||
-H "Content-Type: application/json" \
|
||||
@@ -150,6 +156,7 @@ curl -X POST http://localhost:8080/api/v1/settings/test-url \
|
||||
**Protection**: CrowdSec hub URLs are validated against an allowlist of official hub domains. Custom hub URLs require HTTPS.
|
||||
|
||||
**Allowed Domains**:
|
||||
|
||||
- `hub-data.crowdsec.net` (official hub)
|
||||
- `raw.githubusercontent.com` (official mirror)
|
||||
- `*.example.com`, `*.local` (test domains, testing only)
|
||||
@@ -165,6 +172,7 @@ curl -X POST http://localhost:8080/api/v1/settings/test-url \
|
||||
**Protection**: GitHub API URLs are validated to ensure only official GitHub domains are queried. Prevents SSRF via update check manipulation.
|
||||
|
||||
**Allowed Domains**:
|
||||
|
||||
- `api.github.com`
|
||||
- `github.com`
|
||||
|
||||
@@ -187,6 +195,7 @@ Charon blocks **13+ IP ranges** to prevent SSRF attacks:
|
||||
| `192.168.0.0/16` | Class C private network | `192.168.1.1` |
|
||||
|
||||
**Attack Example**:
|
||||
|
||||
```bash
|
||||
# Attacker attempts to access internal database
|
||||
curl -X POST /api/v1/settings/security/webhook \
|
||||
@@ -209,6 +218,7 @@ curl -X POST /api/v1/settings/security/webhook \
|
||||
| `100.100.100.200` | Alibaba Cloud | Instance metadata |
|
||||
|
||||
**Attack Example**:
|
||||
|
||||
```bash
|
||||
# Attacker attempts AWS metadata access
|
||||
curl -X POST /api/v1/settings/security/webhook \
|
||||
@@ -219,6 +229,7 @@ curl -X POST /api/v1/settings/security/webhook \
|
||||
```
|
||||
|
||||
**Why This Matters**: Cloud metadata endpoints expose:
|
||||
|
||||
- IAM role credentials (AWS access keys)
|
||||
- Service account tokens (GCP)
|
||||
- Managed identity credentials (Azure)
|
||||
@@ -236,6 +247,7 @@ curl -X POST /api/v1/settings/security/webhook \
|
||||
| `::1/128` | IPv6 loopback | `::1` |
|
||||
|
||||
**Attack Example**:
|
||||
|
||||
```bash
|
||||
# Attacker attempts to access Charon's internal API
|
||||
curl -X POST /api/v1/settings/security/webhook \
|
||||
@@ -277,6 +289,7 @@ Charon uses a **four-stage validation pipeline** for all user-controlled URLs:
|
||||
### Stage 1: URL Format Validation
|
||||
|
||||
**Checks**:
|
||||
|
||||
- ✅ URL is not empty
|
||||
- ✅ URL parses correctly (valid syntax)
|
||||
- ✅ Scheme is `http` or `https` only
|
||||
@@ -284,6 +297,7 @@ Charon uses a **four-stage validation pipeline** for all user-controlled URLs:
|
||||
- ✅ No credentials in URL (e.g., `http://user:pass@example.com`)
|
||||
|
||||
**Blocked Schemes**:
|
||||
|
||||
- `file://` (file system access)
|
||||
- `ftp://` (FTP protocol smuggling)
|
||||
- `gopher://` (legacy protocol exploitation)
|
||||
@@ -291,6 +305,7 @@ Charon uses a **four-stage validation pipeline** for all user-controlled URLs:
|
||||
- `javascript:` (XSS/code injection)
|
||||
|
||||
**Example Validation Failure**:
|
||||
|
||||
```go
|
||||
// Blocked: Invalid scheme
|
||||
err := ValidateExternalURL("file:///etc/passwd")
|
||||
@@ -302,17 +317,20 @@ err := ValidateExternalURL("file:///etc/passwd")
|
||||
### Stage 2: DNS Resolution
|
||||
|
||||
**Checks**:
|
||||
|
||||
- ✅ Hostname resolves via DNS (3-second timeout)
|
||||
- ✅ At least one IP address returned
|
||||
- ✅ Handles both IPv4 and IPv6 addresses
|
||||
- ✅ Prevents DNS timeout attacks
|
||||
|
||||
**Protection Against**:
|
||||
|
||||
- Non-existent domains (typosquatting)
|
||||
- DNS timeout DoS attacks
|
||||
- DNS rebinding (resolved IPs checked immediately before request)
|
||||
|
||||
**Example**:
|
||||
|
||||
```go
|
||||
// Resolve hostname to IPs
|
||||
ips, err := net.LookupIP("webhook.example.com")
|
||||
@@ -331,6 +349,7 @@ for _, ip := range ips {
|
||||
### Stage 3: IP Range Validation
|
||||
|
||||
**Checks**:
|
||||
|
||||
- ✅ ALL resolved IPs are checked (not just the first)
|
||||
- ✅ Private IP ranges blocked (13+ CIDR blocks)
|
||||
- ✅ IPv4 and IPv6 support
|
||||
@@ -338,6 +357,7 @@ for _, ip := range ips {
|
||||
- ✅ Loopback and link-local addresses blocked
|
||||
|
||||
**Validation Logic**:
|
||||
|
||||
```go
|
||||
func isPrivateIP(ip net.IP) bool {
|
||||
// Check loopback and link-local first (fast path)
|
||||
@@ -376,12 +396,14 @@ func isPrivateIP(ip net.IP) bool {
|
||||
### Stage 4: Request Execution
|
||||
|
||||
**Checks**:
|
||||
|
||||
- ✅ Use validated IP explicitly (bypass DNS caching attacks)
|
||||
- ✅ Set timeout (5-10 seconds, context-based)
|
||||
- ✅ Limit redirects (0-2 maximum)
|
||||
- ✅ Log all SSRF attempts with HIGH severity
|
||||
|
||||
**HTTP Client Configuration**:
|
||||
|
||||
```go
|
||||
client := &http.Client{
|
||||
Timeout: 10 * time.Second,
|
||||
@@ -403,16 +425,19 @@ client := &http.Client{
|
||||
**Purpose**: Enable local development and integration testing
|
||||
|
||||
**When Allowed**:
|
||||
|
||||
- URL connectivity testing with `WithAllowLocalhost()` option
|
||||
- Development environment (`CHARON_ENV=development`)
|
||||
- Explicit test fixtures in test code
|
||||
|
||||
**Allowed Addresses**:
|
||||
|
||||
- `localhost` (hostname)
|
||||
- `127.0.0.1` (IPv4)
|
||||
- `::1` (IPv6)
|
||||
|
||||
**Example**:
|
||||
|
||||
```go
|
||||
// Production: Blocked
|
||||
err := ValidateExternalURL("http://localhost:8080/admin")
|
||||
@@ -430,11 +455,13 @@ err := ValidateExternalURL("http://localhost:8080/admin", WithAllowLocalhost())
|
||||
### When to Use `WithAllowLocalhost`
|
||||
|
||||
**✅ Safe Uses**:
|
||||
|
||||
1. **Unit tests**: Testing validation logic with mock servers
|
||||
2. **Integration tests**: Testing against local test fixtures
|
||||
3. **Development mode**: Local webhooks for debugging (with explicit flag)
|
||||
|
||||
**❌ Unsafe Uses**:
|
||||
|
||||
1. Production webhook configurations
|
||||
2. User-facing features without strict access control
|
||||
3. Any scenario where an attacker controls the URL
|
||||
@@ -452,6 +479,7 @@ err := ValidateExternalURL("http://localhost:8080/admin", WithAllowLocalhost())
|
||||
- Container orchestration APIs (Docker, Kubernetes)
|
||||
|
||||
2. **Port Scanning**: Attacker can enumerate services:
|
||||
|
||||
```bash
|
||||
# Scan internal ports via error messages
|
||||
http://localhost:22/ # SSH (connection refused)
|
||||
@@ -492,6 +520,7 @@ err := ValidateExternalURL("http://localhost:8080/admin", WithAllowLocalhost())
|
||||
```
|
||||
|
||||
**Why These Are Safe**:
|
||||
|
||||
- ✅ Use HTTPS (encrypted, authenticated)
|
||||
- ✅ Resolve to public IP addresses
|
||||
- ✅ Operated by known, trusted services
|
||||
@@ -542,6 +571,7 @@ err := ValidateExternalURL("http://localhost:8080/admin", WithAllowLocalhost())
|
||||
```
|
||||
|
||||
**Why These Are Blocked**:
|
||||
|
||||
- ❌ Expose internal network resources
|
||||
- ❌ Allow cloud metadata access (credentials leak)
|
||||
- ❌ Enable protocol smuggling
|
||||
@@ -557,11 +587,13 @@ err := ValidateExternalURL("http://localhost:8080/admin", WithAllowLocalhost())
|
||||
**Attack**: DNS record changes between validation and request execution
|
||||
|
||||
**Charon's Defense**:
|
||||
|
||||
1. Resolve hostname immediately before HTTP request
|
||||
2. Check ALL resolved IPs against blocklist
|
||||
3. Use explicit IP in HTTP client (bypass DNS cache)
|
||||
|
||||
**Example Attack Scenario**:
|
||||
|
||||
```
|
||||
Time T0: Attacker configures webhook: http://evil.com/webhook
|
||||
DNS Resolution: evil.com → 203.0.113.10 (public IP, passes validation)
|
||||
@@ -577,6 +609,7 @@ Time T3: Security event triggers webhook
|
||||
```
|
||||
|
||||
**Protection Mechanism**:
|
||||
|
||||
```go
|
||||
// Validation happens at configuration save AND request time
|
||||
func (s *SecurityNotificationService) sendWebhook(ctx context.Context, webhookURL string, event models.SecurityEvent) error {
|
||||
@@ -602,6 +635,7 @@ func (s *SecurityNotificationService) sendWebhook(ctx context.Context, webhookUR
|
||||
**Attack**: Race condition between validation and request
|
||||
|
||||
**Charon's Defense**:
|
||||
|
||||
- Validation and DNS resolution happen in a single transaction
|
||||
- HTTP request uses resolved IP (no re-resolution)
|
||||
- Timeout prevents long-running requests that could stall validation
|
||||
@@ -613,6 +647,7 @@ func (s *SecurityNotificationService) sendWebhook(ctx context.Context, webhookUR
|
||||
**Attack**: Initial URL is valid, but redirects to private IP
|
||||
|
||||
**Charon's Defense**:
|
||||
|
||||
```go
|
||||
client := &http.Client{
|
||||
CheckRedirect: func(req *http.Request, via []*http.Request) error {
|
||||
@@ -637,6 +672,7 @@ client := &http.Client{
|
||||
**Charon's Approach**: Generic user-facing errors, detailed server logs
|
||||
|
||||
**User-Facing Error**:
|
||||
|
||||
```json
|
||||
{
|
||||
"error": "URL resolves to a private IP address (blocked for security)"
|
||||
@@ -644,17 +680,20 @@ client := &http.Client{
|
||||
```
|
||||
|
||||
**Server Log**:
|
||||
|
||||
```
|
||||
level=HIGH msg="Blocked SSRF attempt" url="http://192.168.1.100/admin" resolved_ip="192.168.1.100" user_id="admin123" timestamp="2025-12-23T10:30:00Z"
|
||||
```
|
||||
|
||||
**What's Hidden**:
|
||||
|
||||
- ❌ Internal IP addresses (except in validation context)
|
||||
- ❌ Network topology details
|
||||
- ❌ Service names or ports
|
||||
- ❌ DNS resolution details
|
||||
|
||||
**What's Revealed**:
|
||||
|
||||
- ✅ Validation failure reason (security context)
|
||||
- ✅ User-friendly explanation
|
||||
- ✅ Security justification
|
||||
@@ -670,11 +709,13 @@ level=HIGH msg="Blocked SSRF attempt" url="http://192.168.1.100/admin" resolved_
|
||||
**Cause**: The URL's hostname resolves to a private IP range (RFC 1918, loopback, link-local).
|
||||
|
||||
**Solutions**:
|
||||
|
||||
1. ✅ Use a publicly accessible webhook endpoint
|
||||
2. ✅ If webhook must be internal, use a public-facing gateway/proxy
|
||||
3. ✅ For development, use a service like ngrok or localtunnel
|
||||
|
||||
**Example Fix**:
|
||||
|
||||
```bash
|
||||
# BAD: Internal IP
|
||||
http://192.168.1.100/webhook
|
||||
@@ -693,11 +734,13 @@ https://abc123.ngrok.io/webhook
|
||||
**Cause**: The URL uses `localhost`, `127.0.0.1`, or `::1` without the localhost exception enabled.
|
||||
|
||||
**Solutions**:
|
||||
|
||||
1. ✅ Use a public webhook service (Slack, Discord, etc.)
|
||||
2. ✅ Deploy webhook receiver on a public server
|
||||
3. ✅ For testing, use test URL endpoint with admin privileges
|
||||
|
||||
**Example Fix**:
|
||||
|
||||
```bash
|
||||
# BAD: Localhost
|
||||
http://localhost:3000/webhook
|
||||
@@ -720,6 +763,7 @@ curl -X POST /api/v1/settings/test-url \
|
||||
**Solution**: Change the URL scheme to `http://` or `https://`.
|
||||
|
||||
**Example Fix**:
|
||||
|
||||
```bash
|
||||
# BAD: File protocol
|
||||
file:///etc/passwd
|
||||
@@ -735,12 +779,14 @@ https://api.example.com/webhook
|
||||
**Cause**: Hostname does not resolve, or the server is unreachable.
|
||||
|
||||
**Solutions**:
|
||||
|
||||
1. ✅ Verify the domain exists and is publicly resolvable
|
||||
2. ✅ Check for typos in the URL
|
||||
3. ✅ Ensure the webhook receiver is running and accessible
|
||||
4. ✅ Test connectivity with `curl` or `ping` from Charon's network
|
||||
|
||||
**Example Debugging**:
|
||||
|
||||
```bash
|
||||
# Test DNS resolution
|
||||
nslookup webhooks.example.com
|
||||
@@ -810,6 +856,7 @@ EOF
|
||||
### When to Contact Security Team
|
||||
|
||||
**Report SSRF bypasses if you can**:
|
||||
|
||||
1. Access private IPs despite validation
|
||||
2. Retrieve cloud metadata endpoints
|
||||
3. Use protocol smuggling to bypass scheme checks
|
||||
@@ -817,6 +864,7 @@ EOF
|
||||
5. Bypass IP range checks with IPv6 or encoding tricks
|
||||
|
||||
**How to Report**:
|
||||
|
||||
- Email: `security@charon.example.com` (if configured)
|
||||
- GitHub Security Advisory: <https://github.com/Wikid82/charon/security/advisories/new>
|
||||
- Include: steps to reproduce, proof of concept (non-destructive)
|
||||
@@ -828,11 +876,13 @@ EOF
|
||||
### How to Use `ValidateExternalURL`
|
||||
|
||||
**Import**:
|
||||
|
||||
```go
|
||||
import "github.com/Wikid82/charon/backend/internal/security"
|
||||
```
|
||||
|
||||
**Basic Usage**:
|
||||
|
||||
```go
|
||||
func SaveWebhookConfig(webhookURL string) error {
|
||||
// Validate before saving to database
|
||||
@@ -847,6 +897,7 @@ func SaveWebhookConfig(webhookURL string) error {
|
||||
```
|
||||
|
||||
**With Options**:
|
||||
|
||||
```go
|
||||
// Allow HTTP (not recommended for production)
|
||||
validatedURL, err := security.ValidateExternalURL(webhookURL,
|
||||
@@ -907,11 +958,13 @@ For runtime HTTP requests where SSRF protection must be enforced at connection t
|
||||
3. **Layer 3: Redirect Validation** - Each redirect target is validated before following
|
||||
|
||||
**Import**:
|
||||
|
||||
```go
|
||||
import "github.com/Wikid82/charon/backend/internal/network"
|
||||
```
|
||||
|
||||
**Basic Usage**:
|
||||
|
||||
```go
|
||||
// Create a safe HTTP client with default options
|
||||
client := network.NewSafeHTTPClient()
|
||||
@@ -927,6 +980,7 @@ defer resp.Body.Close()
|
||||
```
|
||||
|
||||
**With Options**:
|
||||
|
||||
```go
|
||||
// Custom timeout (default: 10 seconds)
|
||||
client := network.NewSafeHTTPClient(
|
||||
@@ -1255,6 +1309,7 @@ func (s *NotificationService) SendWebhook(ctx context.Context, event SecurityEve
|
||||
Charon maintains extensive test coverage for all SSRF protection mechanisms:
|
||||
|
||||
**URL Validation Tests** (90.2% coverage):
|
||||
|
||||
- ✅ Private IP detection (IPv4/IPv6)
|
||||
- ✅ Cloud metadata endpoint blocking (169.254.169.254)
|
||||
- ✅ DNS resolution with timeout handling
|
||||
@@ -1263,6 +1318,7 @@ Charon maintains extensive test coverage for all SSRF protection mechanisms:
|
||||
- ✅ Multiple IP address validation (all must pass)
|
||||
|
||||
**Security Notification Tests**:
|
||||
|
||||
- ✅ Webhook URL validation on save
|
||||
- ✅ Webhook URL re-validation on send
|
||||
- ✅ HTTPS enforcement in production
|
||||
@@ -1270,12 +1326,14 @@ Charon maintains extensive test coverage for all SSRF protection mechanisms:
|
||||
- ✅ DNS rebinding protection
|
||||
|
||||
**Integration Tests**:
|
||||
|
||||
- ✅ End-to-end webhook delivery with SSRF checks
|
||||
- ✅ CrowdSec hub URL validation
|
||||
- ✅ URL connectivity testing with admin-only access
|
||||
- ✅ Performance benchmarks (< 10ms validation overhead)
|
||||
|
||||
**Test Pattern Example**:
|
||||
|
||||
```go
|
||||
func TestValidateExternalURL_CloudMetadataDetection(t *testing.T) {
|
||||
// Test blocking AWS metadata endpoint
|
||||
@@ -1325,6 +1383,7 @@ We're interested in:
|
||||
### How to Report
|
||||
|
||||
**Preferred Method**: GitHub Security Advisory
|
||||
|
||||
1. Go to <https://github.com/Wikid82/charon/security/advisories/new>
|
||||
2. Provide:
|
||||
- Steps to reproduce
|
||||
@@ -1334,6 +1393,7 @@ We're interested in:
|
||||
3. We'll respond within 48 hours
|
||||
|
||||
**Alternative Method**: Email
|
||||
|
||||
- Send to: `security@charon.example.com` (if configured)
|
||||
- Encrypt with PGP key (if available in SECURITY.md)
|
||||
- Include same information as GitHub advisory
|
||||
@@ -1341,11 +1401,13 @@ We're interested in:
|
||||
### Responsible Disclosure
|
||||
|
||||
**Please**:
|
||||
|
||||
- ✅ Give us time to fix before public disclosure (90 days)
|
||||
- ✅ Provide clear reproduction steps
|
||||
- ✅ Avoid destructive testing (don't attack real infrastructure)
|
||||
|
||||
**We'll**:
|
||||
|
||||
- ✅ Acknowledge your report within 48 hours
|
||||
- ✅ Provide regular status updates
|
||||
- ✅ Credit you in release notes (if desired)
|
||||
|
||||
@@ -11,10 +11,12 @@
|
||||
After implementing `--no-cache` builds, the supply chain scan still reports **8 Medium vulnerabilities**. Investigation reveals these are **actual runtime dependencies**, not false positives from cached layers.
|
||||
|
||||
**Vulnerability Breakdown**:
|
||||
|
||||
- **3 Alpine APK packages** (busybox, curl, ssl_client) - CVE-2025-60876, CVE-2025-10966 (no fixes available)
|
||||
- **2 Go dependencies** (golang.org/x/crypto v0.42.0) - GHSA-j5w8-q4qc-rx2x, GHSA-f6x5-jh6r-wrfv (fix available: v0.45.0)
|
||||
|
||||
**Current Status**:
|
||||
|
||||
- ✅ No-cache builds implemented successfully
|
||||
- ⚠️ Alpine base image vulnerabilities have no upstream patches yet
|
||||
- 🔧 golang.org/x/crypto requires dependency update
|
||||
@@ -26,6 +28,7 @@ After implementing `--no-cache` builds, the supply chain scan still reports **8
|
||||
### Actual Vulnerabilities Found (Not False Positives)
|
||||
|
||||
#### 1. Alpine Base Image - busybox (CVE-2025-60876)
|
||||
|
||||
**Affected Packages**: busybox, busybox-binsh, ssl_client
|
||||
**Current Version**: 1.37.0-r20
|
||||
**Fixed Version**: None available
|
||||
@@ -34,6 +37,7 @@ After implementing `--no-cache` builds, the supply chain scan still reports **8
|
||||
**Details**: CVE-2025-60876 affects busybox utilities in Alpine 3.21. No patch is available yet from Alpine upstream.
|
||||
|
||||
**Impact**:
|
||||
|
||||
- Affects base image utilities (not directly used by application)
|
||||
- Busybox provides minimal shell and utilities in Alpine
|
||||
- Low exploitability in containerized environment
|
||||
@@ -41,6 +45,7 @@ After implementing `--no-cache` builds, the supply chain scan still reports **8
|
||||
**Recommendation**: Monitor Alpine security advisories for patch release.
|
||||
|
||||
#### 2. Alpine Base Image - curl (CVE-2025-10966)
|
||||
|
||||
**Current Version**: 8.14.1-r2
|
||||
**Fixed Version**: None available
|
||||
**Severity**: Medium
|
||||
@@ -48,6 +53,7 @@ After implementing `--no-cache` builds, the supply chain scan still reports **8
|
||||
**Details**: CVE-2025-10966 affects libcurl in Alpine 3.21. No patch is available yet from Alpine upstream.
|
||||
|
||||
**Impact**:
|
||||
|
||||
- curl is used by healthcheck scripts
|
||||
- Medium severity with limited attack surface
|
||||
- Requires network access to exploit
|
||||
@@ -55,15 +61,18 @@ After implementing `--no-cache` builds, the supply chain scan still reports **8
|
||||
**Recommendation**: Monitor Alpine security advisories for patch release.
|
||||
|
||||
#### 3. Go Dependencies - golang.org/x/crypto (GHSA-j5w8-q4qc-rx2x, GHSA-f6x5-jh6r-wrfv)
|
||||
|
||||
**Current Version**: v0.42.0 (transitive dependency)
|
||||
**Fixed Version**: v0.45.0
|
||||
**Severity**: Medium
|
||||
|
||||
**Details**: Two GitHub Security Advisories affecting golang.org/x/crypto v0.42.0:
|
||||
|
||||
- GHSA-j5w8-q4qc-rx2x: SSH connection handling vulnerability
|
||||
- GHSA-f6x5-jh6r-wrfv: SSH key parsing vulnerability
|
||||
|
||||
**Dependency Chain**:
|
||||
|
||||
```
|
||||
github.com/go-playground/validator/v10@v10.28.0
|
||||
└─> golang.org/x/crypto@v0.42.0 (VULNERABLE)
|
||||
@@ -72,6 +81,7 @@ Direct dependency: golang.org/x/crypto@v0.46.0 (SAFE)
|
||||
```
|
||||
|
||||
**Impact**:
|
||||
|
||||
- Transitive dependency from go-playground/validator
|
||||
- validator library used for input validation in API handlers
|
||||
- Medium severity - requires specific conditions to exploit
|
||||
@@ -124,6 +134,7 @@ require (
|
||||
**Expected Impact**: Eliminates 2-4 of the 8 Medium vulnerabilities (the golang.org/x/crypto issues).
|
||||
|
||||
**Testing Required**:
|
||||
|
||||
- ✅ Backend unit tests
|
||||
- ✅ Integration tests
|
||||
- ✅ Validate validator/v10 compatibility
|
||||
@@ -144,25 +155,31 @@ Since Alpine has not released patches for CVE-2025-60876 and CVE-2025-10966:
|
||||
#### 3. Monitor Alpine Security Advisories
|
||||
|
||||
**Action Plan**:
|
||||
|
||||
1. Subscribe to Alpine Linux security mailing list
|
||||
2. Check https://security.alpinelinux.org/vuln daily
|
||||
2. Check <https://security.alpinelinux.org/vuln> daily
|
||||
3. When patches are released:
|
||||
|
||||
```bash
|
||||
# Update Dockerfile base image
|
||||
FROM caddy:2-alpine # This will pull the latest Alpine patch
|
||||
```
|
||||
|
||||
4. Rebuild and re-scan to verify resolution
|
||||
|
||||
#### 4. Monitor go-playground/validator Updates
|
||||
|
||||
**Action Plan**:
|
||||
1. Check https://github.com/go-playground/validator/releases weekly
|
||||
|
||||
1. Check <https://github.com/go-playground/validator/releases> weekly
|
||||
2. When validator releases version with golang.org/x/crypto@v0.45.0+:
|
||||
|
||||
```bash
|
||||
cd backend
|
||||
go get -u github.com/go-playground/validator/v10@latest
|
||||
go mod tidy
|
||||
```
|
||||
|
||||
3. Remove the replace directive from go.mod
|
||||
4. Re-run tests and supply chain scan
|
||||
|
||||
@@ -173,11 +190,13 @@ Since Alpine has not released patches for CVE-2025-60876 and CVE-2025-10966:
|
||||
#### 5. Implement Automated Dependency Updates
|
||||
|
||||
**Tools to Consider**:
|
||||
|
||||
- Renovate Bot (already configured) - increase update frequency
|
||||
- Dependabot for Go modules
|
||||
- Automated security patch PRs
|
||||
|
||||
**Configuration**:
|
||||
|
||||
```json
|
||||
// .github/renovate.json
|
||||
{
|
||||
@@ -195,11 +214,13 @@ Since Alpine has not released patches for CVE-2025-60876 and CVE-2025-10966:
|
||||
#### 6. Alternative Base Images
|
||||
|
||||
**Research Options**:
|
||||
|
||||
1. **Distroless** (Google) - Minimal attack surface, no shell
|
||||
2. **Alpine with chainguard** - Hardened Alpine with faster security patches
|
||||
3. **Wolfi** (Chainguard) - Modern, security-first distribution
|
||||
|
||||
**Evaluation Criteria**:
|
||||
|
||||
- Security patch velocity
|
||||
- Compatibility with Caddy
|
||||
- Image size impact
|
||||
@@ -285,11 +306,13 @@ docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
|
||||
### Expected Results
|
||||
|
||||
**Before Replace Directive**:
|
||||
|
||||
```
|
||||
Medium: 8 (busybox x3, curl x1, golang.org/x/crypto x4)
|
||||
```
|
||||
|
||||
**After Replace Directive**:
|
||||
|
||||
```
|
||||
Medium: 4 (busybox x3, curl x1)
|
||||
```
|
||||
@@ -349,6 +372,7 @@ go test ./...
|
||||
Implementing `--no-cache` builds across all workflows eliminates false positive vulnerability reports from cached Go module layers. This provides accurate security posture reporting, clean SBOMs, and compliance-ready artifacts. The trade-off of slightly longer build times is acceptable for the security benefits gained.
|
||||
|
||||
**Next Steps**:
|
||||
|
||||
1. ✅ Changes committed to `docker-build.yml` and `waf-integration.yml`
|
||||
2. ⏳ Wait for next PR build to validate clean scan results
|
||||
3. ⏳ Monitor build time impact and adjust if needed
|
||||
@@ -384,12 +408,14 @@ Implementing `--no-cache` builds across all workflows eliminates false positive
|
||||
### Risk Assessment
|
||||
|
||||
**Alpine CVEs (3 unique vulnerabilities in 4 packages)**:
|
||||
|
||||
- **Exploitability**: Low (requires local access or specific network conditions)
|
||||
- **Impact**: Limited (utilities not directly exposed to user input)
|
||||
- **Mitigation**: Containerization limits attack surface
|
||||
- **Status**: **ACCEPTED RISK** - Monitor for upstream patches
|
||||
|
||||
**golang.org/x/crypto (2 unique vulnerabilities, 4 entries due to scan reporting)**:
|
||||
|
||||
- **Exploitability**: Medium (requires SSH connection handling)
|
||||
- **Impact**: Medium (transitive dependency from validator)
|
||||
- **Mitigation**: Add replace directive to force v0.45.0
|
||||
|
||||
Reference in New Issue
Block a user