diff options
author | Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com> | 2023-05-20 17:37:04 +0200 |
---|---|---|
committer | Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com> | 2023-05-20 20:16:45 +0200 |
commit | 2637b4ef4dbb3f8d3e537f900bdd072b4078c87e (patch) | |
tree | 6b64225d157397befe5a7d0ab7925b8ad0e6ba94 | |
parent | 7c7baa618325cb3d2b1ef48bdc1f97aae25f62e9 (diff) |
Allow whitelisting mediaTypes used in resources.GetRemote
Fixes #10286
-rw-r--r-- | config/security/securityConfig.go | 3 | ||||
-rw-r--r-- | config/security/securityConfig_test.go | 2 | ||||
-rw-r--r-- | hugolib/securitypolicies_test.go | 28 | ||||
-rw-r--r-- | hugolib/testdata/fakejson.json | bin | 0 -> 42 bytes | |||
-rw-r--r-- | resources/resource_factories/create/remote.go | 15 |
5 files changed, 41 insertions, 7 deletions
diff --git a/config/security/securityConfig.go b/config/security/securityConfig.go index 66e89fb97..f7d2beac8 100644 --- a/config/security/securityConfig.go +++ b/config/security/securityConfig.go @@ -88,6 +88,9 @@ type HTTP struct { // HTTP methods to allow. Methods Whitelist `json:"methods"` + + // Media types where the Content-Type in the response is used instead of resolving from the file content. + MediaTypes Whitelist `json:"mediaTypes"` } // ToTOML converts c to TOML with [security] as the root. diff --git a/config/security/securityConfig_test.go b/config/security/securityConfig_test.go index 55409e318..edc1737e3 100644 --- a/config/security/securityConfig_test.go +++ b/config/security/securityConfig_test.go @@ -163,8 +163,10 @@ func TestDecodeConfigDefault(t *testing.T) { c.Assert(pc.HTTP.Methods.Accept("GET"), qt.IsTrue) c.Assert(pc.HTTP.Methods.Accept("get"), qt.IsTrue) c.Assert(pc.HTTP.Methods.Accept("DELETE"), qt.IsFalse) + c.Assert(pc.HTTP.MediaTypes.Accept("application/msword"), qt.IsFalse) c.Assert(pc.Exec.OsEnv.Accept("PATH"), qt.IsTrue) c.Assert(pc.Exec.OsEnv.Accept("GOROOT"), qt.IsTrue) c.Assert(pc.Exec.OsEnv.Accept("MYSECRET"), qt.IsFalse) + } diff --git a/hugolib/securitypolicies_test.go b/hugolib/securitypolicies_test.go index aa062bb1f..5b9267b59 100644 --- a/hugolib/securitypolicies_test.go +++ b/hugolib/securitypolicies_test.go @@ -138,9 +138,9 @@ func TestSecurityPolicies(t *testing.T) { } cb := func(b *sitesBuilder) { b.WithConfigFile("toml", ` - [security] - [security.exec] - allow="none" +[security] +[security.exec] +allow="none" `) b.WithTemplatesAdded("index.html", `{{ $scss := "body { color: #333; }" | resources.FromString "foo.scss" | resources.ToCSS (dict "transpiler" "dartsass") }}`) @@ -170,6 +170,28 @@ urls="none" }) }) + c.Run("resources.GetRemote, fake JSON", func(c *qt.C) { + c.Parallel() + httpTestVariant(c, `{{ $json := resources.GetRemote "%[1]s/fakejson.json" }}{{ $json.Content }}`, `(?s).*failed to resolve media type.*`, + func(b *sitesBuilder) { + b.WithConfigFile("toml", ` +`) + }) + }) + + c.Run("resources.GetRemote, fake JSON whitelisted", func(c *qt.C) { + c.Parallel() + httpTestVariant(c, `{{ $json := resources.GetRemote "%[1]s/fakejson.json" }}{{ $json.Content }}`, ``, + func(b *sitesBuilder) { + b.WithConfigFile("toml", ` +[security] +[security.http] +mediaTypes=["application/json"] + +`) + }) + }) + c.Run("getJSON, OK", func(c *qt.C) { c.Parallel() httpTestVariant(c, `{{ $json := getJSON "%[1]s/fruits.json" }}{{ $json.Content }}`, "", nil) diff --git a/hugolib/testdata/fakejson.json b/hugolib/testdata/fakejson.json Binary files differnew file mode 100644 index 000000000..f191b280c --- /dev/null +++ b/hugolib/testdata/fakejson.json diff --git a/resources/resource_factories/create/remote.go b/resources/resource_factories/create/remote.go index 3aae57e8d..73171e570 100644 --- a/resources/resource_factories/create/remote.go +++ b/resources/resource_factories/create/remote.go @@ -171,10 +171,17 @@ func (c *Client) FromRemote(uri string, optionsm map[string]any) (resource.Resou contentType := res.Header.Get("Content-Type") - if isHeadMethod { - // We have no body to work with, so we need to use the Content-Type header. - mediaType, _ = media.FromString(contentType) - } else { + // For HEAD requests we have no body to work with, so we need to use the Content-Type header. + if isHeadMethod || c.rs.ExecHelper.Sec().HTTP.MediaTypes.Accept(contentType) { + var found bool + mediaType, found = c.rs.MediaTypes().GetByType(contentType) + if !found { + // A media type not configured in Hugo, just create one from the content type string. + mediaType, _ = media.FromString(contentType) + } + } + + if mediaType.IsZero() { var extensionHints []string |