Commit Graph

9 Commits

Author SHA1 Message Date
fuomag9
b480c2cf5d chore: remove finding-ID prefixes from code comments
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 12:51:39 +01:00
fuomag9
debd0d98fc security: fix 17 vulnerabilities from comprehensive pentest
Fixes identified from full security audit covering auth, crypto,
injection, infrastructure, and configuration security.

Critical:
- C1: Fail-closed on unrecognized NODE_ENV (prevent DEV_SECRET in staging)
- C3: Validate API token expires_at (reject invalid dates that bypass expiry)

High:
- H1: Refresh JWT role from DB on each session (reflect demotions immediately)
- H2: Docker socket proxy for l4-port-manager (restrict API surface)
- H5: Block dangerous WAF custom directives (SecRuleEngine, SecAuditEngine)
- H7: Require explicit NEXTAUTH_TRUST_HOST instead of always trusting Host
- H8: Semantic validation of sync payload (block metadata SSRF, size limits)

Medium:
- M3: Rate limit password change current-password verification
- M5: Parameterized SQL in log/waf parsers (replace template literals)
- M6: Nonce-based CSP replacing unsafe-inline for script-src
- M9: Strip Caddy placeholders from rewrite path_prefix
- M10: Sanitize authentik outpostDomain (path traversal, placeholders)
- M14: Deny access on missing JWT role instead of defaulting to "user"

Low:
- L1: Require Origin header on mutating session-authenticated requests
- L4: Enforce password complexity on user password changes
- L5: Time-limited legacy SHA-256 key fallback (grace period until 2026-06-01)
- L6: Escape LIKE metacharacters in audit log search
- L7: Runtime-validate WAF excluded_rule_ids as positive integers

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 12:14:44 +01:00
fuomag9
3572b482e8 added tests 2026-03-07 02:02:14 +01:00
fuomag9
e06b41b604 fix WAF detection mode and payload logging
- DetectionOnly mode: add SecAction to set anomaly score thresholds to
  9999999 so rule 949110/980130 never fires; works around coraza-caddy
  bug where is_interrupted=true still causes a 403 in detection mode
- Switch SecAuditEngine back to On (from RelevantOnly) so DetectionOnly
  hits are captured, now safe because body parts are excluded
- SecAuditLogParts: ABIJDEFHZ → ABFHZ, dropping request body (I),
  multipart files (J), intermediate response headers (D), and response
  body (E) — prevents multi-MB payloads being written to audit log
- Parser: store both blocked and detected events; filter on rule matched
  OR is_interrupted instead of is_interrupted only
- Add blocked column to waf_events (migration 0014); existing rows
  default to blocked=true
- WAF Events UI: Blocked/Detected chip in table and drawer header
- Fix misleading help text that said to use Detection Only to observe
  traffic before blocking

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-06 15:32:56 +01:00
fuomag9
54a2a9ea0d feat: parse WAF rule logs for rule ID/message/severity
Coraza does not write matched rules to the audit log (known upstream
bug). Rule details are logged by Caddy's http.handlers.waf logger.

Two changes:

1. caddy.ts: Always configure a dedicated Caddy log sink that writes
   http.handlers.waf logger output to /logs/waf-rules.log as JSON.

2. waf-log-parser.ts: Before parsing the audit log, read the new
   waf-rules.log to build a Map<unique_id, RuleInfo>. Each audit log
   entry joins against this map via transaction.id to populate
   ruleId, ruleMessage, and severity fields. Skips anomaly evaluation
   rules (949110/980130) to show the actual detection rule instead.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-04 08:21:49 +01:00
fuomag9
5e7ceedfe3 fix: filter WAF events by is_interrupted instead of messages array
Coraza does not populate the messages array in the audit log JSON
(known bug — matched rules appear in Caddy's error log but not in
the audit log's messages field). The transaction.is_interrupted flag
IS correctly set to true for blocked/detected requests.

Changes:
- Filter on tx.is_interrupted instead of entry.messages.length
- Check both top-level and tx.messages for rule info (future compat)
- Fall back to tx.highest_severity when messages missing
- Document the Coraza messages bug in interface comments

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-04 08:16:02 +01:00
fuomag9
a2c6991abd fix: only log WAF events where rules matched
- Change SecAuditEngine from On to RelevantOnly so Coraza only writes
  audit log entries for transactions that triggered at least one rule.
  Previously all requests were logged regardless of matches.
- Add parser-side guard to skip entries with empty messages array as
  belt-and-suspenders against any pre-existing clean entries in log.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-04 02:25:21 +01:00
fuomag9
d7e20b10b5 fix WAF: use directives array and Include for OWASP CRS, fix log parser field paths
- buildWafHandler: directives must be string[] not a joined string (coraza-caddy
  JSON API requirement); load_owasp_crs is Caddyfile-only and silently ignored in
  JSON config — replaced with Include @owasp_crs/... directives
- waf-log-parser: use unix_timestamp (nanoseconds) for precise ts; host header is
  headers.host[] (lowercase array); messages[].data.{id,msg,severity} not rule.*

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-04 01:49:22 +01:00
fuomag9
0dad675c6d feat: integrate Coraza WAF with full UI and event logging
- Add coraza-caddy/v2 to Caddy Docker build
- Add waf_events + waf_log_parse_state DB tables (migration 0010)
- Add WafSettings type and get/save functions to settings
- Add WafHostConfig/WafMode types to proxy-hosts model
- Add resolveEffectiveWaf + buildWafHandler to caddy config generation
- Create waf-log-parser.ts: parse Coraza JSON audit log → waf_events
- Add WafFields.tsx per-host WAF UI (accordion, mode, CRS, directives)
- Add global WAF settings card to SettingsClient
- Add WAF Events dashboard page with search, pagination, severity chips
- Add WAF Events nav link to sidebar

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-03 22:16:34 +01:00