Repository navigation
fix(azure_policy): quote-aware [*] detection in field paths - #875
Merged
Anand Krishnamoorthi (anakrish) merged 1 commit intoOct 29, 2026
Conversation
Field paths were searched for `[*]` with plain substring checks, so a quoted key that contains `[*]` (`m['a[*]']`, `items[*]['a[*]']`) was treated as an array wildcard: field conditions, field() and count paths iterated or split at the wrong place, or failed to compile. Add one shared, linear, quote-aware finder (`find_unquoted_wildcard`, `has_unquoted_wildcard` in compiler/utils.rs) and use it at every field-path `[*]` search in the compiler (fields, field(), count bindings, nested-wildcard collection, binding_selects_single_value, alias array-path fallback, metadata). Inside `['...']` / `["..."]` the key runs to the matching quote followed by `]`, with no escaping; so `p['a][*].x[b']` is one quoted key. `split_path_without_wildcards` is now quote-aware too. Count fields must be array aliases: a count field must end with an unquoted `[*]` and must not contain an unclosed quote. Fields such as `items[*].x` or `items[*]['a[*]']` used to be accepted and silently counted `items`; they are now compile errors. Counting over a tag field is also rejected (a tag named `a[*]` used to become a real wildcard). strip_fq_prefix only treats a `/` before the first `[` as the end of the resource-type prefix, so aliases like `labels['a/b']` resolve. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
🟢 Approval recommended
No active review issues block the quoted-key wildcard handling changes.
No open issues 🎉
What changed in this PR
This PR fixes Azure Policy field-path compilation so quoted [*] text is treated as a literal key rather than an array wildcard.
Changes:
- Shares quote-aware wildcard detection across field conditions,
field(), counts, alias resolution, and metadata. - Validates count paths and preserves slashes inside bracketed keys when stripping resource-type prefixes.
- Adds unit tests and paired match/non-match regression cases for quoted keys, aliases, and rejected count shapes.
| File | Description |
|---|---|
tests/azure_policy/cases/quoted_wildcard.yaml |
Covers quoted-key evaluation, count bindings, and invalid count paths. |
tests/azure_policy/cases/aliases_quoted_keys.yaml |
Covers alias resolution with quoted wildcard, bracket, and slash characters. |
tests/azure_policy/aliases/quoted_keys_aliases.json |
Supplies alias fixtures for quoted-key tests. |
src/languages/azure_policy/compiler/utils.rs |
Adds shared quote-aware scanning, path validation, and unit tests. |
src/languages/azure_policy/compiler/metadata.rs |
Flags only unquoted alias wildcards. |
src/languages/azure_policy/compiler/fields.rs |
Uses quote-aware detection for field-value collection. |
src/languages/azure_policy/compiler/expressions.rs |
Corrects field() result wrapping under count bindings. |
src/languages/azure_policy/compiler/count.rs |
Updates wildcard handling and rejects unsupported count paths and tag counts. |
src/languages/azure_policy/compiler/core.rs |
Updates alias fallback detection and preserves bracketed slashes. |
src/languages/azure_policy/compiler/conditions_wildcard.rs |
Uses quote-aware detection for wildcard field conditions. |
Review effort: Balanced
Anand Krishnamoorthi (anakrish)
approved these changes
Oct 29, 2026
Anand Krishnamoorthi (anakrish)
merged commit Oct 29, 2026
6964a23
into
microsoft:main
60 checks passed
This was referenced Oct 30, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Quote-aware
[*]detection in Azure Policy field paths.The compiler used plain substring checks (
contains("[*]"),find("[*]"),split("[*]")) to look for[*]in field paths. So a quoted key containing[*], such asm['a[*]']oritems[*]['a[*]'], was treated as an array wildcard. Depending on where it appeared, field conditions,field()and count paths then iterated the wrong thing, split at the wrong place, or failed to compile with "unclosed bracket".What changed:
One shared finder.
find_unquoted_wildcard/has_unquoted_wildcardincompiler/utils.rsare a single linear scan. They are used at every[*]search on a field path in the compiler:field();binding_selects_single_value;metadata.split_path_without_wildcardsis quote-aware too.Quoting rule (documented and pinned by tests). A bracket whose first non-whitespace character is
'or"is a quoted key. The key runs to the matching quote followed by], and there is no escaping. Sop['a][*].x[b']is one quoted key and contains no wildcard. If the quote never closes, the bracket is read as unquoted text, which is main's behaviour.strip_fq_prefix. Only a/before the first[now ends the resource-type prefix, so aliases such aslabels['a/b']resolve. Before,rfind('/')landed inside the quoted key.Behaviour changes
[*](trailing whitespace is allowed), and it must not contain an unclosed quote.items[*].xanditems[*]['a[*]']are now compile errors. On main they compiled and silently counteditems.count.field"must be an array alias".[*], as intags['a[*]']ortags.a[*]. In that case the quotes were lost and the tag name became a real wildcard overtags.a.tags['x'][*]is an ordinary path and still counts.Tests
tests/azure_policy/cases/quoted_wildcard.yamlandaliases_quoted_keys.yaml(withaliases/quoted_keys_aliases.json). Every match case has a non-match twin. They cover:[*]after a real wildcard;greater: 0;field()under a count binding;]and/inside quotes;a[*];ensure_count_field_path, and the raw-fallbackstrip_fq_prefixsite.Deferred findings
defaultPathon.and inserts literal keys, so a renamed alias with any bracketed key (renamed['ab'], not only quoted[*]) evaluates to Undefined. This is pre-existing and is tracked as follow-up item (bracket-aware alias normalizer/denormalizer).[ * ]with spaces: this PR keeps main's reading, where it is a key, not a wildcard. An exact[*], a linear bracket parse, and nested-count prefix joining with a bracket collection are handled by the count-bracket-suffix work, and will be reconciled when the two are rebased together.[*]check inclassify_field. It overlaps the tag-whitespace work and will be handled there or in the dynamic-tag-fields follow-up.tokenize_path(dynamicconcat()field paths) is not quote-aware. Deferred to the dynamic-tag-fields follow-up.Dependencies: none; this is based on main.