#7334·kubevela

PolicyDefinition CUE templates are validated without the cuex package set

Author: sakirr05Created Aug 17, 2026Updated Aug 17, 2026

Describe the bug

ComponentDefiniion and TraitDefinition validate their CUE templates with ValidateCuexTemplate, which resolves the cuex package set. PolicyDefinition uses the plain ValidateCueTemplate, which does not:

go
// componentdefinition/component_definition_validating_handler.go:110
webhookutils.ValidateCuexTemplate(ctx, cueTemplate)

// traitdefinition/trait_definition_validating_handler.go:128
webhookutils.ValidateCuexTemplate(ctx, cueTemplate)

// policydefinition/policy_definition_validating_handler.go:96
webhookutils.ValidateCueTemplate(cueTemplate)

So a policy importing an internal provider package is rejected at admission, though the render path compiles it fine. Nothing explains the difference; both helpers sit together in pkg/webhook/utils/utils.go.

There are two call sites, not one. The handler runs a second validator later in the same request, and it has the same problem:

go
// application/policy_validation.go:92, reached from the handler at L131
if err := webhookutils.ValidateCueTemplate(cueTemplate); err != nil {

// application/policy_validation.go:160, same template, global policies only
ctx := cuecontext.New()
value := ctx.CompileString(cueTemplate)

Fixing the handler alone leaves the request denied by the second one.

To Reproduce

yaml
apiVersion: core.oam.dev/v1beta1
kind: PolicyDefinition
metadata:
  name: repro-policy
  namespace: vela-system
spec:
  schematic:
    cue:
      template: |
        import "vela/base64"

        encoded: base64.#Encode & {
          $params: "hello"
        }

Run through the validating handler, observed by adding it as a spec in the policydefinition webhook suite:

builtin package "vela/base64" undefined (requestUID=)

After patching only the handler, the same request fails at the second val

invalid PolicyDefinition: [builtin package "vela/base64" undefined] (requestUID=)

Expected behavior

PolicyDefinition validates like the other two kinds, or the difference documented.

WorkloadCompiler is the compiler to match, not the workflow one: policies are parsed into a Component and evaluated by the workload abstract engine, compiles through it.

go
// appfile/parser.go:550
engine: definition.NewWorkloadAbstractEngine(name),

// cue/definition/template.go:139
val, err := velacuex.WorkloadCompiler.Get().CompileString(ctx.GetCtx(), .

That is what ValidateCuexTemplate already uses, so admission would check what render actually runs.

Worth a test that submits a policy importing a provider package. The exis specs use import-free templates, so they pass either way.

KubeVela Version

Checked against master at [5cf3e3a8](https://github.com/kubevela/kubevela/commit/5cf3e3a80ade9d15 the head at the time of writing.

Cluster information

Not applicable. Admission-time validation, reproduces under envtest.

Additional context

Low impact today: none of the nine bundled policy definitions in vela-templates/definitions/internal/policy/ import anything. A parity g rather than an outage.

One snag for whoever picks it up. ValidateCuexTemplate needs a context, and the second validator has none, so its signature and callers have to chang

go
func ValidatePolicyDefinition(policy *v1beta1.PolicyDefinition) *PolicyValidationResult