diff --git a/internal/lang/funcs/filesystem.go b/internal/lang/funcs/filesystem.go index 4092cd504607..2257d5d91c1b 100644 --- a/internal/lang/funcs/filesystem.go +++ b/internal/lang/funcs/filesystem.go @@ -72,20 +72,21 @@ func MakeFileFunc(baseDir string, encBase64 bool) function.Function { // the templatefile function, since that would risk the same file being // included into itself indefinitely. func MakeTemplateFileFunc(baseDir string, funcsCb func() (funcs map[string]function.Function, fsFuncs collections.Set[string], templateFuncs collections.Set[string])) function.Function { - loadTmpl := func(fn string, marks cty.ValueMarks) (hcl.Expression, error) { + loadTmpl := func(fn string, marks cty.ValueMarks) (hcl.Expression, cty.ValueMarks, error) { // We re-use File here to ensure the same filename interpretation // as it does, along with its other safety checks. tmplVal, err := File(baseDir, cty.StringVal(fn).WithMarks(marks)) if err != nil { - return nil, err + return nil, nil, err } + tmplVal, marks = tmplVal.Unmark() expr, diags := hclsyntax.ParseTemplate([]byte(tmplVal.AsString()), fn, hcl.Pos{Line: 1, Column: 1}) if diags.HasErrors() { - return nil, diags + return nil, nil, diags } - return expr, nil + return expr, marks, nil } renderTmpl := makeRenderTemplateFunc(funcsCb, true) @@ -112,7 +113,7 @@ func MakeTemplateFileFunc(baseDir string, funcsCb func() (funcs map[string]funct // return any type. pathArg, pathMarks := args[0].Unmark() - expr, err := loadTmpl(pathArg.AsString(), pathMarks) + expr, _, err := loadTmpl(pathArg.AsString(), pathMarks) if err != nil { return cty.DynamicPseudoType, err } @@ -124,12 +125,12 @@ func MakeTemplateFileFunc(baseDir string, funcsCb func() (funcs map[string]funct }, Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) { pathArg, pathMarks := args[0].Unmark() - expr, err := loadTmpl(pathArg.AsString(), pathMarks) + expr, tmplMarks, err := loadTmpl(pathArg.AsString(), pathMarks) if err != nil { return cty.DynamicVal, err } result, err := renderTmpl(expr, args[1]) - return result.WithMarks(pathMarks), err + return result.WithMarks(tmplMarks), err }, }) diff --git a/internal/lang/funcs/filesystem_test.go b/internal/lang/funcs/filesystem_test.go index cab8f2797615..4b65560fa01e 100644 --- a/internal/lang/funcs/filesystem_test.go +++ b/internal/lang/funcs/filesystem_test.go @@ -187,6 +187,18 @@ func TestTemplateFile(t *testing.T) { cty.True, // since this template contains only an interpolation, its true value shines through ``, }, + { + // If the template filename is sensitive then we also treat the + // rendered result as sensitive, because the rendered result + // is likely to imply which filename was used. + // (Sensitive filenames seem pretty unlikely, but if they do + // crop up then we should handle them consistently with our + // usual sensitivity rules.) + cty.StringVal("testdata/hello.txt").Mark(marks.Sensitive), + cty.EmptyObjectVal, + cty.StringVal("Hello World").Mark(marks.Sensitive), + ``, + }, } funcs := map[string]function.Function{