diff --git a/pkg/policies/policies.go b/pkg/policies/policies.go index bb58ac983..909f2061b 100644 --- a/pkg/policies/policies.go +++ b/pkg/policies/policies.go @@ -773,22 +773,19 @@ func getInputArguments(inputs map[string]string) map[string]any { args := make(map[string]any) for k, v := range inputs { - // scan for multiple values + // Normalize consistently: split on newlines first (multi-value inputs, + // e.g. a comma-separated contract value merged with runtime values by + // mergeRuntimeInputs), then split each line on commas. Doing both means a + // comma-separated segment is always expanded into separate values, + // regardless of whether it arrived as a single line or as one of several + // merged lines. lines := strings.Split(strings.TrimRight(v, "\n"), "\n") - value := getValue(lines) - - if value == nil { - continue - } - s, ok := value.(string) - if !ok { - // case for multivalued argument - args[k] = value + values := make([]string, 0, len(lines)) + for _, line := range lines { + values = append(values, splitArgs(line)...) } - // Single string, let's check for CSV and escaped commas `\,` - lines = splitArgs(s) - value = getValue(lines) + value := getValue(values) if value == nil { continue } diff --git a/pkg/policies/policies_test.go b/pkg/policies/policies_test.go index 723993c2d..85fbe3042 100644 --- a/pkg/policies/policies_test.go +++ b/pkg/policies/policies_test.go @@ -799,6 +799,33 @@ func (s *testSuite) TestGetInputArguments() { inputs: map[string]string{"foo": "\n\n\nbar1\nbar2\n\nbar3\n"}, expected: map[string]any{"foo": []string{"bar1", "bar2", "bar3"}}, }, + { + // A comma-separated contract value merged with runtime values (which + // mergeRuntimeInputs joins with newlines) must still split the + // comma-joined line into separate values instead of collapsing it into + // a single literal glob containing commas. + name: "multiline input where a line is comma-separated", + inputs: map[string]string{"foo": "**/vendor/**,**/redist/**\nC:/a\nC:/b"}, + expected: map[string]any{"foo": []string{"**/vendor/**", "**/redist/**", "C:/a", "C:/b"}}, + }, + { + name: "multiline input where several lines are comma-separated", + inputs: map[string]string{"foo": "a,b\nc,d\ne"}, + expected: map[string]any{"foo": []string{"a", "b", "c", "d", "e"}}, + }, + { + name: "multiline input with escaped comma on a line", + inputs: map[string]string{"foo": "a\\,b,c\nd"}, + expected: map[string]any{"foo": []string{"a,b", "c", "d"}}, + }, + { + // A multiline input that reduces to a single non-empty value after + // blank-line filtering must return a plain string, not a one-element + // slice, so the two-stage split never over-wraps single values. + name: "multiline input collapsing to a single value", + inputs: map[string]string{"foo": "\nbar\n"}, + expected: map[string]any{"foo": "bar"}, + }, { name: "no input", inputs: nil,