Input validation / Path traversal in object metadata name

MEDIUM
kubernetes/kubernetes
Commit: 34c63c39c3a4
Affected: <= v1.36.0-beta.0
2026-06-30 15:47 UTC

Description

The commit enhances input validation during object creation by validating the object metadata (metadata.name) through a path-segment validator (validatePathSegment) via genericvalidation.ValidateObjectMetaAccessor. This change aims to prevent malformed or adversarial resource names from slipping through creation validation, addressing potential security or stability issues such as path traversal or invalid resource handling. It also preserves DeclarativeValidation integration. The update also slightly adjusts the validation ordering to ensure object metadata validation runs after initial strategy validation has passed. While Kubernetes names are generally constrained by DNS labeling rules, this patch adds an explicit name/path validation layer at creation time, which tightens security against edge-case or future-name-policy violations.

Proof of Concept

Note: Kubernetes enforces resource naming rules, so attempting to use path-like names in metadata.name is typically rejected by existing validation. This PoC demonstrates the concept of attempting a path-traversal-like name and shows how the fix would reject it. Hypothetical attack scenario (for demonstration in a test environment): 1) Prepare a manifest that tries to set a dangerous metadata.name that includes path traversal segments. 2) Submit the manifest to the API server prior to this fix and observe whether the validation allows the request to proceed into storage logic (potentially leading to unexpected storage paths or behavior). 3) With the patch in place, the API server should reject such an object due to validatePathSegment-based checks on the metadata.name. Example manifest (conceptual; in real clusters Kubernetes validates names strictly, so this would usually be rejected by the API server before storage): apiVersion: v1 kind: ConfigMap metadata: name: "..//..//secret" data: key: value Expected outcome: - Before this patch: the request could bypass path-segment validation and potentially cause improper resource path handling in storage logic (depending on cluster config). - After this patch: the API server rejects the request with a validation error indicating an invalid metadata.name due to path-segment validation.

Commit Details

Author: Lalit Chauhan

Date: 2026-06-18 16:46 UTC

Message:

Compare objectMeta validation errors with DV for Create operation, similar to Update operation

Triage Assessment

Vulnerability Type: Input validation (object metadata name / path traversal potential)

Confidence: MEDIUM

Reasoning:

The patch changes how object metadata is validated during Create, introducing explicit object meta validation and ensuring path-segment validation is applied. This strengthens input validation for resource names in metadata, which can prevent malformed or adversarial names that could lead to security or stability issues (e.g., path traversal or invalid resource handling). It also preserves declarative validation integration. Overall, it addresses input validation that has security implications.

Verification Assessment

Vulnerability Type: Input validation / Path traversal in object metadata name

Confidence: MEDIUM

Affected Versions: <= v1.36.0-beta.0

Code Diff

diff --git a/staging/src/k8s.io/apiserver/pkg/registry/rest/create.go b/staging/src/k8s.io/apiserver/pkg/registry/rest/create.go index 8997fdd832369..faa8d77bc5b3c 100644 --- a/staging/src/k8s.io/apiserver/pkg/registry/rest/create.go +++ b/staging/src/k8s.io/apiserver/pkg/registry/rest/create.go @@ -144,25 +144,26 @@ func BeforeCreate(strategy RESTCreateStrategy, ctx context.Context, obj runtime. // ValidateCreate performs common and strategy-specific validation for a create operation. func ValidateCreate(ctx context.Context, obj runtime.Object, strategy RESTCreateStrategy) field.ErrorList { errs := strategy.Validate(ctx, obj) - if dv, ok := strategy.(DeclarativeValidationStrategy); ok { - errs = dv.ValidateDeclaratively(ctx, obj, nil, errs, operation.Create, dv.DeclarativeValidationConfig(ctx, obj, nil)) - } - if len(errs) > 0 { - return errs - } + if len(errs) == 0 { + objectMeta, err := meta.Accessor(obj) + if err != nil { + return append(errs, field.InternalError(field.NewPath("metadata"), fmt.Errorf("failed to get object metadata: %v", err))) + } - objectMeta, err := meta.Accessor(obj) - if err != nil { - return append(errs, field.InternalError(field.NewPath("metadata"), fmt.Errorf("failed to get object metadata: %w", err))) + // TODO: Replace this check with the ObjectMeta name validation (validatePathSegment) once we are sure that all other validations are covered by strategy.Validate and strategy.ValidateDeclaratively. + + // Custom validation (including name validation) passed + // Now run common validation on object meta + // Do this *after* custom validation so that specific error messages are shown whenever possible + errs = append(errs, genericvalidation.ValidateObjectMetaAccessor(objectMeta, strategy.NamespaceScoped(), validatePathSegment, field.NewPath("metadata"))...) } - // TODO: Replace this check with the ObjectMeta name validation (validatePathSegment) once we are sure that all other validations are covered by strategy.Validate and strategy.ValidateDeclaratively. + if dv, ok := strategy.(DeclarativeValidationStrategy); ok { + errs = dv.ValidateDeclaratively(ctx, obj, nil, errs, operation.Create, dv.DeclarativeValidationConfig(ctx, obj, nil)) + } - // Custom validation (including name validation) passed - // Now run common validation on object meta - // Do this *after* custom validation so that specific error messages are shown whenever possible - return genericvalidation.ValidateObjectMetaAccessor(objectMeta, strategy.NamespaceScoped(), validatePathSegment, field.NewPath("metadata")) + return errs } // CheckGeneratedNameError checks whether an error that occurred creating a resource is due diff --git a/staging/src/k8s.io/apiserver/pkg/registry/rest/update.go b/staging/src/k8s.io/apiserver/pkg/registry/rest/update.go index 80717f79c1965..b66978ca14fc7 100644 --- a/staging/src/k8s.io/apiserver/pkg/registry/rest/update.go +++ b/staging/src/k8s.io/apiserver/pkg/registry/rest/update.go @@ -151,7 +151,6 @@ func BeforeUpdate(strategy RESTUpdateStrategy, ctx context.Context, obj, old run if oldMeta.GetDeletionGracePeriodSeconds() != nil && objectMeta.GetDeletionGracePeriodSeconds() == nil { objectMeta.SetDeletionGracePeriodSeconds(oldMeta.GetDeletionGracePeriodSeconds()) } - // Ensure some common fields, like UID, are validated for all resources. errs := ValidateUpdate(ctx, obj, old, strategy) if len(errs) > 0 { RecordDuplicateValidationErrors(ctx, kind.GroupKind(), errs) @@ -171,6 +170,7 @@ func BeforeUpdate(strategy RESTUpdateStrategy, ctx context.Context, obj, old run func ValidateUpdate(ctx context.Context, obj runtime.Object, old runtime.Object, strategy RESTUpdateStrategy) field.ErrorList { // TODO: Replace this check with the ObjectMeta name validation (validatePathSegment) once we are sure that all other validations are covered by strategy.Validate and strategy.ValidateDeclaratively. + // Ensure some common fields, like UID, are validated for all resources. errs := validateCommonFields(obj, old, strategy) errs = append(errs, strategy.ValidateUpdate(ctx, obj, old)...)
← Back to Alerts View on GitHub →