Function Apps on language runtimes past Microsoft's end-of-support floor
What does ZopNight detect here?
Function Apps running a runtime past Microsoft's end-of-support get no security patches. Rule RC-1313 parses the discoverer's runtime value and fires when the version sits below the documented floor: Python 3.10, Node 22, Java 8, .NET 8, PowerShell 7.4. Ambiguous shapes like the Windows dotnet4.0 fallback always abstain.
Signal and threshold
| Field | Value |
|---|---|
| Rule IDs | RC-1313 |
| Category | compliance |
| Severity | high |
| Metric | none — pure configuration read |
| Source | function_runtime.go |
Where it applies
Runtimes past their patch window
A function on a retired runtime keeps executing (Azure does not switch it off), but every CVE published against that language version from retirement day onward stays unfixed underneath your code. The exposure compounds silently: the app that was compliant when deployed becomes a known-vulnerable surface without a single code change, and platform support for it ends too. Severity is high because the risk grows with time, not with any action you take.
Pipe shape versus fallback shape
The only signal available is the discoverer’s runtime metadata, taken from the site’s ARM
FxVersion and written as a lowercased pipe pair: python|3.12, node|20,
dotnetcore|8.0. Only this shape names a real worker stack, so only this shape is judged.
The second shape, a pipe-less dotnet4.0-style string, comes from the netFrameworkVersion
fallback, a property that reads v4.0 on every Windows site, whatever actually runs
there. A Node or PowerShell in-process app looks identical to a .NET Framework one under that
fallback, so the rule treats the shape as unknown-worker and abstains, a hardening added
after a live false positive.
The support floors enforced
Each stack family has a minimum currently-supported version, sourced from Microsoft’s
supported-languages page (last reconciled 2026-07-02): Python 3.10, Node 22, Java 8, .NET 8,
PowerShell 7.4. A parsed version below its family’s floor fires; at or above it, the rule
abstains. Unrecognized stacks (custom, docker, anything without a floor entry) also
abstain rather than being guessed at. These floors roll forward as Microsoft retires
versions, so a finding today can be preceded by silence last quarter on the same app.
Sequencing an upgrade
Runtime upgrades are app-setting changes, but rarely only that: Node major bumps and Python minors both surface dependency breakage, and the .NET path usually means moving to the isolated worker model. Upgrade a staging slot first, run the function’s actual triggers against it, then swap. The slot mechanism exists for precisely this. Check the current value under the Function App’s Environment variables blade before and after.
List runtime stacks across function apps
az functionapp config show -n <app> -g <rg> \ --query "{linux: linuxFxVersion, windows: windowsFxVersion, netFx: netFrameworkVersion}"Compare the reported stack and version against the floors above; a bare netFx value with
both FxVersions empty is the ambiguous Windows case the rule declines to judge.