Skip to content

fix: guard ref names in billingaccountbinding create policy#69

Open
ecv wants to merge 2 commits into
mainfrom
fix/billingaccountbinding-ref-name-dlq-guard
Open

fix: guard ref names in billingaccountbinding create policy#69
ecv wants to merge 2 commits into
mainfrom
fix/billingaccountbinding-ref-name-dlq-guard

Conversation

@ecv

@ecv ecv commented Jun 27, 2026

Copy link
Copy Markdown

What

Tighten the create-with-refs match in billingaccountbinding-policy.yaml to
require projectRef.name and billingAccountRef.name, the fields its summary
dereferences.

Why

Same DLQ-leak class as milo-os/activity#212. The match guarded only
has(projectRef) / has(billingAccountRef), but the summary derefs their
.name. A create whose refs omit name (rejected by admission, but still
recorded in the audit requestObject) raises CEL no such key: name → event
to DLQ → retries fail.

Fix

Adding the .name leaves to the match routes malformed bindings to the
existing create-fallback rule (created billing account binding <name>)
instead of leaking. Match-based guard, consistent with this file's style.

Remediation

Merge + billing release → the billing-milo-activity-policies Flux
Kustomization re-applies the corrected CR. No kubectl.

Related

The create-with-refs rule matched on has(projectRef) and has(billingAccountRef)
but its summary dereferenced projectRef.name and billingAccountRef.name. A
create whose refs omit name (rejected by admission, but still recorded in the
audit requestObject) raised CEL "no such key: name", sending the event to the
DLQ -- the same leak class as milo-os/activity#212.

Require the .name leaves in the match so malformed bindings fall through to the
create-fallback rule instead of leaking.
create-with-refs reads audit.requestObject.spec refs (always present, safe), but
create-fallback derefs audit.responseObject.metadata.name unconditionally. A
create that misses the refs guard and is rejected returns a Status as
responseObject with no metadata.name, raising "no such key: name" -> DLQ. A
generateName create rejected before naming also has an empty objectRef.name.

Replace with a per-level-guarded fallback chain:
  responseObject.metadata.name -> objectRef.name -> responseObject.details.name -> literal
The details branch is guarded with has(responseObject.details) because some
Status responses carry no details.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@ecv ecv marked this pull request as ready for review June 28, 2026 04:57
@ecv ecv enabled auto-merge June 28, 2026 05:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant