diff --git a/backend/go.mod b/backend/go.mod index 5ec971d0..55d2836c 100644 --- a/backend/go.mod +++ b/backend/go.mod @@ -23,7 +23,7 @@ require ( github.com/gorilla/feeds v1.1.1 github.com/hashicorp/go-multierror v1.1.0 github.com/kyokomi/emoji v2.2.1+incompatible - github.com/microcosm-cc/bluemonday v1.0.5 + github.com/microcosm-cc/bluemonday v1.0.9 github.com/pkg/errors v0.9.1 github.com/rakyll/statik v0.1.7 github.com/rs/xid v1.2.1 @@ -35,5 +35,5 @@ require ( go.uber.org/goleak v1.0.0 golang.org/x/crypto v0.0.0-20200406173513-056763e48d71 golang.org/x/image v0.0.0-20200119044424-58c23975cae1 - golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2 + golang.org/x/net v0.0.0-20210421230115-4e50805a0758 ) diff --git a/backend/go.sum b/backend/go.sum index 675e464f..ef8e0b63 100644 --- a/backend/go.sum +++ b/backend/go.sum @@ -28,8 +28,6 @@ github.com/aws/aws-sdk-go v1.34.28 h1:sscPpn/Ns3i0F4HPEWAVcwdIRaZZCuL7llJ2/60yPI github.com/aws/aws-sdk-go v1.34.28/go.mod h1:H7NKnBqNVzoTJpGfLrQkkD+ytBA93eiDYi/+8rV9s48= github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= -github.com/chris-ramon/douceur v0.2.0 h1:IDMEdxlEUUBYBKE4z/mJnFyVXox+MjuEVDJNN27glkU= -github.com/chris-ramon/douceur v0.2.0/go.mod h1:wDW5xjJdeoMm1mRt4sD4c/LbF/mWdEpRXQKjTR8nIBE= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= @@ -88,6 +86,7 @@ github.com/go-session/session v3.1.2+incompatible/go.mod h1:8B3iivBQjrz/JtC68Np2 github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-test/deep v1.0.4 h1:u2CU3YKy9I2pmu9pX0eq50wCgjfGIt539SqR7FbHiho= github.com/go-test/deep v1.0.4/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0= github.com/gobuffalo/depgen v0.0.0-20190329151759-d478694a28d3/go.mod h1:3STtPUQYuzV0gBVOY3vy6CfMm/ljR4pABfrTeHNLHUY= @@ -132,7 +131,6 @@ github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= github.com/gorilla/feeds v1.1.1 h1:HwKXxqzcRNg9to+BbvJog4+f3s/xzvtZXICcQGutYfY= github.com/gorilla/feeds v1.1.1/go.mod h1:Nk0jZrvPFZX1OBe5NPiddPw7CfwF6Q9eqzaBbaightA= -github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM= github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= @@ -180,10 +178,8 @@ github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNx github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc= -github.com/microcosm-cc/bluemonday v1.0.4 h1:p0L+CTpo/PLFdkoPcJemLXG+fpMD7pYOoDEq1axMbGg= -github.com/microcosm-cc/bluemonday v1.0.4/go.mod h1:8iwZnFn2CDDNZ0r6UXhF4xawGvzaqzCRa1n3/lO3W2w= -github.com/microcosm-cc/bluemonday v1.0.5 h1:cF59UCKMmmUgqN1baLvqU/B1ZsMori+duLVTLpgiG3w= -github.com/microcosm-cc/bluemonday v1.0.5/go.mod h1:8iwZnFn2CDDNZ0r6UXhF4xawGvzaqzCRa1n3/lO3W2w= +github.com/microcosm-cc/bluemonday v1.0.9 h1:dpCwruVKoyrULicJwhuY76jB+nIxRVKv/e248Vx/BXg= +github.com/microcosm-cc/bluemonday v1.0.9/go.mod h1:B2riunDr9benLHghZB7hjIgdwSUzzs0pjCxFrWYEZFU= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= github.com/moul/http2curl v1.0.0 h1:dRMWoAtb+ePxMlLkrCbAqh4TlPHXvoGUSQ323/9Zahs= @@ -307,8 +303,9 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2 h1:eDrdRpKgkcCqKZQwyZRyeFZgfqt37SL7Kv3tok06cKE= golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20210421230115-4e50805a0758 h1:aEpZnXcAmXkd6AvLb2OPt+EN1Zu/8Ne3pCqPjja5PXY= +golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -333,12 +330,16 @@ golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe h1:WdX7u8s3yOigWAhHEaDl8r9G+4XwFQEQFtBMYyN+kXQ= +golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1 h1:NusfzzA6yGQ+ua51ck7E3omNUX/JuqbFSaRGqU8CcLI= golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/backend/vendor/github.com/chris-ramon/douceur/parser/parser.go b/backend/vendor/github.com/aymerick/douceur/parser/parser.go similarity index 100% rename from backend/vendor/github.com/chris-ramon/douceur/parser/parser.go rename to backend/vendor/github.com/aymerick/douceur/parser/parser.go diff --git a/backend/vendor/github.com/chris-ramon/douceur/LICENSE b/backend/vendor/github.com/chris-ramon/douceur/LICENSE deleted file mode 100644 index 6ce87cd3..00000000 --- a/backend/vendor/github.com/chris-ramon/douceur/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2015 Aymerick JEHANNE - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - diff --git a/backend/vendor/github.com/go-pkgz/rest/cache_control.go b/backend/vendor/github.com/go-pkgz/rest/cache_control.go new file mode 100644 index 00000000..5a709339 --- /dev/null +++ b/backend/vendor/github.com/go-pkgz/rest/cache_control.go @@ -0,0 +1,35 @@ +package rest + +import ( + "crypto/sha1" //nolint not used for cryptography + "fmt" + "net/http" + "strings" + "time" +) + +// CacheControl is a middleware setting cache expiration. Using url+version for etag +func CacheControl(expiration time.Duration, version string) func(http.Handler) http.Handler { + + etag := func(r *http.Request, version string) string { + s := fmt.Sprintf("%s:%s", version, r.URL.String()) + return fmt.Sprintf("%x", sha1.Sum([]byte(s))) //nolint + } + + return func(h http.Handler) http.Handler { + fn := func(w http.ResponseWriter, r *http.Request) { + e := `"` + etag(r, version) + `"` + w.Header().Set("Etag", e) + w.Header().Set("Cache-Control", fmt.Sprintf("max-age=%d, no-cache", int(expiration.Seconds()))) + + if match := r.Header.Get("If-None-Match"); match != "" { + if strings.Contains(match, e) { + w.WriteHeader(http.StatusNotModified) + return + } + } + h.ServeHTTP(w, r) + } + return http.HandlerFunc(fn) + } +} diff --git a/backend/vendor/github.com/go-pkgz/rest/depricattion.go b/backend/vendor/github.com/go-pkgz/rest/depricattion.go new file mode 100644 index 00000000..7b5f7131 --- /dev/null +++ b/backend/vendor/github.com/go-pkgz/rest/depricattion.go @@ -0,0 +1,21 @@ +package rest + +import ( + "fmt" + "net/http" + "time" +) + +// Deprecation adds a header 'Deprecation: version="version", date="date" header' +// see https://tools.ietf.org/id/draft-dalal-deprecation-header-00.html +func Deprecation(version string, date time.Time) func(http.Handler) http.Handler { + f := func(h http.Handler) http.Handler { + fn := func(w http.ResponseWriter, r *http.Request) { + headerVal := fmt.Sprintf("version=\"%s\", date=\"%s\"", version, date.Format(time.RFC3339)) + w.Header().Set("Deprecation", headerVal) + h.ServeHTTP(w, r) + } + return http.HandlerFunc(fn) + } + return f +} diff --git a/backend/vendor/github.com/go-pkgz/rest/file_server.go b/backend/vendor/github.com/go-pkgz/rest/file_server.go new file mode 100644 index 00000000..8c981a05 --- /dev/null +++ b/backend/vendor/github.com/go-pkgz/rest/file_server.go @@ -0,0 +1,49 @@ +package rest + +import ( + "fmt" + "net/http" + "os" + "path/filepath" + "strings" +) + +// FileServer returns http.FileServer handler to serve static files from a http.FileSystem, +// prevents directory listing. +// - public defines base path of the url, i.e. for http://example.com/static/* it should be /static +// - local for the local path to the root of the served directory +func FileServer(public, local string) (http.Handler, error) { + + root, err := filepath.Abs(local) + if err != nil { + return nil, fmt.Errorf("can't get absolute path for %s: %w", local, err) + } + if _, err = os.Stat(root); os.IsNotExist(err) { + return nil, fmt.Errorf("local path %s doesn't exist: %w", root, err) + } + + return http.StripPrefix(public, http.FileServer(noDirListingFS{http.Dir(root)})), nil +} + +type noDirListingFS struct{ fs http.FileSystem } + +// Open file on FS, for directory enforce index.html and fail on a missing index +func (fs noDirListingFS) Open(name string) (http.File, error) { + f, err := fs.fs.Open(name) + if err != nil { + return nil, err + } + + s, err := f.Stat() + if err != nil { + return nil, err + } + + if s.IsDir() { + index := strings.TrimSuffix(name, "/") + "/index.html" + if _, err := fs.fs.Open(index); err != nil { + return nil, err + } + } + return f, nil +} diff --git a/backend/vendor/github.com/go-pkgz/rest/rewrite.go b/backend/vendor/github.com/go-pkgz/rest/rewrite.go new file mode 100644 index 00000000..f3286bd2 --- /dev/null +++ b/backend/vendor/github.com/go-pkgz/rest/rewrite.go @@ -0,0 +1,57 @@ +package rest + +import ( + "context" + "net/http" + "net/url" + "path" + "regexp" + "strings" +) + +// Rewrite middleware with from->to rule. Supports regex (like nginx) and prevents multiple rewrites +// example: Rewrite(`^/sites/(.*)/settings/$`, `/sites/settings/$1` +func Rewrite(from, to string) func(http.Handler) http.Handler { + reFrom := regexp.MustCompile(from) + + f := func(next http.Handler) http.Handler { + fn := func(w http.ResponseWriter, r *http.Request) { + + ctx := r.Context() + + // prevent double rewrites + if ctx != nil { + if _, ok := ctx.Value(contextKey("rewrite")).(bool); ok { + next.ServeHTTP(w, r) + return + } + } + + if !reFrom.MatchString(r.URL.Path) { + next.ServeHTTP(w, r) + return + } + + ru := reFrom.ReplaceAllString(r.URL.Path, to) + cru := path.Clean(ru) + if strings.HasSuffix(ru, "/") { // don't drop trailing slash + cru += "/" + } + u, e := url.Parse(cru) + if e != nil { + w.WriteHeader(http.StatusInternalServerError) + return + } + r.Header.Set("X-Original-URL", r.URL.RequestURI()) + r.URL.Path = u.Path + r.URL.RawPath = u.RawPath + if u.RawQuery != "" { + r.URL.RawQuery = u.RawQuery + } + ctx = context.WithValue(ctx, contextKey("rewrite"), true) + next.ServeHTTP(w, r.WithContext(ctx)) + } + return http.HandlerFunc(fn) + } + return f +} diff --git a/backend/vendor/github.com/microcosm-cc/bluemonday/.travis.yml b/backend/vendor/github.com/microcosm-cc/bluemonday/.travis.yml index 80809178..97175fbb 100644 --- a/backend/vendor/github.com/microcosm-cc/bluemonday/.travis.yml +++ b/backend/vendor/github.com/microcosm-cc/bluemonday/.travis.yml @@ -11,6 +11,10 @@ go: - 1.10.x - 1.11.x - 1.12.x + - 1.13.x + - 1.14.x + - 1.15.x + - 1.16.x - tip matrix: allow_failures: diff --git a/backend/vendor/github.com/microcosm-cc/bluemonday/SECURITY.md b/backend/vendor/github.com/microcosm-cc/bluemonday/SECURITY.md new file mode 100644 index 00000000..a344e7c0 --- /dev/null +++ b/backend/vendor/github.com/microcosm-cc/bluemonday/SECURITY.md @@ -0,0 +1,15 @@ +# Security Policy + +## Supported Versions + +Latest tag and tip are supported. + +Older tags remain present but changes result in new tags and are not back ported... please verify any issue against the latest tag and tip. + +## Reporting a Vulnerability + +Email: + +Bluemonday is pure OSS and not maintained by a company. As such there is no bug bounty program but security issues will be taken seriously and resolved as soon as possible. + +The maintainer lives in the United Kingdom and whilst the email is monitored expect a reply or ACK when the maintainer is awake. diff --git a/backend/vendor/github.com/microcosm-cc/bluemonday/go.mod b/backend/vendor/github.com/microcosm-cc/bluemonday/go.mod index 47b521a7..edbd585f 100644 --- a/backend/vendor/github.com/microcosm-cc/bluemonday/go.mod +++ b/backend/vendor/github.com/microcosm-cc/bluemonday/go.mod @@ -1,10 +1,9 @@ module github.com/microcosm-cc/bluemonday -go 1.9 +go 1.16 require ( - github.com/aymerick/douceur v0.2.0 // indirect - github.com/chris-ramon/douceur v0.2.0 + github.com/aymerick/douceur v0.2.0 github.com/gorilla/css v1.0.0 // indirect - golang.org/x/net v0.0.0-20181220203305-927f97764cc3 + golang.org/x/net v0.0.0-20210421230115-4e50805a0758 ) diff --git a/backend/vendor/github.com/microcosm-cc/bluemonday/go.sum b/backend/vendor/github.com/microcosm-cc/bluemonday/go.sum index 8c34e7a4..e195d4ea 100644 --- a/backend/vendor/github.com/microcosm-cc/bluemonday/go.sum +++ b/backend/vendor/github.com/microcosm-cc/bluemonday/go.sum @@ -1,8 +1,11 @@ github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= -github.com/chris-ramon/douceur v0.2.0 h1:IDMEdxlEUUBYBKE4z/mJnFyVXox+MjuEVDJNN27glkU= -github.com/chris-ramon/douceur v0.2.0/go.mod h1:wDW5xjJdeoMm1mRt4sD4c/LbF/mWdEpRXQKjTR8nIBE= github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= -golang.org/x/net v0.0.0-20181220203305-927f97764cc3 h1:eH6Eip3UpmR+yM/qI9Ijluzb1bNv/cAU/n+6l8tRSis= -golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20210421230115-4e50805a0758 h1:aEpZnXcAmXkd6AvLb2OPt+EN1Zu/8Ne3pCqPjja5PXY= +golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/backend/vendor/github.com/microcosm-cc/bluemonday/handlers.go b/backend/vendor/github.com/microcosm-cc/bluemonday/handlers.go index 1ef4c8ac..9753d6e9 100644 --- a/backend/vendor/github.com/microcosm-cc/bluemonday/handlers.go +++ b/backend/vendor/github.com/microcosm-cc/bluemonday/handlers.go @@ -26,6 +26,7 @@ // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + package bluemonday import ( diff --git a/backend/vendor/github.com/microcosm-cc/bluemonday/policy.go b/backend/vendor/github.com/microcosm-cc/bluemonday/policy.go index 739d302c..9c7e662f 100644 --- a/backend/vendor/github.com/microcosm-cc/bluemonday/policy.go +++ b/backend/vendor/github.com/microcosm-cc/bluemonday/policy.go @@ -69,6 +69,9 @@ type Policy struct { // Will skip for href="/foo" or href="foo" requireNoReferrerFullyQualifiedLinks bool + // When true, add crossorigin="anonymous" to HTML audio, img, link, script, and video tags + requireCrossOriginAnonymous bool + // When true add target="_blank" to fully qualified links // Will add for href="http://foo" // Will skip for href="/foo" or href="foo" @@ -433,25 +436,25 @@ func (spb *stylePolicyBuilder) OnElements(elements ...string) *Policy { // and return the updated policy func (spb *stylePolicyBuilder) OnElementsMatching(regex *regexp.Regexp) *Policy { - for _, attr := range spb.propertyNames { + for _, attr := range spb.propertyNames { - if _, ok := spb.p.elsMatchingAndStyles[regex]; !ok { - spb.p.elsMatchingAndStyles[regex] = make(map[string]stylePolicy) - } - - sp := stylePolicy{} - if spb.handler != nil { - sp.handler = spb.handler - } else if len(spb.enum) > 0 { - sp.enum = spb.enum - } else if spb.regexp != nil { - sp.regexp = spb.regexp - } else { - sp.handler = getDefaultHandler(attr) - } - spb.p.elsMatchingAndStyles[regex][attr] = sp + if _, ok := spb.p.elsMatchingAndStyles[regex]; !ok { + spb.p.elsMatchingAndStyles[regex] = make(map[string]stylePolicy) } + sp := stylePolicy{} + if spb.handler != nil { + sp.handler = spb.handler + } else if len(spb.enum) > 0 { + sp.enum = spb.enum + } else if spb.regexp != nil { + sp.regexp = spb.regexp + } else { + sp.handler = getDefaultHandler(attr) + } + spb.p.elsMatchingAndStyles[regex][attr] = sp + } + return spb.p } @@ -558,6 +561,16 @@ func (p *Policy) RequireNoReferrerOnFullyQualifiedLinks(require bool) *Policy { return p } +// RequireCrossOriginAnonymous will result in all audio, img, link, script, and +// video tags having a crossorigin="anonymous" added to them if one does not +// already exist +func (p *Policy) RequireCrossOriginAnonymous(require bool) *Policy { + + p.requireCrossOriginAnonymous = require + + return p +} + // AddTargetBlankToFullyQualifiedLinks will result in all a, area and link tags // that point to a non-local destination (i.e. starts with a protocol and has a // host) having a target="_blank" added to them if one does not already exist diff --git a/backend/vendor/github.com/microcosm-cc/bluemonday/sanitize.go b/backend/vendor/github.com/microcosm-cc/bluemonday/sanitize.go index bda91245..b462f099 100644 --- a/backend/vendor/github.com/microcosm-cc/bluemonday/sanitize.go +++ b/backend/vendor/github.com/microcosm-cc/bluemonday/sanitize.go @@ -39,7 +39,7 @@ import ( "golang.org/x/net/html" - cssparser "github.com/chris-ramon/douceur/parser" + "github.com/aymerick/douceur/parser" ) var ( @@ -122,22 +122,85 @@ func escapeUrlComponent(val string) string { return w.String() } -func sanitizedUrl(val string) (string, error) { +// Query represents a query +type Query struct { + Key string + Value string + HasValue bool +} + +func parseQuery(query string) (values []Query, err error) { + for query != "" { + key := query + if i := strings.IndexAny(key, "&;"); i >= 0 { + key, query = key[:i], key[i+1:] + } else { + query = "" + } + if key == "" { + continue + } + value := "" + hasValue := false + if i := strings.Index(key, "="); i >= 0 { + key, value = key[:i], key[i+1:] + hasValue = true + } + key, err1 := url.QueryUnescape(key) + if err1 != nil { + if err == nil { + err = err1 + } + continue + } + value, err1 = url.QueryUnescape(value) + if err1 != nil { + if err == nil { + err = err1 + } + continue + } + values = append(values, Query{ + Key: key, + Value: value, + HasValue: hasValue, + }) + } + return values, err +} + +func encodeQueries(queries []Query) string { + var buff bytes.Buffer + for i, query := range queries { + buff.WriteString(url.QueryEscape(query.Key)) + if query.HasValue { + buff.WriteString("=") + buff.WriteString(url.QueryEscape(query.Value)) + } + if i < len(queries)-1 { + buff.WriteString("&") + } + } + return buff.String() +} + +func sanitizedURL(val string) (string, error) { u, err := url.Parse(val) if err != nil { return "", err } - // sanitize the url query params - sanitizedQueryValues := make(url.Values, 0) - queryValues := u.Query() - for k, vals := range queryValues { - sk := html.EscapeString(k) - for _, v := range vals { - sv := v - sanitizedQueryValues.Add(sk, sv) - } + + // we use parseQuery but not u.Query to keep the order not change because + // url.Values is a map which has a random order. + queryValues, err := parseQuery(u.RawQuery) + if err != nil { + return "", err } - u.RawQuery = sanitizedQueryValues.Encode() + // sanitize the url query params + for i, query := range queryValues { + queryValues[i].Key = html.EscapeString(query.Key) + } + u.RawQuery = encodeQueries(queryValues) // u.String() will also sanitize host/scheme/user/pass return u.String(), nil } @@ -158,7 +221,7 @@ func (p *Policy) writeLinkableBuf(buff *bytes.Buffer, token *html.Token) { tokenBuff.WriteString(html.EscapeString(attr.Val)) continue } - u, err := sanitizedUrl(u) + u, err := sanitizedURL(u) if err == nil { tokenBuff.WriteString(u) } else { @@ -664,6 +727,26 @@ func (p *Policy) sanitizeAttrs( } } + if p.requireCrossOriginAnonymous && len(cleanAttrs) > 0 { + switch elementName { + case "audio", "img", "link", "script", "video": + var crossOriginFound bool + for _, htmlAttr := range cleanAttrs { + if htmlAttr.Key == "crossorigin" { + crossOriginFound = true + htmlAttr.Val = "anonymous" + } + } + + if !crossOriginFound { + crossOrigin := html.Attribute{} + crossOrigin.Key = "crossorigin" + crossOrigin.Val = "anonymous" + cleanAttrs = append(cleanAttrs, crossOrigin) + } + } + } + return cleanAttrs } @@ -687,7 +770,7 @@ func (p *Policy) sanitizeStyles(attr html.Attribute, elementName string) html.At if len(attr.Val) > 0 && attr.Val[len(attr.Val)-1] != ';' { attr.Val = attr.Val + ";" } - decs, err := cssparser.ParseDeclarations(attr.Val) + decs, err := parser.ParseDeclarations(attr.Val) if err != nil { attr.Val = "" return attr @@ -888,7 +971,6 @@ func (p *Policy) matchRegex(elementName string) (map[string]attrPolicy, bool) { return aps, matched } - // normaliseElementName takes a HTML element like