Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/sip-header-value-cap.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"github.com/livekit/protocol": patch
"@livekit/protocol": patch
---

Raise the SIP header value cap from 1 KB to 4 KB so carrier headers like Twilio's `X-Twilio-CallToken` (Immutable Call Forwarding token with SHAKEN/STIR PASSporTs, >1 KB) pass `CreateSIPParticipant` validation
15 changes: 13 additions & 2 deletions livekit/sip_validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,12 @@ func init() {
headerValuesCharacters.AddUTF8()
}

// maxHeaderValueLength caps a single SIP header value. It is not an RFC limit
// (RFC 3261 §7.1 bounds the message, not headers), but guards against abusive
// or oversized values. Set above carriers' real-world maximums — Twilio's
// X-Twilio-CallToken exceeds 1 KB — and well below the 8 KB UDP datagram bound.
const maxHeaderValueLength = 4096

// Required headers for SIP requests per RFC 3261 Section 8.1.1
var RequiredRequestHeaders = map[string]bool{
"via": true,
Expand Down Expand Up @@ -257,8 +263,13 @@ func ValidateHeaderValueResult(name, value string) ValidationResult {
return ValidationResult{}
}

if len(value) > 1024 {
return ValidationFailure(fmt.Errorf("header %s: value too long (max 1024 characters)", name))
// RFC 3261 caps the whole message (8 KB per §7.1 when UDP), not individual
// header values. Carriers do exceed 1 KB on a single header — e.g. Twilio's
// X-Twilio-CallToken carries an Immutable Call Forwarding token with
// SHAKEN/STIR + DIV PASSporTs that must be forwarded unchanged. 4096 keeps
// a single header from dominating a datagram while tolerating those.
if len(value) > maxHeaderValueLength {
return ValidationFailure(fmt.Errorf("header %s: value too long (max %d characters)", name, maxHeaderValueLength))
}

// Basic character validation - printable ASCII. We're stricter than the spec here - no UTF-8 for now
Expand Down
5 changes: 3 additions & 2 deletions livekit/sip_validation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,8 @@ var ValidHeaderValues = []string{
"Header with unicode café", // Unicode
"Header with unicode 世界", // Unicode
"Header with unicode émojis 🎉", // Unicode with emojis
strings.Repeat("a", 1024), // max length
strings.Repeat("a", 1024), // beyond carrier needs (e.g. X-Twilio-CallToken)
strings.Repeat("a", 4096), // max length
}

// Note: These restrictions are NOT in RFC 3261 but are applied for security/performance
Expand All @@ -110,7 +111,7 @@ var InvalidHeaderValues = []string{
"Header with\x01control", // control character
"Header with\x1Funit separator", // control character
"Header with\x7Fdelete", // delete character
strings.Repeat("a", 1025), // too long
strings.Repeat("a", 4097), // too long
}

// testCaseName truncates a test case name to maxLen and adds dots with total size
Expand Down