diff --git a/netbox/utilities/forms/utils.py b/netbox/utilities/forms/utils.py index 8675f295f..9f32491c2 100644 --- a/netbox/utilities/forms/utils.py +++ b/netbox/utilities/forms/utils.py @@ -198,8 +198,12 @@ def parse_csv(reader): header = header.strip() if '.' in header: field, to_field = header.split('.', 1) + if field in headers: + raise forms.ValidationError(f'Duplicate or conflicting column header for "{field}"') headers[field] = to_field else: + if header in headers: + raise forms.ValidationError(f'Duplicate or conflicting column header for "{header}"') headers[header] = None # Parse CSV rows into a list of dictionaries mapped from the column headers. diff --git a/netbox/utilities/tests/test_forms.py b/netbox/utilities/tests/test_forms.py index 0f833d4a9..65b6943a0 100644 --- a/netbox/utilities/tests/test_forms.py +++ b/netbox/utilities/tests/test_forms.py @@ -319,6 +319,22 @@ class CSVDataFieldTest(TestCase): with self.assertRaises(forms.ValidationError): self.field.clean(input) + def test_duplicate_header(self): + input = """ + status,status + Active,Active + """ + with self.assertRaisesRegex(forms.ValidationError, 'Duplicate'): + self.field.clean(input) + + def test_duplicate_header_key(self): + input = """ + vrf.name,vrf.rd + Test VRF,123:456 + """ + with self.assertRaisesRegex(forms.ValidationError, 'Duplicate'): + self.field.clean(input) + def test_clean_default_to_field(self): input = """ address,status,vrf.name