Files
Charon/CODEQL_EMAIL_INJECTION_REMEDIATION_COMPLETE.md

5.6 KiB
Raw Blame History

CodeQL go/email-injection Remediation - Complete

Date: 2026-01-10 Status: RESOLVED

Summary

Successfully remediated the CodeQL go/email-injection finding by implementing proper email header separation according to security best practices outlined in the specification.

Changes Implemented

1. Helper Functions Added to backend/internal/services/mail_service.go

encodeSubject(subject string) (string, error)

  • Trims whitespace from subject lines
  • Rejects any CR/LF characters to prevent header injection
  • Uses MIME Q-encoding (RFC 2047) for UTF-8 subject lines
  • Returns encoded subject suitable for email headers

toHeaderUndisclosedRecipients() string

  • Returns constant "undisclosed-recipients:;" for RFC 5322 To: header
  • Prevents request-derived email addresses from appearing in message headers
  • Eliminates the CodeQL-detected taint flow from user input to SMTP message

2. Modified buildEmail() Function

Key Security Changes:

  • Changed To: header to use toHeaderUndisclosedRecipients() instead of request-derived recipient address
  • Recipient validation still performed for SMTP envelope (RCPT TO command)
  • Subject encoding enforced through encodeSubject() helper
  • Updated security documentation comments

Critical Implementation Detail:

  • SMTP envelope recipients (toEnvelope in smtp.SendMail) remain correct for delivery
  • Only RFC 5322 message headers changed
  • Separation of envelope routing from message headers eliminates injection risk

3. Enhanced Test Coverage

New Tests in backend/internal/services/mail_service_test.go:

  1. TestMailService_BuildEmail_UndisclosedRecipients

    • Verifies To: header contains undisclosed-recipients:;
    • Asserts recipient email does NOT appear in message headers
    • Prevents regression of CodeQL finding
  2. TestMailService_SendInvite_HTMLTemplateEscaping

    • Tests HTML template auto-escaping for special characters in appName
    • Verifies XSS protection in invite emails

Updated Tests in backend/internal/api/handlers/user_handler_test.go:

  1. TestUserHandler_PreviewInviteURL_Success_Unconfigured

    • Updated to verify base_url and preview_url are empty when app.public_url not configured
    • Prevents fallback to request headers
  2. TestUserHandler_PreviewInviteURL_Unconfigured_DoesNotUseRequestHost (NEW)

    • Explicitly tests malicious Host header injection scenario
    • Asserts response does NOT contain attacker-controlled hostname
    • Verifies protection against host header poisoning attacks

Verification Results

Test Results

cd /projects/Charon/backend/internal/services
go test -v -run "TestMail" .

Result: All mail service tests PASS

  • Total mail service tests: 28 tests
  • New security tests: 2 added
  • Updated tests: 1 modified
  • Coverage: 81.1% of statements (services package)

CodeQL Scan Results

codeql database analyze codeql-db-go \
  --format=sarif-latest \
  --output=codeql-results-go.sarif

Result:

  • Total findings: 0
  • go/email-injection findings: 0 (RESOLVED)
  • Previous finding location: backend/internal/services/mail_service.go:285
  • Status: No longer detected

Security Impact

Before Remediation

  • Request-derived email addresses flowed into RFC 5322 message headers
  • CodeQL identified potential for content spoofing (CWE-640)
  • Malicious recipient addresses could theoretically manipulate headers
  • Risk: Low (existing CRLF rejection mitigated most attacks, but CodeQL flagged it)

After Remediation

  • Zero request-derived data in message headers
  • To: header uses RFC-compliant constant: undisclosed-recipients:;
  • SMTP envelope routing unchanged (still uses validated recipient)
  • Subject lines properly MIME-encoded
  • Multiple layers of defense:
    1. CRLF rejection (existing)
    2. MIME encoding (new)
    3. Header isolation (new)
    4. Dot-stuffing (existing)

Additional Protections

  • Host header injection prevented in invite URL generation
  • HTML template auto-escaping verified
  • Comprehensive test coverage for injection scenarios

Files Modified

  1. backend/internal/services/mail_service.go

    • Added: encodeSubject(), toHeaderUndisclosedRecipients()
    • Modified: SendEmail(), buildEmail()
    • Lines changed: ~30
  2. backend/internal/services/mail_service_test.go

    • Added: 2 new security-focused tests
    • Modified: 1 existing test
    • Lines changed: ~50
  3. backend/internal/api/handlers/user_handler_test.go

    • Added: 1 new host header injection test
    • Modified: 1 existing test
    • Lines changed: ~20

Compliance

  • OWASP Top 10 2021: A03:2021 Injection
  • CWE-93: Improper Neutralization of CRLF Sequences in HTTP Headers
  • CWE-640: Weak Password Recovery Mechanism for Forgotten Password
  • RFC 5321: SMTP (envelope vs. message header separation)
  • RFC 5322: Internet Message Format
  • RFC 2047: MIME Message Header Extensions

References

  • Specification: docs/plans/current_spec.md
  • CodeQL Query: go/email-injection
  • Original SARIF: codeql-results-go.sarif (prior to remediation)
  • Security Instructions: .github/instructions/security-and-owasp.instructions.md

Conclusion

The CodeQL go/email-injection vulnerability has been completely resolved through proper separation of SMTP envelope routing from RFC 5322 message headers. The implementation follows security best practices, maintains backward compatibility with SMTP delivery, and includes comprehensive test coverage to prevent regression.

No suppressions were used - the vulnerability was remediated at the source by eliminating the tainted data flow.