From 9b38e0eb5c5704e1bc11015e1be35506ae388b84 Mon Sep 17 00:00:00 2001 From: Lucas Bajolet Date: Thu, 9 May 2024 11:30:06 -0400 Subject: [PATCH] addrs: limit source component length to 16 When specifying/installing plugins, a source URI is required for Packer to be able to locate or install a plugin to the local plugin hierarchy. The plugin hierarchy is based on the plugin source, where each component in this hierarchy will become a directory. In order to avoid sources with too many levels of nesting, causing a lot of mkdirs, we limit the number of sources to 16 in this commit, this should be long enough for most of our users. --- hcl2template/addrs/plugin.go | 17 +++++++++++++++-- hcl2template/addrs/plugin_test.go | 2 ++ packer/plugin-getter/plugins.go | 17 ++++++++++++++++- 3 files changed, 33 insertions(+), 3 deletions(-) diff --git a/hcl2template/addrs/plugin.go b/hcl2template/addrs/plugin.go index 2baae5703..9e5dd9356 100644 --- a/hcl2template/addrs/plugin.go +++ b/hcl2template/addrs/plugin.go @@ -218,7 +218,20 @@ func ParsePluginSourceString(str string) (*Plugin, hcl.Diagnostics) { }) } - return &Plugin{ + plug := &Plugin{ Source: str, - }, diags + } + if len(plug.Parts()) > 16 { + return nil, diags.Append(&hcl.Diagnostic{ + Severity: hcl.DiagError, + Summary: "Too many parts to source URL", + Detail: fmt.Sprintf("The source URL must have at most 16 components, and the one provided has %d.\n"+ + "This is unsupported by Packer, please consider using a source that has less components to it.\n"+ + "If this is a blocking issue for you, please open an issue to ask for supporting more "+ + "components to the source URI.", + len(plug.Parts())), + }) + } + + return plug, diags } diff --git a/hcl2template/addrs/plugin_test.go b/hcl2template/addrs/plugin_test.go index 60af038be..199169811 100644 --- a/hcl2template/addrs/plugin_test.go +++ b/hcl2template/addrs/plugin_test.go @@ -20,6 +20,7 @@ func TestPluginParseSourceString(t *testing.T) { {"invalid: only one component, rejected", "potato", nil, true}, {"valid: two components in name", "hashicorp/azr", &Plugin{"hashicorp/azr"}, false}, {"valid: three components, nothing superfluous", "github.com/hashicorp/azr", &Plugin{"github.com/hashicorp/azr"}, false}, + {"valid: 16 components, nothing superfluous", "github.com/hashicorp/azr/a/b/c/d/e/f/g/h/i/j/k/l/m", &Plugin{"github.com/hashicorp/azr/a/b/c/d/e/f/g/h/i/j/k/l/m"}, false}, {"invalid: trailing slash", "github.com/hashicorp/azr/", nil, true}, {"invalid: reject because scheme specified", "https://github.com/hashicorp/azr", nil, true}, {"invalid: reject because query non nil", "github.com/hashicorp/azr?arg=1", nil, true}, @@ -28,6 +29,7 @@ func TestPluginParseSourceString(t *testing.T) { {"invalid: leading slashes are removed", "/github.com/hashicorp/azr", nil, true}, {"invalid: plugin name contains packer-", "/github.com/hashicorp/packer-azr", nil, true}, {"invalid: plugin name contains packer-plugin-", "/github.com/hashicorp/packer-plugin-azr", nil, true}, + {"invalid: 17 components, too many parts to URL", "github.com/hashicorp/azr/a/b/c/d/e/f/g/h/i/j/k/l/m/n", nil, true}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/packer/plugin-getter/plugins.go b/packer/plugin-getter/plugins.go index 9813e35af..ef84d6f0e 100644 --- a/packer/plugin-getter/plugins.go +++ b/packer/plugin-getter/plugins.go @@ -182,7 +182,22 @@ func (pr Requirement) getPluginBinaries(opts ListInstallationsOptions) ([]string return nil, err } - return matches, err + retMatches := make([]string, 0, len(matches)) + // Don't keep plugins that are nested too deep in the hierarchy + for _, match := range matches { + dir := strings.Replace(filepath.Dir(match), opts.PluginDirectory, "", 1) + parts := strings.FieldsFunc(dir, func(r rune) bool { + return r == '/' + }) + if len(parts) > 16 { + log.Printf("[WARN] plugin %q ignored, too many levels of depth: %d (max 16)", match, len(parts)) + continue + } + + retMatches = append(retMatches, match) + } + + return retMatches, err } // ListInstallations lists unique installed versions of plugin Requirement pr