Skip to content

Add HTTP Security Headers#49

Merged
munishchouhan merged 1 commit intomasterfrom
add-security-headers
Mar 2, 2026
Merged

Add HTTP Security Headers#49
munishchouhan merged 1 commit intomasterfrom
add-security-headers

Conversation

@munishchouhan
Copy link
Member

@munishchouhan munishchouhan commented Feb 16, 2026

Summary

This PR implements comprehensive HTTP security headers middleware to protect against common browser-based attacks including SSL stripping, clickjacking, XSS, MIME-sniffing, and unauthorized feature access.

Problem Statement

The application was identified as vulnerable to multiple security risks due to missing HTTP response headers:

Vulnerability: Server Security Misconfiguration - Lack of Security Headers
OWASP Severity: Low
CVSS v3.1 Score: Low (3.7)

Missing Headers

  • Strict-Transport-Security (HSTS): Allowed downgrade attacks forcing users onto HTTP and potential SSL stripping
  • Content-Security-Policy (CSP): Left application open to XSS and data injection attacks
  • X-Frame-Options: Enabled clickjacking attacks via iframe embedding
  • X-Content-Type-Options: Allowed MIME-sniffing leading to content-type confusion
  • Referrer-Policy: Exposed sensitive URL parameters to third parties via Referer header
  • Permissions-Policy: Failed to restrict browser features (camera, microphone, geolocation)

Affected Resources

  • https://wave.stage-seqera.io/v1alpha1/* - Missing HSTS header
  • https://community.wave.stage-seqera.io/ - Missing all security headers

Solution

Implemented a global Gin middleware (securityHeadersMiddleware) that adds six critical security headers to all HTTP responses.

Security Headers Implemented

1. Strict-Transport-Security (HSTS)

Strict-Transport-Security: max-age=31536000; includeSubDomains
  • Forces HTTPS connections for 1 year (31,536,000 seconds)
  • Applies to all subdomains
  • Prevents SSL stripping attacks

2. X-Frame-Options

X-Frame-Options: DENY
  • Prevents page from being displayed in any frame/iframe
  • Blocks clickjacking attacks completely

3. X-Content-Type-Options

X-Content-Type-Options: nosniff
  • Prevents MIME-type sniffing
  • Forces browsers to respect declared content-type

4. Content-Security-Policy (CSP)

Content-Security-Policy: default-src 'self'; style-src 'self' 'unsafe-inline';
  script-src 'self'; img-src 'self' data: https:; font-src 'self';
  object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'none';

Directives:

  • default-src 'self': Only allow resources from same origin
  • style-src 'self' 'unsafe-inline': Allow inline styles (needed for Tailwind CSS)
  • script-src 'self': Only allow scripts from same origin
  • img-src 'self' data: https:: Allow images from same origin, data URIs, and HTTPS
  • font-src 'self': Only allow fonts from same origin
  • object-src 'none': Block plugins (Flash, etc.)
  • base-uri 'self': Prevent base tag injection
  • form-action 'self': Only allow form submissions to same origin
  • frame-ancestors 'none': Enhanced clickjacking protection

5. Referrer-Policy

Referrer-Policy: strict-origin-when-cross-origin
  • Sends full URL for same-origin requests
  • Sends only origin for cross-origin HTTPS requests
  • Sends nothing when downgrading from HTTPS to HTTP

6. Permissions-Policy

Permissions-Policy: camera=(), microphone=(), geolocation=(), interest-cohort=()
  • Denies access to camera
  • Denies access to microphone
  • Denies access to geolocation
  • Disables FLoC/interest-cohort tracking

Changes

Modified Files

pkg/server/server.go

  • Added securityHeadersMiddleware() function (lines 185-221)
  • Registered middleware globally in New() function (line 88)
  • Middleware applied to all routes before request routing

New Files

pkg/server/security_headers_test.go (260 lines)

  • Comprehensive test suite with 5 test cases
  • Tests all 6 security headers
  • Validates middleware behavior across multiple endpoints
  • Verifies compatibility with other middleware

Implementation Details

Middleware Placement

r.Use(sloggin.NewWithConfig(log, lmConfig))
r.Use(gin.Recovery())
r.Use(securityHeadersMiddleware())  // ← Added here (early in chain)

Rationale:

  • Placed after logging and recovery middleware
  • Applied before routing to ensure all responses include headers
  • Runs for all endpoints (API, HTML, static assets)

Test Coverage

TestSecurityHeadersMiddleware

Validates all six headers are set with correct values:

Strict-Transport-Security: max-age=31536000; includeSubDomainsX-Frame-Options: DENYX-Content-Type-Options: nosniffContent-Security-Policy: [full policy]
✓ Referrer-Policy: strict-origin-when-cross-originPermissions-Policy: camera=(), microphone=(), geolocation=(), interest-cohort=()

TestSecurityHeadersMiddleware_MultipleRequests

  • Tests GET and POST endpoints
  • Verifies headers across different status codes (200, 201)
  • Ensures consistency across all routes

TestSecurityHeadersMiddleware_WithOtherMiddleware

  • Validates no conflicts with existing middleware
  • Confirms custom headers are preserved

TestSecurityHeadersMiddleware_HSTS_Format

  • Verifies HSTS max-age directive
  • Confirms includeSubDomains flag present

TestSecurityHeadersMiddleware_CSP_Directives

  • Validates critical CSP directives
  • Ensures protection against XSS and injection attacks

Test Results

$ go test ./pkg/server/... -v
=== RUN   TestSecurityHeadersMiddleware
=== RUN   TestSecurityHeadersMiddleware/Strict-Transport-Security_header
=== RUN   TestSecurityHeadersMiddleware/X-Frame-Options_header
=== RUN   TestSecurityHeadersMiddleware/X-Content-Type-Options_header
=== RUN   TestSecurityHeadersMiddleware/Content-Security-Policy_header
=== RUN   TestSecurityHeadersMiddleware/Referrer-Policy_header
=== RUN   TestSecurityHeadersMiddleware/Permissions-Policy_header
--- PASS: TestSecurityHeadersMiddleware (0.00s)
[...]
PASS
ok      github.com/seqeralabs/staticreg/pkg/server    2.100s

All tests passing - No regressions introduced

Security Impact

Before

HTTP/2 200 OK
Content-Type: application/json
[No security headers]

After

HTTP/2 200 OK
Content-Type: application/json
Strict-Transport-Security: max-age=31536000; includeSubDomains
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
Content-Security-Policy: default-src 'self'; style-src 'self' 'unsafe-inline'; [...]
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: camera=(), microphone=(), geolocation=(), interest-cohort=()

Verification

Manual Testing

# Build and run the application
make _output/dist
./staticreg serve

# Test headers with curl
curl -I http://localhost:8080/

# Expected output includes:
# Strict-Transport-Security: max-age=31536000; includeSubDomains
# X-Frame-Options: DENY
# X-Content-Type-Options: nosniff
# Content-Security-Policy: [...]
# Referrer-Policy: strict-origin-when-cross-origin
# Permissions-Policy: [...]

Browser Testing

Use browser DevTools to verify:

  1. Network tab → Response Headers
  2. Security scan tools (Mozilla Observatory, SecurityHeaders.com)
  3. OWASP ZAP automated scan

Configuration Notes

CSP Customization

The current CSP policy allows 'unsafe-inline' for styles to support Tailwind CSS. If your application requires stricter CSP:

// Remove 'unsafe-inline' and use nonces
c.Writer.Header().Set("Content-Security-Policy",
  "style-src 'self' 'nonce-{random}'")

HSTS Considerations

  • max-age=31536000: 1 year HSTS duration (recommended minimum: 6 months)
  • includeSubDomains: Applies to all subdomains (ensure all subdomains support HTTPS)
  • preload: Not included (requires HTTPS on all subdomains + manual submission to browsers)

To enable HSTS preload:

c.Writer.Header().Set("Strict-Transport-Security",
  "max-age=63072000; includeSubDomains; preload")

References

Checklist

  • Security headers middleware implemented
  • All 6 critical headers configured
  • Comprehensive unit tests added (5 test cases)
  • All existing tests passing (no regressions)
  • Code compiles successfully
  • Middleware registered globally
  • Headers applied to all routes
  • Documentation included in code comments
  • OWASP recommendations followed

Review Focus Areas

  1. CSP Policy (pkg/server/server.go:207)

    • Verify 'unsafe-inline' is acceptable for your use case
    • Consider if additional directives needed for external resources
  2. HSTS Configuration (pkg/server/server.go:190)

    • Confirm 1-year max-age is appropriate
    • Verify all subdomains support HTTPS before deploying
  3. Middleware Order (pkg/server/server.go:88)

    • Placed after recovery but before routing
    • Ensures headers on all responses (including errors)
  4. Test Coverage (pkg/server/security_headers_test.go)

    • All headers tested with exact value matching
    • Edge cases covered (multiple requests, middleware interaction)

Resolves: Server Security Misconfiguration vulnerability (OWASP Low, CVSS 3.7)
Impact: Hardens application against clickjacking, XSS, SSL stripping, and MIME-sniffing attacks

@munishchouhan munishchouhan self-assigned this Feb 16, 2026
@munishchouhan munishchouhan requested review from a team and fntlnz February 16, 2026 15:14
@munishchouhan munishchouhan changed the title Added security headers Add HTTP Security Headers Feb 16, 2026
@munishchouhan munishchouhan merged commit fc3e434 into master Mar 2, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants