[AAP-78700] Add field level validations for source path traversal (#16637)

* Add field level validations for source path traversal

* Reject absolute UNC and drive-qualified paths

* Remove absolute path check
This commit is contained in:
Pratyush Bhandari
2026-09-10 16:23:08 +02:00
committed by GitHub
parent 94333d005e
commit fcd7003510
4 changed files with 159 additions and 1 deletions
+10 -1
View File
@@ -128,7 +128,7 @@ from awx.api.versioning import reverse
from awx.api.fields import BooleanNullField, CharNullField, ChoiceNullField, VerbatimField, DeprecatedCredentialField
# AWX Utils
from awx.api.validators import HostnameRegexValidator
from awx.api.validators import HostnameRegexValidator, contains_path_traversal
logger = logging.getLogger('awx.api.serializers')
@@ -2350,6 +2350,15 @@ class InventorySourceOptionsSerializer(BaseSerializer):
res['credential'] = self.reverse('api:credential_detail', kwargs={'pk': obj.credential})
return res
def validate_source_path(self, value):
# Unchanged values on update are grandfathered so pre-existing traversal
# paths are not rejected until they are edited (AAP-78700).
if self.instance is not None and getattr(self.instance, 'source_path', None) == value:
return value
if contains_path_traversal(value):
raise serializers.ValidationError(_("Enter a path that does not include '..' path segments."))
return value
def validate_source_vars(self, value):
ret = vars_validate_or_raise(value)
for env_k in parse_yaml_or_json(value):
+12
View File
@@ -4,6 +4,18 @@ from django.core.validators import RegexValidator, validate_ipv46_address
from django.core.exceptions import ValidationError
def contains_path_traversal(value):
"""Return True if value contains a '..' path segment.
Matches POSIX (`../`) and Windows (`..\\`) traversal. A file name that
merely contains two dots (e.g. `backup..yml`) is not traversal.
Absolute paths are allowed; they are not parent-directory traversal.
"""
if not isinstance(value, str) or not value:
return False
return any(part == '..' for part in value.replace('\\', '/').split('/'))
class HostnameRegexValidator(RegexValidator):
"""
Fully validates a domain name that is compliant with norms in Linux/RHEL