From 2637b4ef4dbb3f8d3e537f900bdd072b4078c87e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Pedersen?= Date: Sat, 20 May 2023 17:37:04 +0200 Subject: [PATCH] Allow whitelisting mediaTypes used in resources.GetRemote Fixes #10286 --- config/security/securityConfig.go | 3 ++ config/security/securityConfig_test.go | 2 ++ hugolib/securitypolicies_test.go | 28 ++++++++++++++++-- hugolib/testdata/fakejson.json | Bin 0 -> 42 bytes resources/resource_factories/create/remote.go | 15 +++++++--- 5 files changed, 41 insertions(+), 7 deletions(-) create mode 100644 hugolib/testdata/fakejson.json 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") }}`) @@ -166,6 +166,28 @@ func TestSecurityPolicies(t *testing.T) { [security] [security.http] 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"] + `) }) }) diff --git a/hugolib/testdata/fakejson.json b/hugolib/testdata/fakejson.json new file mode 100644 index 0000000000000000000000000000000000000000..f191b280ce91e6cb8c387735c10ef9bc5da6c83b GIT binary patch literal 42 ocmZ?wbhEHbWMp7uXkY+=|Ns9h{$ybUF?B!$NQQxl(S^Yp0J!f4_W%F@ literal 0 HcmV?d00001 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