From 919aa29f151b67d10ca5dc7f0c54eafa9e7838a5 Mon Sep 17 00:00:00 2001 From: fabiobaiao <53570695+fabiobaiao@users.noreply.github.com> Date: Fri, 17 Jul 2026 10:52:59 +0100 Subject: [PATCH] feat: support disabling insecure template functions only (#2689) Signed-off-by: fabiobaiao <53570695+fabiobaiao@users.noreply.github.com> --- pkg/envvar/const.go | 5 +++-- pkg/tmpl/context_funcs.go | 21 +++++++++++---------- pkg/tmpl/context_funcs_test.go | 21 +++++++++++++++++++-- 3 files changed, 33 insertions(+), 14 deletions(-) diff --git a/pkg/envvar/const.go b/pkg/envvar/const.go index 2a79766c..9da13e3a 100644 --- a/pkg/envvar/const.go +++ b/pkg/envvar/const.go @@ -1,8 +1,9 @@ package envvar const ( - DisableInsecureFeatures = "HELMFILE_DISABLE_INSECURE_FEATURES" - DisableHooks = "HELMFILE_DISABLE_HOOKS" + DisableInsecureFeatures = "HELMFILE_DISABLE_INSECURE_FEATURES" + DisableInsecureTemplateFunctions = "HELMFILE_DISABLE_INSECURE_TEMPLATE_FUNCTIONS" + DisableHooks = "HELMFILE_DISABLE_HOOKS" // use helm status to check if a release exists before installing it UseHelmStatusToCheckReleaseExistence = "HELMFILE_USE_HELM_STATUS_TO_CHECK_RELEASE_EXISTENCE" diff --git a/pkg/tmpl/context_funcs.go b/pkg/tmpl/context_funcs.go index c0f1111d..14316ded 100644 --- a/pkg/tmpl/context_funcs.go +++ b/pkg/tmpl/context_funcs.go @@ -24,22 +24,23 @@ import ( type Values = map[string]any -var DisableInsecureFeaturesErr = DisableInsecureFeaturesError{envvar.DisableInsecureFeatures + " is active, insecure function calls are disabled"} +var DisableInsecureFunctionsErr = DisableInsecureFunctionsError{envvar.DisableInsecureFeatures + " or " + envvar.DisableInsecureTemplateFunctions + " is active, insecure function calls are disabled"} -type DisableInsecureFeaturesError struct { +type DisableInsecureFunctionsError struct { err string } -func (e DisableInsecureFeaturesError) Error() string { +func (e DisableInsecureFunctionsError) Error() string { return e.err } var ( - disableInsecureFeatures bool + disableInsecureFeatures, disableInsecureTemplateFunctions bool ) func init() { disableInsecureFeatures, _ = strconv.ParseBool(os.Getenv(envvar.DisableInsecureFeatures)) + disableInsecureTemplateFunctions, _ = strconv.ParseBool(os.Getenv(envvar.DisableInsecureTemplateFunctions)) } func (c *Context) createFuncMap() template.FuncMap { @@ -80,22 +81,22 @@ func (c *Context) createFuncMap() template.FuncMap { return []fs.DirEntry{}, nil } } - if disableInsecureFeatures { + if disableInsecureFeatures || disableInsecureTemplateFunctions { // disable insecure functions funcMap["exec"] = func(string, []any, ...string) (string, error) { - return "", DisableInsecureFeaturesErr + return "", DisableInsecureFunctionsErr } funcMap["envExec"] = func(map[string]any, string, []any, ...string) (string, error) { - return "", DisableInsecureFeaturesErr + return "", DisableInsecureFunctionsErr } funcMap["readFile"] = func(string) (string, error) { - return "", DisableInsecureFeaturesErr + return "", DisableInsecureFunctionsErr } funcMap["readDir"] = func(string) ([]string, error) { - return nil, DisableInsecureFeaturesErr + return nil, DisableInsecureFunctionsErr } funcMap["readDirEntries"] = func(string) ([]string, error) { - return nil, DisableInsecureFeaturesErr + return nil, DisableInsecureFunctionsErr } } diff --git a/pkg/tmpl/context_funcs_test.go b/pkg/tmpl/context_funcs_test.go index a72e39a9..002a6ce4 100644 --- a/pkg/tmpl/context_funcs_test.go +++ b/pkg/tmpl/context_funcs_test.go @@ -38,14 +38,31 @@ func TestCreateFuncMap_DisabledInsecureFeatures(t *testing.T) { funcMaps := ctx.createFuncMap() args := make([]any, 0) _, err1 := funcMaps["exec"].(func(command string, args []any, inputs ...string) (string, error))("ls", args) - require.ErrorIs(t, err1, DisableInsecureFeaturesErr) + require.ErrorIs(t, err1, DisableInsecureFunctionsErr) _, err2 := funcMaps["readFile"].(func(filename string) (string, error))("context_funcs_test.go") - require.ErrorIs(t, err2, DisableInsecureFeaturesErr) + require.ErrorIs(t, err2, DisableInsecureFunctionsErr) } disableInsecureFeatures = currentVal } +func TestCreateFuncMap_DisabledInsecureTemplateFunctions(t *testing.T) { + currentVal := disableInsecureTemplateFunctions + + { + disableInsecureTemplateFunctions = true + ctx := &Context{basePath: "."} + funcMaps := ctx.createFuncMap() + args := make([]any, 0) + _, err1 := funcMaps["exec"].(func(command string, args []any, inputs ...string) (string, error))("ls", args) + require.ErrorIs(t, err1, DisableInsecureFunctionsErr) + _, err2 := funcMaps["readFile"].(func(filename string) (string, error))("context_funcs_test.go") + require.ErrorIs(t, err2, DisableInsecureFunctionsErr) + } + + disableInsecureTemplateFunctions = currentVal +} + func newFSExpecting(expectedFilename string, expected string) *filesystem.FileSystem { return filesystem.FromFileSystem(filesystem.FileSystem{ ReadFile: func(filename string) ([]byte, error) {