Clean up wrong vanity rules
This commit is contained in:
+6
-12
@@ -13,15 +13,6 @@ import (
|
||||
// could be mistaken for a path element, a dotfile or a traversal is excluded.
|
||||
var vanityRe = regexp.MustCompile(`^[a-z0-9][a-z0-9._-]{1,63}$`)
|
||||
|
||||
// reserved names would shadow a route or a well-known file if they were ever
|
||||
// allowed into the object namespace.
|
||||
var reserved = map[string]bool{
|
||||
"d": true, "i": true, "api": true, "static": true, "admin": true,
|
||||
"login": true, "logout": true, "upload": true,
|
||||
"favicon.ico": true, "robots.txt": true, "index.html": true,
|
||||
"sitemap.xml": true, "tokens.json": true, "objects": true,
|
||||
}
|
||||
|
||||
var ErrBadID = errors.New("invalid name")
|
||||
|
||||
// CleanID validates an id arriving from a URL or from a vanity request and
|
||||
@@ -30,6 +21,12 @@ var ErrBadID = errors.New("invalid name")
|
||||
//
|
||||
// This is the *only* function permitted to turn caller input into a path
|
||||
// element; every filesystem path in this package is built from its output.
|
||||
//
|
||||
// There is deliberately no list of reserved words. An id appears only under
|
||||
// /d/ and /i/ in a URL, and only as a directory of its own inside the objects
|
||||
// directory on disk, so no spelling of it can shadow a route or a file of
|
||||
// ours: "favicon.png" and "admin" are ordinary names and refusing them would
|
||||
// be theatre.
|
||||
func CleanID(s string) (string, error) {
|
||||
s = strings.ToLower(strings.TrimSpace(s))
|
||||
if !vanityRe.MatchString(s) {
|
||||
@@ -40,9 +37,6 @@ func CleanID(s string) (string, error) {
|
||||
if strings.Contains(s, "..") || strings.HasSuffix(s, ".") {
|
||||
return "", ErrBadID
|
||||
}
|
||||
if reserved[s] {
|
||||
return "", ErrBadID
|
||||
}
|
||||
return s, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -23,12 +23,11 @@ func TestCleanID(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// Anything that could escape the objects directory, shadow a route, or
|
||||
// collide on a case-insensitive filesystem must be refused.
|
||||
// Anything that could escape the objects directory or collide on a
|
||||
// case-insensitive filesystem must be refused.
|
||||
invalid := []string{
|
||||
"", "a", ".", "..", "...", "../etc/passwd", "a/b", `a\b`, "/abs",
|
||||
".hidden", "a..b", "trailing.", "api", "static", "d", "i",
|
||||
"robots.txt", "tokens.json", "with space", "emoji-🙂",
|
||||
".hidden", "a..b", "trailing.", "d", "i", "with space", "emoji-🙂",
|
||||
strings.Repeat("x", 65), "a\x00b", "a\nb",
|
||||
}
|
||||
for _, in := range invalid {
|
||||
@@ -36,6 +35,16 @@ func TestCleanID(t *testing.T) {
|
||||
t.Errorf("CleanID(%q) = %q, want an error", in, got)
|
||||
}
|
||||
}
|
||||
|
||||
// Names that merely look like something of ours are ordinary names: an id
|
||||
// lives under /d/ and /i/ and in a directory of its own, so it shadows
|
||||
// nothing. Refusing these would take names from people for no benefit.
|
||||
for _, in := range []string{"api", "static", "admin", "upload", "login",
|
||||
"robots.txt", "tokens.json", "favicon.png", "index.html"} {
|
||||
if got, err := CleanID(in); err != nil || got != in {
|
||||
t.Errorf("CleanID(%q) = %q, %v; want it accepted unchanged", in, got, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCleanIDAcceptsGeneratedUUIDs(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user