stream library is currently in active development (0.x versions). We provide security updates for the following versions:
| Version | Supported |
|---|---|
| 0.1.x | ✅ |
| < 0.1.0 | ❌ |
Future stable releases (v1.0+) will follow semantic versioning with LTS support.
We take security seriously. If you discover a security vulnerability in stream, please report it responsibly.
DO NOT open a public GitHub issue for security vulnerabilities.
Instead, please report security issues by:
-
Private Security Advisory (preferred): https://github.com/coregx/stream/security/advisories/new
-
Email to maintainers: Create a private GitHub issue or contact via discussions
Please include the following information in your report:
- Description of the vulnerability
- Steps to reproduce the issue (include proof-of-concept if applicable)
- Affected versions (which versions are impacted)
- Potential impact (DoS, information disclosure, RCE, etc.)
- Suggested fix (if you have one)
- Your contact information (for follow-up questions)
- Initial Response: Within 48-72 hours
- Triage & Assessment: Within 1 week
- Fix & Disclosure: Coordinated with reporter
We aim to:
- Acknowledge receipt within 72 hours
- Provide an initial assessment within 1 week
- Work with you on a coordinated disclosure timeline
- Credit you in the security advisory (unless you prefer to remain anonymous)
Real-time communication libraries (SSE and WebSocket) handle long-lived connections and untrusted data streams, introducing unique security risks.
Risk: Malicious handshake requests can exploit upgrade vulnerabilities.
Attack Vectors:
- Invalid
Sec-WebSocket-Keyvalues - Missing required headers
- Origin header spoofing
- Subprotocol injection
Mitigation in Library:
- ✅ RFC 6455 compliant handshake validation
- ✅ Strict header validation
- ✅ Proper
Sec-WebSocket-Acceptcomputation - ✅ Version negotiation (only version 13 supported)
- ✅ Optional origin validation
User Recommendations:
// ❌ BAD - Don't skip origin validation in production
conn, _ := websocket.Upgrade(w, r, nil)
// ✅ GOOD - Validate origins
opts := &websocket.UpgradeOptions{
CheckOrigin: func(r *http.Request) bool {
origin := r.Header.Get("Origin")
return origin == "https://yourdomain.com"
},
}
conn, err := websocket.Upgrade(w, r, opts)
if err != nil {
http.Error(w, "Forbidden", http.StatusForbidden)
return
}Risk: Long-lived connections can exhaust server resources.
Attack Vectors:
- Connection exhaustion (opening thousands of connections)
- Message flooding (sending excessive messages)
- Large frame/event payloads (memory exhaustion)
- Slow-read attacks (not consuming data)
Mitigation in Library:
- ✅ Configurable frame size limits
- ✅ Read/write timeouts
- ✅ Proper connection cleanup
- ✅ Hub-based broadcasting (efficient multi-client handling)
User Recommendations:
// ✅ Set connection limits
opts := &websocket.UpgradeOptions{
ReadBufferSize: 4096,
WriteBufferSize: 4096,
}
// ✅ Implement connection counting
var connCount atomic.Int32
http.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) {
if connCount.Load() >= 1000 {
http.Error(w, "Too many connections", http.StatusServiceUnavailable)
return
}
conn, _ := websocket.Upgrade(w, r, opts)
connCount.Add(1)
defer connCount.Add(-1)
defer conn.Close()
// Handle connection...
})
// ✅ Implement rate limiting per connection
limiter := rate.NewLimiter(100, 10) // 100 msg/s, burst 10
for {
if !limiter.Allow() {
conn.Close()
break
}
msgType, data, err := conn.Read()
if err != nil {
break
}
// Process message...
}Risk: Malicious messages can exploit client-side vulnerabilities.
Attack Vectors:
- XSS via SSE event data
- XSS via WebSocket messages
- Malicious JSON payloads
- Script injection in event streams
Mitigation:
- ✅ JSON parsing uses
encoding/json/v2(safe unmarshaling) - ✅ Binary-safe message handling
- 🔄 User Responsibility: Sanitize data before sending to clients
User Best Practices:
// ❌ BAD - Don't send unsanitized user input
hub.BroadcastText(userInput)
// ✅ GOOD - Sanitize HTML content
import "html"
safeData := html.EscapeString(userInput)
hub.BroadcastText(safeData)
// ✅ BETTER - Use JSON (auto-escaped)
type Message struct {
User string `json:"user"`
Text string `json:"text"`
}
hub.BroadcastJSON(Message{
User: username,
Text: userMessage, // Auto-escaped in JSON
})
// ✅ WebSocket - validate message types
msgType, data, err := conn.Read()
if err != nil {
return
}
if msgType != websocket.TextMessage && msgType != websocket.BinaryMessage {
conn.Close() // Reject invalid types
return
}Risk: Unauthenticated access to real-time streams.
Attack Vectors:
- Missing authentication on upgrade
- Token theft via insecure connections
- Session hijacking
- Unauthorized subscription to private channels
Mitigation:
- ✅ Upgrade happens at HTTP layer (use standard HTTP authentication)
- ✅ Origin validation support
- 🔄 User Responsibility: Implement authentication before upgrade
User Best Practices:
// ✅ Authenticate BEFORE upgrading to WebSocket
http.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) {
// Validate JWT token from query param or header
token := r.URL.Query().Get("token")
user, err := validateToken(token)
if err != nil {
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}
// Now upgrade
conn, err := websocket.Upgrade(w, r, &websocket.UpgradeOptions{
CheckOrigin: func(r *http.Request) bool {
return r.Header.Get("Origin") == "https://yourdomain.com"
},
})
if err != nil {
return
}
// Handle authenticated connection
handleAuthenticatedConn(conn, user)
})
// ✅ SSE - use standard HTTP auth
http.HandleFunc("/events", func(w http.ResponseWriter, r *http.Request) {
// Check Authorization header
if !isAuthorized(r) {
http.Error(w, "Forbidden", http.StatusForbidden)
return
}
conn, _ := sse.Upgrade(w, r)
defer conn.Close()
// Send authorized events only
})Risk: Malicious WebSocket frames can crash or compromise clients.
Attack Vectors:
- Malformed WebSocket frames
- Invalid UTF-8 in text frames
- Incorrect masking
- Reserved opcodes
Mitigation in Library:
- ✅ RFC 6455 compliant frame parsing
- ✅ UTF-8 validation for text frames
- ✅ Proper masking/unmasking
- ✅ Opcode validation
- ✅ Max frame size limits
User Best Practices:
// ✅ Validate received data
msgType, data, err := conn.Read()
if err != nil {
log.Printf("Read error: %v", err)
conn.Close()
return
}
// Validate message type
if msgType != websocket.TextMessage {
log.Printf("Unexpected message type: %d", msgType)
conn.Close()
return
}
// Parse and validate JSON
var msg Message
if err := json.Unmarshal(data, &msg); err != nil {
log.Printf("Invalid JSON: %v", err)
return // Ignore bad message, don't close
}Risk: Broadcasting to many clients can exhaust resources.
Attack Vectors:
- Memory exhaustion from buffered channels
- Goroutine leaks from unregistered clients
- CPU exhaustion from excessive broadcasts
Mitigation in Library:
- ✅ Hub uses buffered channels
- ✅ Proper client cleanup on unregister
- ✅ Non-blocking broadcast operations
- ✅ Graceful hub shutdown
User Best Practices:
// ✅ Always unregister clients
http.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) {
conn, _ := websocket.Upgrade(w, r, nil)
hub.Register(conn)
defer hub.Unregister(conn) // Critical!
for {
_, data, err := conn.Read()
if err != nil {
break
}
hub.Broadcast(data)
}
})
// ✅ Monitor hub health
go func() {
ticker := time.NewTicker(10 * time.Second)
for range ticker.C {
count := hub.ClientCount()
if count > 10000 {
log.Printf("WARNING: High client count: %d", count)
}
}
}()Always validate messages from clients:
// Define message schema
type ChatMessage struct {
Type string `json:"type"`
Content string `json:"content"`
UserID string `json:"user_id"`
}
// Validate all incoming messages
for {
msgType, data, err := conn.Read()
if err != nil {
break
}
var msg ChatMessage
if err := json.Unmarshal(data, &msg); err != nil {
log.Printf("Invalid message format: %v", err)
continue // Ignore invalid messages
}
// Validate fields
if msg.Type == "" || msg.Content == "" {
log.Printf("Missing required fields")
continue
}
// Sanitize content before broadcasting
msg.Content = html.EscapeString(msg.Content)
// Process validated message
handleMessage(msg)
}Protect against connection spam:
// Per-IP connection limits
var connLimiter = make(map[string]*rate.Limiter)
var limitMu sync.Mutex
func getConnLimiter(ip string) *rate.Limiter {
limitMu.Lock()
defer limitMu.Unlock()
limiter, exists := connLimiter[ip]
if !exists {
limiter = rate.NewLimiter(1, 5) // 1 conn/sec, burst 5
connLimiter[ip] = limiter
}
return limiter
}
http.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) {
ip := r.RemoteAddr
if !getConnLimiter(ip).Allow() {
http.Error(w, "Rate limit exceeded", http.StatusTooManyRequests)
return
}
conn, _ := websocket.Upgrade(w, r, nil)
// Handle connection...
})Never leak sensitive information:
// ❌ BAD - Leaks internal details
conn, err := websocket.Upgrade(w, r, nil)
if err != nil {
http.Error(w, err.Error(), 500) // Leaks implementation details!
}
// ✅ GOOD - Generic error messages
conn, err := websocket.Upgrade(w, r, nil)
if err != nil {
log.Printf("WebSocket upgrade failed: %v", err) // Log internally
http.Error(w, "Upgrade failed", http.StatusInternalServerError)
return
}Always use secure connections in production:
// ✅ Require TLS for WebSocket connections
http.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) {
if r.TLS == nil {
http.Error(w, "HTTPS required", http.StatusUpgradeRequired)
return
}
conn, _ := websocket.Upgrade(w, r, &websocket.UpgradeOptions{
CheckOrigin: func(r *http.Request) bool {
origin := r.Header.Get("Origin")
return strings.HasPrefix(origin, "https://")
},
})
// Handle connection...
})
// ✅ Use WSS (WebSocket Secure) URLs on client
// wss://yourdomain.com/ws (NOT ws://)Status: Mitigated via configuration and best practices.
Risk Level: Medium
Description: Attackers can open thousands of connections to exhaust resources.
Mitigation:
- Configurable timeouts
- Frame size limits
- Hub channel buffer limits
- User responsibility to implement connection limits
Status: Mitigated via timeouts.
Risk Level: Medium
Description: Clients can deliberately read/write slowly to tie up resources.
Mitigation:
- Buffered channels prevent blocking
- 🔄 User Responsibility: Set appropriate timeouts
Status: Mitigated in library.
Risk Level: Low
Description: Excessive fragmented frames can exhaust memory.
Mitigation:
- Max frame size enforced
- RFC 6455 compliant implementation
stream library has ZERO external dependencies:
- ✅ Pure stdlib implementation (SSE and WebSocket)
- ✅ No supply chain attacks
- ✅ No dependency vulnerabilities
- ✅ No transitive dependencies
- ✅ Smaller attack surface
Monitoring:
- ✅ Go stdlib security updates tracked
- ✅ No Dependabot needed (zero deps!)
- ✅ Unit tests with malicious frame data (314 tests)
- ✅ Malformed handshake tests
- ✅ Invalid UTF-8 validation tests
- ✅ Frame injection tests
- ✅ Race detector (
go test -race) - ✅ Static analysis (
go vet) - ✅ 34+ golangci-lint linters (security-focused)
- Overall: 84.3% (314 tests)
- SSE: 92.3% coverage
- WebSocket: 84.3% coverage
- 🔄 Fuzzing with go-fuzz (frame parsing, handshakes)
- 🔄 Penetration testing of WebSocket endpoints
- 🔄 Load testing for DoS resilience
- 🔄 Memory profiling under attack scenarios
No security vulnerabilities have been reported or fixed yet (project is in 0.x development).
When vulnerabilities are addressed, they will be listed here with:
- CVE ID (if assigned)
- Affected versions
- Fixed in version
- Severity (Critical/High/Medium/Low)
- Credit to reporter
- GitHub Security Advisory: https://github.com/coregx/stream/security/advisories/new
- Public Issues (for non-sensitive bugs): https://github.com/coregx/stream/issues
- Discussions: https://github.com/coregx/stream/discussions
stream library does not currently have a bug bounty program. We rely on responsible disclosure from the security community.
If you report a valid security vulnerability:
- ✅ Public credit in security advisory (if desired)
- ✅ Acknowledgment in CHANGELOG
- ✅ Our gratitude and recognition in README
- ✅ Priority review and quick fix
Thank you for helping keep stream secure! 🔒
Security is a journey, not a destination. We continuously improve our security posture with each release.