Adds IncludeAllDeployments option to show all deployments, not just problem ones (where replicas don't match desired). This provides parity with the existing --kube-include-all-pods flag. - Add IncludeAllDeployments to kubernetesagent.Config - Add --kube-include-all-deployments flag and PULSE_KUBE_INCLUDE_ALL_DEPLOYMENTS env var - Update collectDeployments to respect the new flag - Add test for IncludeAllDeployments functionality - Update UNIFIED_AGENT.md documentation Addresses feedback from PR #855
375 lines
15 KiB
Markdown
375 lines
15 KiB
Markdown
# Security Audit Report - Pulse Application
|
||
## Date: 2025-12-18
|
||
## Auditor: Claude (Gemini)
|
||
|
||
---
|
||
|
||
## Executive Summary
|
||
|
||
This document presents the findings from a comprehensive security audit of the Pulse monitoring application. The audit examined authentication, authorization, cryptography, input validation, SSRF prevention, command execution, and general security practices.
|
||
|
||
### Overall Assessment
|
||
|
||
**Security Posture: A- (Excellent with minor recommendations)**
|
||
|
||
The codebase demonstrates a mature security posture with:
|
||
- ✅ Strong cryptographic practices (bcrypt, SHA3-256, AES-256-GCM)
|
||
- ✅ Comprehensive SSRF protection for webhooks
|
||
- ✅ CSRF protection for session-based authentication
|
||
- ✅ Rate limiting and account lockout
|
||
- ✅ Command execution policy with blocklist/allowlist
|
||
- ✅ Proper input sanitization and validation
|
||
- ✅ Security headers implementation
|
||
- ✅ Audit logging
|
||
|
||
A prior security audit on 2025-11-07 addressed 9 critical to low severity issues in the sensor-proxy component, all of which were successfully remediated.
|
||
|
||
---
|
||
|
||
## Audit Scope
|
||
|
||
### Components Reviewed
|
||
1. **Authentication System** (`internal/api/auth.go`, `internal/auth/`)
|
||
2. **Session Management** (`internal/api/security.go`, session stores)
|
||
3. **Cryptography** (`internal/crypto/crypto.go`)
|
||
4. **API Token Management** (`internal/api/security_tokens.go`)
|
||
5. **OIDC Integration** (`internal/api/security_oidc.go`)
|
||
6. **Webhook/Notification Security** (`internal/notifications/`)
|
||
7. **Command Execution** (`internal/agentexec/policy.go`)
|
||
8. **Database Operations** (`internal/metrics/store.go`)
|
||
9. **Configuration & Secrets** (`internal/config/`)
|
||
|
||
---
|
||
|
||
## Strengths Identified
|
||
|
||
### 1. Authentication & Password Security ✅
|
||
- **bcrypt hashing** with cost factor 12 for passwords
|
||
- **SHA3-256** for API token hashing
|
||
- **Constant-time comparison** for token validation (prevents timing attacks)
|
||
- **12-character minimum** password length requirement
|
||
- **Automatic hashing** of plain-text passwords on startup
|
||
|
||
### 2. Session Security ✅
|
||
- **HttpOnly cookies** for session tokens
|
||
- **Secure flag** set based on HTTPS detection
|
||
- **SameSite policy** properly configured (Lax/None based on proxy detection)
|
||
- **24-hour session expiry** with sliding window extension
|
||
- **Session invalidation** on password change
|
||
|
||
### 3. Rate Limiting & Account Lockout ✅
|
||
- **10 attempts/minute** for auth endpoints
|
||
- **5 failed attempts** triggers 15-minute lockout
|
||
- **Per-username AND per-IP** tracking
|
||
- **Lockout bypass prevention** (both must be clear)
|
||
|
||
### 4. CSRF Protection ✅
|
||
- **CSRF tokens** generated per session
|
||
- **Separate CSRF cookie** (not HttpOnly, readable by JS)
|
||
- **Header/form validation** for state-changing requests
|
||
- **Safe methods** (GET, HEAD, OPTIONS) exempted
|
||
- **API token auth** correctly bypasses CSRF (not vulnerable)
|
||
|
||
### 5. SSRF Prevention ✅
|
||
- **Webhook URL validation** with DNS resolution check
|
||
- **Private IP blocking** (RFC1918, link-local, loopback)
|
||
- **Cloud metadata endpoint blocking** (169.254.169.254, etc.)
|
||
- **Configurable allowlist** for internal webhooks
|
||
- **DNS rebinding protection** via IP resolution verification
|
||
|
||
### 6. Encryption at Rest ✅
|
||
- **AES-256-GCM** for credential encryption
|
||
- **Unique nonce** generation per encryption operation
|
||
- **Key file protections** with existence validation before encryption
|
||
- **Orphaned data prevention** (refuses to encrypt if key deleted)
|
||
|
||
### 7. Security Headers ✅
|
||
- Content-Security-Policy
|
||
- X-Frame-Options (DENY by default)
|
||
- X-Content-Type-Options: nosniff
|
||
- X-XSS-Protection
|
||
- Referrer-Policy
|
||
- Permissions-Policy
|
||
|
||
### 8. Command Execution Policy ✅
|
||
- **Blocklist** for dangerous commands (rm -rf, mkfs, dd, etc.)
|
||
- **Auto-approve list** for read-only inspection commands
|
||
- **Require approval** for service control, package management
|
||
- **Sudo normalization** for consistent policy application
|
||
|
||
### 9. SQL Injection Prevention ✅
|
||
- **Parameterized queries** used throughout metrics store
|
||
- **Prepared statements** for batch operations
|
||
- No string concatenation in SQL queries
|
||
|
||
### 10. XSS Prevention ✅
|
||
- **DOMPurify** for markdown rendering
|
||
- **HTML entity encoding** in tooltips
|
||
- **Allowed tag/attribute lists** for sanitized content
|
||
- **LLM output sanitization** (AI chat)
|
||
|
||
---
|
||
|
||
## Findings & Recommendations
|
||
|
||
### HIGH SEVERITY: None Identified
|
||
|
||
### MEDIUM SEVERITY
|
||
|
||
#### M1. Admin Bypass Debug Mode 🟡
|
||
**Location:** `internal/api/auth.go:675-691`
|
||
|
||
**Finding:**
|
||
The `adminBypassEnabled()` function allows bypassing authentication when both `ALLOW_ADMIN_BYPASS=1` and `PULSE_DEV=true` are set. While properly gated for development only:
|
||
|
||
```go
|
||
if os.Getenv("ALLOW_ADMIN_BYPASS") != "1" {
|
||
return
|
||
}
|
||
if os.Getenv("PULSE_DEV") == "true" || strings.EqualFold(os.Getenv("NODE_ENV"), "development") {
|
||
log.Warn().Msg("Admin authentication bypass ENABLED (development mode)")
|
||
adminBypassState.enabled = true
|
||
}
|
||
```
|
||
|
||
**Risk:** Accidental production deployment with these env vars could expose full admin access.
|
||
|
||
**Recommendation:**
|
||
1. Add prominent warning log at startup if either var is set
|
||
2. Consider disallowing in Docker `PULSE_DOCKER=true` mode
|
||
3. Document this explicitly as a development-only feature
|
||
|
||
---
|
||
|
||
#### M2. Recovery Token Exposure Window 🟡
|
||
**Location:** Session and recovery token stores
|
||
|
||
**Finding:**
|
||
Recovery tokens for password reset appear to be stored in JSON files. While tokens are hashed:
|
||
- File permissions should be verified as 0600
|
||
- Token expiration should be enforced server-side (appears to be implemented)
|
||
|
||
**Recommendation:**
|
||
1. Verify file permissions are set correctly (0600) during token store initialization
|
||
2. Add cleanup routine for expired tokens
|
||
|
||
---
|
||
|
||
### LOW SEVERITY
|
||
|
||
#### L1. Cookie Security in HTTP Proxies 🔵
|
||
**Location:** `internal/api/auth.go:75-107`
|
||
|
||
**Finding:**
|
||
When behind an HTTP (non-HTTPS) proxy, cookies fall back to `SameSite=Lax` with `Secure=false`. This is functionally necessary but reduces security.
|
||
|
||
**Recommendation:**
|
||
1. Log a warning when cookies are set without Secure flag
|
||
2. Add documentation recommending HTTPS termination at proxy
|
||
|
||
---
|
||
|
||
#### L2. Session Token Entropy 🔵
|
||
**Location:** `internal/api/auth.go:109-118`
|
||
|
||
**Finding:**
|
||
Session tokens are 32 bytes (256 bits) of entropy via `crypto/rand`, which is excellent. However, the error handling falls back to empty string:
|
||
|
||
```go
|
||
if _, err := cryptorand.Read(b); err != nil {
|
||
log.Error().Err(err).Msg("Failed to generate secure session token")
|
||
return "" // Fallback - should never happen
|
||
}
|
||
```
|
||
|
||
**Recommendation:**
|
||
Consider returning an error or panicking rather than returning empty string, as an empty session token could have undefined behavior.
|
||
|
||
---
|
||
|
||
#### L3. OIDC State Parameter Validation 🔵
|
||
**Location:** `internal/api/security_oidc.go`
|
||
|
||
**Finding:**
|
||
OIDC configuration is properly validated and state parameters should be verified during the OAuth flow. This should be confirmed in the callback handler.
|
||
|
||
**Recommendation:**
|
||
1. Verify state parameter is generated with sufficient entropy
|
||
2. Ensure state parameter has short expiration (5-10 minutes)
|
||
|
||
---
|
||
|
||
#### L4. Apprise CLI Command Execution 🔵
|
||
**Location:** `internal/notifications/notifications.go`
|
||
|
||
**Finding:**
|
||
The Apprise CLI path and targets are passed to `exec.CommandContext`. While the CLI path is configurable:
|
||
|
||
```go
|
||
args := []string{"-t", title, "-b", body}
|
||
args = append(args, cfg.Targets...)
|
||
execFn := n.appriseExec
|
||
```
|
||
|
||
**Risk:** If an attacker can control `cfg.Targets`, they might inject malicious arguments.
|
||
|
||
**Recommendation:**
|
||
1. Validate that targets match expected Apprise URL format
|
||
2. Consider sanitizing or escaping special characters in targets
|
||
|
||
---
|
||
|
||
### INFORMATIONAL
|
||
|
||
#### I1. Dependencies ℹ️
|
||
The `go.mod` shows modern, well-maintained dependencies:
|
||
- Go 1.24.0 (latest stable)
|
||
- `golang.org/x/crypto v0.45.0` (current)
|
||
- `github.com/coreos/go-oidc/v3 v3.17.0` (current)
|
||
|
||
**Recommendation:**
|
||
Run `govulncheck` periodically to scan for known vulnerabilities.
|
||
|
||
---
|
||
|
||
#### I2. GitGuardian Integration ℹ️
|
||
The `.gitguardian.yaml` is properly configured to:
|
||
- Ignore documentation and example files
|
||
- Block placeholder patterns
|
||
- Scan actual code and configuration
|
||
|
||
---
|
||
|
||
#### I3. Existing Security Audit ℹ️
|
||
The previous audit (2025-11-07) addressed critical vulnerabilities in the sensor-proxy:
|
||
- Socket directory tampering (CRITICAL) ✅ Fixed
|
||
- SSRF via get_temperature (CRITICAL) ✅ Fixed
|
||
- Connection exhaustion DoS (CRITICAL) ✅ Fixed
|
||
- Multi-UID rate limit bypass (CRITICAL) ✅ Fixed
|
||
- Incomplete GID authorization (MEDIUM) ✅ Fixed
|
||
- Unbounded SSH output (MEDIUM) ✅ Fixed
|
||
- Weak host key validation (MEDIUM) ✅ Fixed
|
||
- Insufficient capability separation (MEDIUM) ✅ Fixed
|
||
- Missing systemd hardening (LOW) ✅ Fixed
|
||
|
||
---
|
||
|
||
## Security Architecture Summary
|
||
|
||
### Data Flow Security
|
||
```
|
||
┌─────────────────────────────────────────────────────────────────┐
|
||
│ Client (Browser/API) │
|
||
│ ┌─────────────────────────────────────────────────────────────┐│
|
||
│ │ HTTPS + TLS │ Session Cookie (HttpOnly, Secure, SameSite) ││
|
||
│ │ │ CSRF Token (Cookie + Header validation) ││
|
||
│ │ │ API Token (Header: X-API-Token) ││
|
||
│ └─────────────────────────────────────────────────────────────┘│
|
||
└─────────────────────────────────────────────────────────────────┘
|
||
│
|
||
▼
|
||
┌─────────────────────────────────────────────────────────────────┐
|
||
│ Pulse Server │
|
||
│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │
|
||
│ │ Rate Limiter │ │ Auth Middleware │ │ CSRF Handler │ │
|
||
│ │ 10 auth/min │ │ Session/Token │ │ State-changing │ │
|
||
│ │ 500 api/min │ │ Validation │ │ operations │ │
|
||
│ └─────────────────┘ └─────────────────┘ └─────────────────┘ │
|
||
│ │
|
||
│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │
|
||
│ │ Account Lockout │ │ Command Policy │ │ SSRF Prevention │ │
|
||
│ │ 5 attempts/15m │ │ Block/Allow/ │ │ Private IP │ │
|
||
│ │ │ │ Require Approval│ │ blocklist │ │
|
||
│ └─────────────────┘ └─────────────────┘ └─────────────────┘ │
|
||
│ │
|
||
│ ┌─────────────────────────────────────────────────────────────┐│
|
||
│ │ Encryption at Rest (AES-256-GCM) ││
|
||
│ │ - Node credentials: /etc/pulse/nodes.enc ││
|
||
│ │ - Email settings: /etc/pulse/email.enc ││
|
||
│ │ - Webhooks: /etc/pulse/webhooks.enc ││
|
||
│ │ - OIDC config: /etc/pulse/oidc.enc ││
|
||
│ └─────────────────────────────────────────────────────────────┘│
|
||
└─────────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
### Password/Token Hashing
|
||
| Credential Type | Algorithm | Parameters |
|
||
|-----------------|-----------|------------|
|
||
| User Passwords | bcrypt | Cost factor 12 |
|
||
| API Tokens | SHA3-256 | - |
|
||
| Encryption Key | AES-256-GCM | 32-byte random key |
|
||
| Session Tokens | Random | 32 bytes (256-bit) |
|
||
|
||
---
|
||
|
||
## Compliance Checklist
|
||
|
||
| Requirement | Status | Notes |
|
||
|-------------|--------|-------|
|
||
| Password hashing | ✅ | bcrypt, cost 12 |
|
||
| Session management | ✅ | Secure cookies, 24h expiry |
|
||
| CSRF protection | ✅ | Token-based |
|
||
| Rate limiting | ✅ | Auth + API endpoints |
|
||
| Encryption at rest | ✅ | AES-256-GCM |
|
||
| HTTPS support | ✅ | TLS configurable |
|
||
| Security headers | ✅ | CSP, X-Frame-Options, etc. |
|
||
| Audit logging | ✅ | Auth events logged |
|
||
| Input validation | ✅ | SQL params, webhook URLs |
|
||
| Command execution control | ✅ | Policy-based |
|
||
|
||
---
|
||
|
||
## Recommendations Summary
|
||
|
||
### Priority 1 (Consider Addressing)
|
||
- [ ] M1: Add additional safeguards for dev mode bypass
|
||
- [ ] M2: Verify recovery token file permissions
|
||
|
||
### Priority 2 (Optional Improvements)
|
||
- [ ] L1: Add warning logs for non-secure cookies
|
||
- [ ] L2: Improve session token generation error handling
|
||
- [ ] L3: Document OIDC state parameter security
|
||
- [ ] L4: Add Apprise target validation
|
||
|
||
### Priority 3 (Ongoing)
|
||
- [ ] I1: Run `govulncheck` regularly
|
||
- [ ] Keep dependencies updated
|
||
- [ ] Review GitGuardian alerts
|
||
|
||
---
|
||
|
||
## Conclusion
|
||
|
||
The Pulse application demonstrates a **strong security posture** with comprehensive protections against common web application vulnerabilities. The codebase shows evidence of security-conscious development practices:
|
||
|
||
1. **Defense in depth** with multiple layers of authentication and authorization
|
||
2. **Secure defaults** requiring explicit configuration to reduce security
|
||
3. **Modern cryptography** using industry-standard algorithms
|
||
4. **Comprehensive validation** of user inputs and external URLs
|
||
5. **Audit trails** for security-relevant events
|
||
|
||
The identified findings are primarily of low to medium severity and represent opportunities for hardening rather than critical vulnerabilities.
|
||
|
||
**Final Security Grade: A-**
|
||
|
||
---
|
||
|
||
## References
|
||
|
||
- **Previous Audit:** `docs/SECURITY_AUDIT_2025-11-07.md`
|
||
- **Security Policy:** `SECURITY.md`
|
||
- **Security Changelog:** `docs/SECURITY_CHANGELOG.md`
|
||
|
||
---
|
||
|
||
## Audit Team
|
||
|
||
**Auditor:** Claude (Gemini 2.5)
|
||
**Methodology:** Static code analysis and architecture review
|
||
**Audit Duration:** 2025-12-18 (single session)
|
||
**Files Reviewed:** ~50 source files across 10 packages
|
||
|
||
---
|
||
|
||
**For security concerns or questions:**
|
||
https://github.com/rcourtman/Pulse/issues
|