xsrftoken: escape colons
The current clean() replaces : with _ (colons are internally used as
separators).
This produce can produce same output for different inputs, for example
the user _foo_ can obtain valid tokens for user :foo:.
This CL replace colons with double colons instead of replacing them
with underscores.
Fixes golang/go#34308
Change-Id: I3e4148a0836e62fda1a5f0ba32b375121368afd3
Reviewed-on: https://go-review.googlesource.com/c/net/+/196457
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
diff --git a/xsrftoken/xsrf.go b/xsrftoken/xsrf.go
index bc861e1..4f66adf 100644
--- a/xsrftoken/xsrf.go
+++ b/xsrftoken/xsrf.go
@@ -20,9 +20,9 @@
// It is exported so clients may set cookie timeouts that match generated tokens.
const Timeout = 24 * time.Hour
-// clean sanitizes a string for inclusion in a token by replacing all ":"s.
+// clean sanitizes a string for inclusion in a token by replacing all ":" with "::".
func clean(s string) string {
- return strings.Replace(s, ":", "_", -1)
+ return strings.Replace(s, `:`, `::`, -1)
}
// Generate returns a URL-safe secure XSRF token that expires in 24 hours.
diff --git a/xsrftoken/xsrf_test.go b/xsrftoken/xsrf_test.go
index 6c8e7d9..fc0a48a 100644
--- a/xsrftoken/xsrf_test.go
+++ b/xsrftoken/xsrf_test.go
@@ -36,10 +36,32 @@
// TestSeparatorReplacement tests that separators are being correctly substituted
func TestSeparatorReplacement(t *testing.T) {
- tok := generateTokenAtTime("foo:bar", "baz", "wah", now)
- tok2 := generateTokenAtTime("foo", "bar:baz", "wah", now)
- if tok == tok2 {
- t.Errorf("Expected generated tokens to be different")
+ separatorTests := []struct {
+ name string
+ token1 string
+ token2 string
+ }{
+ {
+ "Colon",
+ generateTokenAtTime("foo:bar", "baz", "wah", now),
+ generateTokenAtTime("foo", "bar:baz", "wah", now),
+ },
+ {
+ "Colon and Underscore",
+ generateTokenAtTime("key", ":foo:", "wah", now),
+ generateTokenAtTime("key", "_foo_", "wah", now),
+ },
+ {
+ "Colon and Double Colon",
+ generateTokenAtTime("key", ":foo:", "wah", now),
+ generateTokenAtTime("key", "::foo::", "wah", now),
+ },
+ }
+
+ for _, st := range separatorTests {
+ if st.token1 == st.token2 {
+ t.Errorf("%v: Expected generated tokens to be different", st.name)
+ }
}
}