Azure / Azure/PSRule.Rules.Azure
Export-AzRuleData can exit silently with no output: unreachable context guard, StrictMode filter aborts all contexts, bare return
- Dominant language
- PowerShell
- Stars
- 447
- Forks
- 109
- Avg merge
- 2d 19h
- Merged PRs (30d)
- 23
Description
## Summary
Three defects in `PSRule.Rules.Azure.psm1` compose so that `Export-AzRuleData` can exit **successfully, silently, and with no output** when the Azure context is missing or partially malformed. Downstream that becomes a clean, empty scan — a false negative on a security tool, which is the worst failure mode for this kind of check.
Verified against `main` (`src/PSRule.Rules.Azure/PSRule.Rules.Azure.psm1`) at time of filing. Line numbers are from that file.
## 1. Unreachable guard in `FindAzureContext` (line 703)
```powershell
$context = @(GetAzureContext -ListAvailable:$listAvailable);
if ($Null -eq $context -and $context.Length -gt 0) {
Write-Error -Message 'Could not find an existing context. Use Connect-AzAccount to establish a PowerShell context with Azure.';
return;
}
```
`$context` is wrapped in `@(...)`, so it is always an array and never `$null`. `$Null -eq $context` is therefore always `$false`, `-and` short-circuits, and the body is unreachable. The condition is also self-contradictory as written: it requires `$context` to be null *and* to have a positive length.
The actionable "Use Connect-AzAccount" error can never be emitted. The intent looks like:
```powershell
if ($Null -eq $context -or $context.Length -eq 0) {
```
## 2. Whole filter pipeline inside one `try`, under `Set-StrictMode -Version latest` (lines 708-726)
The module sets `Set-StrictMode -Version latest` at line 8. `FindAzureContext` then does:
```powershell
try {
$filteredContext = @($context | ForEach-Object -Process {
if (
($Null -eq $Tenant -or $Tenant.Length -eq 0 -or ($_.Tenant.Id -in $Tenant)) -and
($Null -eq $Subscription -or $Subscription.Length -eq 0 -or ($_.Subscription.Id -in $Subscription) -or ($_.Subscription.Name -in $Subscription))
) {
$_;
}
})
...
return $filteredContext;
}
catch {
Write-Error -Message "Failed to filter contexts. Error: $_";
}
```
Under StrictMode, a single context missing `.Tenant` or `.Subscription` throws on property access. Because the `try` spans the entire pipeline *and* `return $filteredContext` sits inside it, that one bad context causes **every** context to be discarded — the function falls into `catch` and returns nothing at all, rather than skipping the offending entry.
Filtering per-item, or narrowing the `try`, would let one malformed context be skipped without destroying the rest.
## 3. Silent bare `return` in `Export-AzRuleData` (lines 86-88)
```powershell
if ($Null -eq $contextSubscriptions -or $contextSubscriptions.Length -eq 0) {
return;
}
```
Nothing is written to the error or warning stream. Combined with (1) and (2), the caller gets a successful exit code and an empty output directory with no diagnostic anywhere.
## Combined effect
1. No usable Azure context, or one malformed context present
2. (2) discards all contexts and returns nothing
3. (1) cannot fire, so the actionable error is never surfaced
4. (3) returns silently, exit code 0, no output
Result: `Export-AzRuleData` reports success and exports nothing, and any downstream PSRule scan over that directory reports a clean result.
## Impact
We hit this in a downstream tool that calls `Export-AzRuleData` and then scans the export directory. Every subscription scan came back clean and empty, with no error at any layer, which is indistinguishable from "no findings". For a security-assessment tool a silent false negative is materially worse than a loud failure.
## Suggested fixes
- Correct the guard to `-or ... -eq 0` so it can actually fire
- Filter contexts per-item so one malformed entry does not discard the whole set, or use StrictMode-safe property access in the filter predicate
- Replace the bare `return` with a `Write-Error` (or at minimum `Write-Warning`) so an empty export is distinguishable from a clean one
Happy to open a PR if the maintainers would like these as one change or three.
## Credit
Found by @haflidif while testing against live Azure tenants, and diagnosed while investigating a downstream report at `martinopedal/azure-analyzer#1215`.
Contributor guide
Assessment
This issue has not been assessed yet.