summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>2023-05-20 17:37:04 +0200
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>2023-05-20 20:16:45 +0200
commit2637b4ef4dbb3f8d3e537f900bdd072b4078c87e (patch)
tree6b64225d157397befe5a7d0ab7925b8ad0e6ba94
parent7c7baa618325cb3d2b1ef48bdc1f97aae25f62e9 (diff)
Allow whitelisting mediaTypes used in resources.GetRemote
Fixes #10286
-rw-r--r--config/security/securityConfig.go3
-rw-r--r--config/security/securityConfig_test.go2
-rw-r--r--hugolib/securitypolicies_test.go28
-rw-r--r--hugolib/testdata/fakejson.jsonbin0 -> 42 bytes
-rw-r--r--resources/resource_factories/create/remote.go15
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
new file mode 100644
index 000000000..f191b280c
--- /dev/null
+++ b/hugolib/testdata/fakejson.json
Binary files differ
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