Skip to content
Draft
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
3 changes: 2 additions & 1 deletion urns/schemes.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ var lineRegex = regexp.MustCompile(`^[a-zA-Z0-9_]{1,36}$`)
var phoneRegex = regexp.MustCompile(`^((\+[0-9]{7,15})|([a-z0-9]{1,64}))$`) // E164 or short code or sender ID
var twitterHandleRegex = regexp.MustCompile(`^[a-zA-Z0-9_]{1,15}$`)
var webchatRegex = regexp.MustCompile(`^[a-zA-Z0-9]{24}(:[^\s@]+@[^\s@]+)?$`)
var whatsappRegex = regexp.MustCompile(`^[a-zA-Z0-9.]{1,256}$`)
Copy link

Copilot AI Nov 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The regex pattern ^[a-zA-Z0-9.]{1,256}$ is too permissive and doesn't properly validate WhatsApp URNs. It accepts invalid patterns like "abc.def.ghi", "user", or random alphanumeric strings.

According to the WhatsApp Business-scoped user ID documentation, the format should be user. followed by exactly 64 hexadecimal characters. The regex should validate:

  1. Traditional phone number format: digits only (original format)
  2. Business-scoped user IDs: user. prefix followed by 64 hex characters

Consider using a more specific pattern like:

var whatsappRegex = regexp.MustCompile(`^([0-9]+|user\.[0-9a-f]{64})$`)

This ensures only valid WhatsApp identifiers are accepted.

Suggested change
var whatsappRegex = regexp.MustCompile(`^[a-zA-Z0-9.]{1,256}$`)
var whatsappRegex = regexp.MustCompile(`^([0-9]+|user\.[0-9a-f]{64})$`)

Copilot uses AI. Check for mistakes.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where is @copilot getting this information from? According to https://developers.facebook.com/documentation/business-messaging/whatsapp/business-scoped-user-ids#business-scoped-user-id the identifiers are "composed of up to 256 alphanumeric characters"


const (
// FacebookRefPrefix is prefix used for facebook referral URNs
Expand Down Expand Up @@ -196,5 +197,5 @@ var WeChat = &Scheme{
var WhatsApp = &Scheme{
Prefix: "whatsapp",
Name: "WhatsApp",
Validate: func(path string) bool { return allDigitsRegex.MatchString(path) },
Validate: func(path string) bool { return whatsappRegex.MatchString(path) },
}
6 changes: 5 additions & 1 deletion urns/urns_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ func TestURNProperties(t *testing.T) {
{"tel:+250788383383", "0788 383 383", "", "", map[string][]string{}},
{"twitter:85114?foo=bar#foobar", "foobar", "foobar", "foo=bar", map[string][]string{"foo": {"bar"}}},
{"webchat:123456789012345678901234", "123456789012345678901234", "", "", map[string][]string{}},
{"whatsapp:123456789012345678901234", "123456789012345678901234", "", "", map[string][]string{}},
{"whatsapp:user.9373795779eb6441c8adb2eaee5b848e7dd174ddd302d7db62142f4722d574b6", "user.9373795779eb6441c8adb2eaee5b848e7dd174ddd302d7db62142f4722d574b6", "", "", map[string][]string{}},
}
for _, tc := range testCases {
assert.Equal(t, string(tc.urn), tc.urn.String())
Expand Down Expand Up @@ -64,6 +66,7 @@ func TestNewFromParts(t *testing.T) {
{urns.Instagram, "12345", nil, "", "instagram:12345", "instagram:12345", false},
{urns.Telegram, "12345", nil, "Jane", "telegram:12345#Jane", "telegram:12345", false},
{urns.WhatsApp, "12345", nil, "", "whatsapp:12345", "whatsapp:12345", false},
{urns.WhatsApp, "user.9373795779eb6441c8adb2eaee5b848e7dd174ddd302d7db62142f4722d574b6", nil, "", "whatsapp:user.9373795779eb6441c8adb2eaee5b848e7dd174ddd302d7db62142f4722d574b6", "whatsapp:user.9373795779eb6441c8adb2eaee5b848e7dd174ddd302d7db62142f4722d574b6", false},
{urns.WebChat, "123456789012345678901234", nil, "", "webchat:123456789012345678901234", "webchat:123456789012345678901234", false},
{urns.WebChat, "123456789012345678901234", nil, "[email protected]", "webchat:123456789012345678901234#[email protected]", "webchat:123456789012345678901234", false},

Expand Down Expand Up @@ -224,7 +227,8 @@ func TestValidate(t *testing.T) {

// whatsapp needs to be integers
Copy link

Copilot AI Nov 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment is now outdated. WhatsApp URNs no longer need to be integers only - they can also be business-scoped user IDs in the format user.<hex_string>.

Update the comment to reflect both supported formats:

// whatsapp can be phone numbers (integers) or business-scoped user IDs (user.<hex>)
Suggested change
// whatsapp needs to be integers
// whatsapp can be phone numbers (integers) or business-scoped user IDs (user.<hex>)

Copilot uses AI. Check for mistakes.
{"whatsapp:12354", ""},
{"whatsapp:abcde", "invalid path component"},
{"whatsapp:abcde", ""},
Copy link

Copilot AI Nov 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test case for "whatsapp:abcde" has been changed from expecting an error to being valid (empty error string). However, "abcde" is neither a valid phone number (not all digits) nor a valid business-scoped user ID (doesn't match the user.<64-hex-chars> format).

This should remain invalid and expect an error. If the validation regex is fixed to properly validate both formats, this test case should continue to expect "invalid path component".

Suggested change
{"whatsapp:abcde", ""},
{"whatsapp:abcde", "invalid path component"},

Copilot uses AI. Check for mistakes.
{"whatsapp:user.9373795779eb6441c8adb2eaee5b848e7dd174ddd302d7db62142f4722d574b6", ""},
Copy link

Copilot AI Nov 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider adding more test cases to validate edge cases and invalid business-scoped user ID formats, such as:

  • {"whatsapp:user.123", "invalid path component"} - hex string too short
  • {"whatsapp:user.9373795779eb6441c8adb2eaee5b848e7dd174ddd302d7db62142f4722d574b6extra", "invalid path component"} - hex string too long
  • {"whatsapp:user.9373795779eb6441c8adb2eaee5b848e7dd174ddd302d7db62142f4722d574bG", "invalid path component"} - invalid hex character (G)
  • {"whatsapp:user", "invalid path component"} - missing hex portion

This ensures the validation properly enforces the business-scoped user ID format.

Copilot uses AI. Check for mistakes.
{"whatsapp:+12067799294", "invalid path component"},

// freschat has to be two uuids separated by a colon
Expand Down