Missing Tls in Chi
How Missing Tls Manifests in Chi
Missing TLS in Chi applications creates several attack vectors that are particularly problematic for Go HTTP APIs. When Chi routers are deployed without TLS termination, attackers can intercept API requests in transit, leading to credential theft, session hijacking, and data exposure.
The most common manifestation occurs when developers run Chi servers on HTTP without considering production deployment. Consider this vulnerable pattern:
package main
import (
"github.com/go-chi/chi/v5"
"net/http"
)
func main() {
r := chi.NewRouter()
r.Get("/api/users", getUsersHandler)
http.ListenAndServe(":8080", r) // Vulnerable: no TLS
}
This exposes the entire API surface to man-in-the-middle attacks. An attacker on the same network can capture authentication headers, API keys, and sensitive user data flowing between clients and the Chi server.
Another Chi-specific vulnerability arises when middleware chains assume secure connections. Many authentication middlewares check r.TLS or r.Header.Get("X-Forwarded-Proto") to validate connection security. When deployed behind a load balancer without proper configuration, these checks can be bypassed:
func AuthMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Vulnerable: assumes r.TLS is reliable
if r.TLS == nil {
http.Error(w, "HTTPS required", http.StatusForbidden)
return
}
next.ServeHTTP(w, r)
})
}
Behind a misconfigured load balancer, r.TLS may always be nil, causing the middleware to reject all requests or, worse, allow insecure connections if the check is removed.
Chi's URL parameter handling also becomes dangerous without TLS. Path parameters containing sensitive identifiers like user IDs or tokens are transmitted in plaintext:
r.Get("/api/users/{userID}/profile", getUserProfileHandler)
// Vulnerable: userID transmitted without encryption
// attacker can see: /api/users/12345/profile
This is especially problematic for APIs using sequential IDs or predictable patterns, enabling enumeration attacks even if the application logic is sound.
Chi-Specific Detection
Detecting missing TLS in Chi applications requires both static analysis and runtime scanning. For static detection, middleBrick's OpenAPI analysis can identify endpoints that lack HTTPS requirements in their specifications:
openapi: 3.0.0
info:
title: Vulnerable API
paths:
/api/users:
get:
# Missing: "schemes: [https]"
summary: List users
responses:
'200':
description: OK
middleBrick scans the running Chi application and identifies endpoints accessible over HTTP. The scanner tests each discovered endpoint by attempting connections on both HTTP and HTTPS ports, then flags any endpoints that respond over unencrypted channels.
For Chi applications behind reverse proxies, middleBrick checks the X-Forwarded-Proto header handling. Many Chi apps incorrectly trust this header without validation:
func ProtoMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
proto := r.Header.Get("X-Forwarded-Proto")
if proto != "https" {
// Vulnerable: trusts header without validation
http.Redirect(w, r, "https://"+r.Host+r.RequestURI, http.StatusPermanentRedirect)
return
}
next.ServeHTTP(w, r)
})
}
middleBrick actively tests this by sending requests with forged X-Forwarded-Proto headers to verify proper validation.
The scanner also examines middleware chains for TLS-dependent logic. If authentication or authorization middleware contains r.TLS != nil checks, middleBrick flags this as a potential security dependency that could fail in production environments.
middleBrick's LLM security module adds another layer of detection for Chi applications that integrate AI features. If your Chi API serves LLM endpoints over HTTP, the scanner tests for system prompt leakage and prompt injection vulnerabilities that are exacerbated by lack of transport encryption.
Chi-Specific Remediation
Remediating TLS issues in Chi requires both configuration changes and code updates. The most straightforward fix is enabling TLS directly in your Chi application:
package main
import (
"github.com/go-chi/chi/v5"
"net/http"
"os"
)
func main() {
r := chi.NewRouter()
r.Get("/api/users", getUsersHandler)
// Load certificates from environment
certPath := os.Getenv("TLS_CERT_PATH")
keyPath := os.Getenv("TLS_KEY_PATH")
if certPath == "" || keyPath == "" {
panic("TLS certificates not configured")
}
// Enforce HTTPS
http.ListenAndServeTLS(":443", certPath, keyPath, r)
}
For development environments, you can use self-signed certificates or tools like mkcert to generate trusted local certs.
When deploying behind a reverse proxy or load balancer, implement proper X-Forwarded-Proto validation in Chi middleware:
func SecureProtoMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Validate forwarded proto only from trusted proxies
trustedProxies := []string{"192.168.1.0/24", "10.0.0.0/8"}
if isTrustedProxy(r.RemoteAddr, trustedProxies) {
proto := r.Header.Get("X-Forwarded-Proto")
if proto == "http" {
httpsURL := "https://" + r.Host + r.RequestURI
http.Redirect(w, r, httpsURL, http.StatusPermanentRedirect)
return
}
}
// Additional check for direct connections
if r.TLS == nil && !isTrustedProxy(r.RemoteAddr, trustedProxies) {
http.Error(w, "HTTPS required", http.StatusForbidden)
return
}
next.ServeHTTP(w, r)
})
}
func isTrustedProxy(addr string, subnets []string) bool {
// Implementation to check if addr is in trusted subnets
return false
}
Integrate this middleware early in your Chi router chain to ensure all requests are validated before reaching business logic.
For comprehensive TLS coverage, combine middleware with middleware that enforces HSTS headers:
func HSTSHandler(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Add("Strict-Transport-Security", "max-age=31536000; includeSubDomains")
next.ServeHTTP(w, r)
})
}
// Apply to router
r.Use(HSTSHandler)
r.Use(SecureProtoMiddleware)
Finally, integrate middleBrick scanning into your development workflow to catch TLS regressions:
# .github/workflows/security.yml
name: Security Scan
on: [push, pull_request]
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Run middleBrick Scan
run: |
npm install -g middlebrick
middlebrick scan http://localhost:8080 --output scan-report.json
- name: Fail on TLS issues
run: |
if grep -q "Missing TLS" scan-report.json; then
echo "TLS vulnerabilities found!" >&2
exit 1
fi
This ensures any deployment without proper TLS configuration fails the build, preventing vulnerable code from reaching production.
Related CWEs: encryption
| CWE ID | Name | Severity |
|---|---|---|
| CWE-319 | Cleartext Transmission of Sensitive Information | HIGH |
| CWE-295 | Improper Certificate Validation | HIGH |
| CWE-326 | Inadequate Encryption Strength | HIGH |
| CWE-327 | Use of a Broken or Risky Cryptographic Algorithm | HIGH |
| CWE-328 | Use of Weak Hash | HIGH |
| CWE-330 | Use of Insufficiently Random Values | HIGH |
| CWE-338 | Use of Cryptographically Weak PRNG | MEDIUM |
| CWE-693 | Protection Mechanism Failure | MEDIUM |
| CWE-757 | Selection of Less-Secure Algorithm During Negotiation | HIGH |
| CWE-261 | Weak Encoding for Password | HIGH |
Frequently Asked Questions
Can I use Let's Encrypt with Chi for free TLS certificates?
Does middleBrick scan for TLS configuration issues beyond just missing TLS?
X-Forwarded-Proto headers when behind proxies, and checks for middleware that makes insecure TLS assumptions.