]> git.maquefel.me Git - brevno-suite/hugo/commitdiff
Don't panic on invalid security whitelist regexp
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Wed, 28 Jun 2023 06:56:35 +0000 (08:56 +0200)
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Wed, 28 Jun 2023 06:57:28 +0000 (08:57 +0200)
Fixes #11176

config/security/securityConfig.go
config/security/whitelist.go
config/security/whitelist_test.go
hugolib/integrationtest_builder.go
hugolib/testhelpers_test.go
markup/pandoc/convert_test.go
markup/rst/convert_test.go

index 5d0db2fb94053ffc38bc75db020a57733726b61a..3d17b7a480638a9f1c9d3c7c39d40963da7af971 100644 (file)
@@ -34,7 +34,7 @@ const securityConfigKey = "security"
 // DefaultConfig holds the default security policy.
 var DefaultConfig = Config{
        Exec: Exec{
-               Allow: NewWhitelist(
+               Allow: MustNewWhitelist(
                        "^(dart-)?sass(-embedded)?$", // sass, dart-sass, dart-sass-embedded.
                        "^go$",                       // for Go Modules
                        "^npx$",                      // used by all Node tools (Babel, PostCSS).
@@ -42,14 +42,14 @@ var DefaultConfig = Config{
                ),
                // These have been tested to work with Hugo's external programs
                // on Windows, Linux and MacOS.
-               OsEnv: NewWhitelist(`(?i)^((HTTPS?|NO)_PROXY|PATH(EXT)?|APPDATA|TE?MP|TERM|GO\w+)$`),
+               OsEnv: MustNewWhitelist(`(?i)^((HTTPS?|NO)_PROXY|PATH(EXT)?|APPDATA|TE?MP|TERM|GO\w+)$`),
        },
        Funcs: Funcs{
-               Getenv: NewWhitelist("^HUGO_", "^CI$"),
+               Getenv: MustNewWhitelist("^HUGO_", "^CI$"),
        },
        HTTP: HTTP{
-               URLs:    NewWhitelist(".*"),
-               Methods: NewWhitelist("(?i)GET|POST"),
+               URLs:    MustNewWhitelist(".*"),
+               Methods: MustNewWhitelist("(?i)GET|POST"),
        },
 }
 
@@ -221,7 +221,7 @@ func stringSliceToWhitelistHook() mapstructure.DecodeHookFuncType {
 
                wl := types.ToStringSlicePreserveString(data)
 
-               return NewWhitelist(wl...), nil
+               return NewWhitelist(wl...)
 
        }
 }
index 72a80da2e236f8e583611845591d51ecb82aa261..92eb3102f5984877de6b96be7996f3d8fac0a38f 100644 (file)
@@ -45,9 +45,9 @@ func (w Whitelist) MarshalJSON() ([]byte, error) {
 // NewWhitelist creates a new Whitelist from zero or more patterns.
 // An empty patterns list or a pattern with the value 'none' will create
 // a whitelist that will Accept none.
-func NewWhitelist(patterns ...string) Whitelist {
+func NewWhitelist(patterns ...string) (Whitelist, error) {
        if len(patterns) == 0 {
-               return Whitelist{acceptNone: true}
+               return Whitelist{acceptNone: true}, nil
        }
 
        var acceptSome bool
@@ -68,7 +68,7 @@ func NewWhitelist(patterns ...string) Whitelist {
        if !acceptSome {
                return Whitelist{
                        acceptNone: true,
-               }
+               }, nil
        }
 
        var patternsr []*regexp.Regexp
@@ -78,10 +78,23 @@ func NewWhitelist(patterns ...string) Whitelist {
                if p == "" {
                        continue
                }
-               patternsr = append(patternsr, regexp.MustCompile(p))
+               re, err := regexp.Compile(p)
+               if err != nil {
+                       return Whitelist{}, fmt.Errorf("failed to compile whitelist pattern %q: %w", p, err)
+               }
+               patternsr = append(patternsr, re)
        }
 
-       return Whitelist{patterns: patternsr, patternsStrings: patternsStrings}
+       return Whitelist{patterns: patternsr, patternsStrings: patternsStrings}, nil
+}
+
+// MustNewWhitelist creates a new Whitelist from zero or more patterns and panics on error.
+func MustNewWhitelist(patterns ...string) Whitelist {
+       w, err := NewWhitelist(patterns...)
+       if err != nil {
+               panic(err)
+       }
+       return w
 }
 
 // Accept reports whether name is whitelisted.
index 5c4196dff2115959b9dc4803386428b6526ec9a6..89d1bc2b109bc291e581cd01059953ac6d113678 100644 (file)
@@ -24,21 +24,21 @@ func TestWhitelist(t *testing.T) {
        c := qt.New(t)
 
        c.Run("none", func(c *qt.C) {
-               c.Assert(NewWhitelist("none", "foo").Accept("foo"), qt.IsFalse)
-               c.Assert(NewWhitelist().Accept("foo"), qt.IsFalse)
-               c.Assert(NewWhitelist("").Accept("foo"), qt.IsFalse)
-               c.Assert(NewWhitelist("  ", " ").Accept("foo"), qt.IsFalse)
+               c.Assert(MustNewWhitelist("none", "foo").Accept("foo"), qt.IsFalse)
+               c.Assert(MustNewWhitelist().Accept("foo"), qt.IsFalse)
+               c.Assert(MustNewWhitelist("").Accept("foo"), qt.IsFalse)
+               c.Assert(MustNewWhitelist("  ", " ").Accept("foo"), qt.IsFalse)
                c.Assert(Whitelist{}.Accept("foo"), qt.IsFalse)
        })
 
        c.Run("One", func(c *qt.C) {
-               w := NewWhitelist("^foo.*")
+               w := MustNewWhitelist("^foo.*")
                c.Assert(w.Accept("foo"), qt.IsTrue)
                c.Assert(w.Accept("mfoo"), qt.IsFalse)
        })
 
        c.Run("Multiple", func(c *qt.C) {
-               w := NewWhitelist("^foo.*", "^bar.*")
+               w := MustNewWhitelist("^foo.*", "^bar.*")
                c.Assert(w.Accept("foo"), qt.IsTrue)
                c.Assert(w.Accept("bar"), qt.IsTrue)
                c.Assert(w.Accept("mbar"), qt.IsFalse)
index cb34cb28b63eb6106557a2fbe1370adc234fe5a0..9c40fa7d02e87c408891cecbd5e1fc277cc97845 100644 (file)
@@ -381,7 +381,8 @@ func (s *IntegrationTestBuilder) initBuilder() error {
                        s.Assert(os.Chdir(s.Cfg.WorkingDir), qt.IsNil)
                        s.C.Cleanup(func() { os.Chdir(wd) })
                        sc := security.DefaultConfig
-                       sc.Exec.Allow = security.NewWhitelist("npm")
+                       sc.Exec.Allow, err = security.NewWhitelist("npm")
+                       s.Assert(err, qt.IsNil)
                        ex := hexec.New(sc)
                        command, err := ex.New("npm", "install")
                        s.Assert(err, qt.IsNil)
index e1fd537a8fda4fd86a543a77641ea5ad5863c0ee..73920bd49f6656c1c3265ebc6db7e87b9ae05baf 100644 (file)
@@ -834,7 +834,9 @@ func (s *sitesBuilder) GetPageRel(p page.Page, ref string) page.Page {
 
 func (s *sitesBuilder) NpmInstall() hexec.Runner {
        sc := security.DefaultConfig
-       sc.Exec.Allow = security.NewWhitelist("npm")
+       var err error
+       sc.Exec.Allow, err = security.NewWhitelist("npm")
+       s.Assert(err, qt.IsNil)
        ex := hexec.New(sc)
        command, err := ex.New("npm", "install")
        s.Assert(err, qt.IsNil)
index 6a1535946c52c11e43ad9aca99a9bd3b706a83df..dec30c4102db7384d4edfb432642b5e00df1cb35 100644 (file)
@@ -31,7 +31,9 @@ func TestConvert(t *testing.T) {
        }
        c := qt.New(t)
        sc := security.DefaultConfig
-       sc.Exec.Allow = security.NewWhitelist("pandoc")
+       var err error
+       sc.Exec.Allow, err = security.NewWhitelist("pandoc")
+       c.Assert(err, qt.IsNil)
        p, err := Provider.New(converter.ProviderConfig{Exec: hexec.New(sc), Logger: loggers.NewDefault()})
        c.Assert(err, qt.IsNil)
        conv, err := p.New(converter.DocumentContext{})
index 9e98d0405c5d08301c267f0c9920a3b9136663bf..1897e650f2649addfdea367285fc0e76388681ad 100644 (file)
@@ -31,7 +31,7 @@ func TestConvert(t *testing.T) {
        }
        c := qt.New(t)
        sc := security.DefaultConfig
-       sc.Exec.Allow = security.NewWhitelist("rst", "python")
+       sc.Exec.Allow = security.MustNewWhitelist("rst", "python")
 
        p, err := Provider.New(
                converter.ProviderConfig{