Summary
newPolicyConfig declares var registry string but never assigns it, so the "all plugin configs must have the same registry" validation can never fire. Policy plugin configs mixing registries (e.g. a private BSR plus buf.build) are accepted silently — exactly the configuration this check was written to reject.
Reproduction
# buf.policy.yaml
version: v2
plugins:
- plugin: buf.build/acme/lint-plugin
- plugin: registry.corp.example.com/acme/other-plugin
Expected: all plugin configs must have the same registry, got "buf.build" and "registry.corp.example.com". Actual: accepted.
Root cause
private/bufpkg/bufpolicy/policy_config.go:221-232:
var registry string
for _, pluginConfig := range pluginConfigs {
ref := pluginConfig.Ref()
if ref == nil {
continue
}
if ref.FullName().Registry() == "" {
return nil, syserror.Newf(...)
}
if registry != "" && ref.FullName().Registry() != registry { // always false
return nil, fmt.Errorf("all plugin configs must have the same registry, ...")
}
}
registry = ref.FullName().Registry() is missing from the loop body, so the guard short-circuits forever.
Consequence
Beyond the missing error: marshalPolicyConfigAsJSON stores plugins as owner/plugin/ref without registry for the O1 digest, and unmarshalJSONPolicyConfig(registry, ...) re-anchors every plugin to a single registry — so a mixed-registry config digests identically to a single-registry one and round-trips to the wrong plugin identity.
Found via a full mutest (mutation-testing) run over this repo (the !=→== mutant at line 229 survived because the branch is unreachable); verified by source inspection.
Summary
newPolicyConfigdeclaresvar registry stringbut never assigns it, so the "all plugin configs must have the same registry" validation can never fire. Policy plugin configs mixing registries (e.g. a private BSR plus buf.build) are accepted silently — exactly the configuration this check was written to reject.Reproduction
Expected:
all plugin configs must have the same registry, got "buf.build" and "registry.corp.example.com". Actual: accepted.Root cause
private/bufpkg/bufpolicy/policy_config.go:221-232:registry = ref.FullName().Registry()is missing from the loop body, so the guard short-circuits forever.Consequence
Beyond the missing error:
marshalPolicyConfigAsJSONstores plugins as owner/plugin/ref without registry for the O1 digest, andunmarshalJSONPolicyConfig(registry, ...)re-anchors every plugin to a single registry — so a mixed-registry config digests identically to a single-registry one and round-trips to the wrong plugin identity.Found via a full mutest (mutation-testing) run over this repo (the
!=→==mutant at line 229 survived because the branch is unreachable); verified by source inspection.