Skip to content

fix: accept legacy Azure Resource Manager audience in JWT validation - #203

Open
rootsecdev wants to merge 1 commit into
SpecterOps:mainfrom
rootsecdev:main
Open

fix: accept legacy Azure Resource Manager audience in JWT validation#203
rootsecdev wants to merge 1 commit into
SpecterOps:mainfrom
rootsecdev:main

Conversation

@rootsecdev

@rootsecdev rootsecdev commented Jul 28, 2026

Copy link
Copy Markdown

Problem

--jwt fails with failed to create new Azure client: error: invalid token audience when supplied an ARM access token whose aud claim is https://management.core.windows.net/ rather than https://management.azure.com.

Entra ID issues ARM tokens under either of two registered identifier URIs, and ARM accepts both. ParseAud only trims a trailing slash, so client/client.go:52 and client/rest/auth.go:299 compare the legacy URI against the canonical endpoint and reject a valid token.

az account get-access-token resolves the ARM scope through activeDirectoryResourceId, which is https://management.core.windows.net/ for AzureCloud. Tokens sourced from the Azure CLI including from Cloud Shell, where the token proxy normalizes to that resource ID regardless of the requested scope are rejected outright. Requesting --scope https://management.azure.com/.default explicitly does not reliably change the resulting audience.

Fix

Normalize the legacy identifier URI to the canonical endpoint inside ParseAud. Both audience checks client selection at startup and per-request validation call ParseAud, so a single normalization covers initialization and every outbound request. Without this, a token could pass startup and then fail mid-collection.

Equivalent legacy URIs for US Gov and China are included for parity.

Scope

Only audiences that ARM already treats as equivalent are affected. Any other audience, including Graph, passes through unchanged, so no previously rejected token becomes accepted except the ARM aliases.

Testing

Added client/rest/utils_test.go covering the alias normalization (with and without trailing slash, all three clouds), trailing-slash trimming, unchanged passthrough for Graph and an unrelated audience, and the malformed-token error path.

Verified end-to-end against a real tenant: azurehound list az-rm --jwt with a management.core.windows.net audience fails on main and completes collection with this change. go build ./... and go test ./... pass.

Bonus

Testing and confirming fix through an Azure Cloud Shell session was a bonus as this can evade conditional access policies.

Summary by CodeRabbit

  • Bug Fixes
    • Improved Azure authentication handling by recognizing legacy audience values and converting them to their canonical endpoints.
    • Standardized audience values by removing trailing slashes for more consistent validation.

@github-actions

github-actions Bot commented Jul 28, 2026

Copy link
Copy Markdown

All contributors have signed the CLA ✍️ ✅
Posted by the CLA Assistant Lite bot.

@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 8be3d617-583b-41a9-8745-c21f56f1d04e

📥 Commits

Reviewing files that changed from the base of the PR and between 7092bc6 and ee282c9.

📒 Files selected for processing (1)
  • client/rest/utils.go

Walkthrough

ParseAud now validates and normalizes token audience claims, mapping legacy Azure Resource Manager values to canonical AzureHound comparison endpoints while preserving other trimmed values.

Changes

Audience normalization

Layer / File(s) Summary
Parse and normalize token audiences
client/rest/utils.go
ParseAud validates that aud is a string, trims trailing slashes, and maps legacy ARM audience variants through audAliases.

Estimated code review effort: 2 (Simple) | ~10 minutes

Poem

I’m a bunny with a token to parse,
Trimming old slashes with care and flair.
Legacy hosts hop into line,
Canonical endpoints now shine.
One neat map, and all is well—
Azure audiences ring the bell!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: accepting legacy Azure Resource Manager audiences during JWT validation.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
🔧 Fix failing CI
  • Fix failing CI in branch main

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@rootsecdev

Copy link
Copy Markdown
Author

I have read the CLA Document and I hereby sign the CLA

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