Microsoft Defender for Cloud · Azure Functions
Unused API endpoints should be disabled and removed from Function Apps (Preview)
Written and reviewed by Emnode · Last reviewed
What does the recommendation "Unused API endpoints should be disabled and removed from Function Apps (Preview)" check?
This is a Microsoft Defender for Cloud API security posture recommendation, not a deployable Azure Policy, so there is no policy definition to assign. It is delivered by the Defender CSPM plan with the API security posture management extension enabled, and Function App support is currently in Preview and limited to Premium, Elastic Premium, Dedicated (App Service) and App Service Environment hosting tiers (Consumption tier Function Apps are not supported) and REST APIs only. After a Function App is onboarded through this extension, Defender for Cloud inventories its HTTP-triggered endpoints and flags any that have received no traffic for 30 days, marking them Inactive. The check only inspects HTTP-triggered functions discovered through API security posture telemetry. It does not see timer, queue, blob, Event Grid or Service Bus triggers, it does not evaluate Function Apps that have not been onboarded, and it makes no judgement about authentication or input validation on the endpoints that are still active.
Why does "Unused API endpoints should be disabled and removed from Function Apps (Preview)" matter?
An endpoint nobody calls is still an endpoint an attacker can call. Inactive HTTP functions are usually leftovers: a deprecated API version, a one-off migration job, a test handler that shipped to production. Because no team owns them any more, they drift out of patch and dependency cycles and rarely appear in threat models, yet they remain internet-reachable and authenticate against the same backing data and identities as the live app. That makes them a quiet expansion of the attack surface and a favoured pivot once an exposed function is found. Removing dormant endpoints shrinks what you have to defend and monitor, and cuts the chance that a forgotten function becomes the way in.
How do I fix "Unused API endpoints should be disabled and removed from Function Apps (Preview)"?
- Enable the Defender CSPM plan, then onboard the Function App by turning on the API security posture management extension: in the Azure portal go to Microsoft Defender for Cloud > Environment settings, select the subscription, open the Defender CSPM plan Settings, enable API security posture management, then select Continue and Save. The Function App must be on a supported hosting tier (Premium, Elastic Premium, Dedicated or App Service Environment) and expose REST APIs. Once onboarded, confirm the recommendation populates the Inactive endpoints under the API security view in Defender for Cloud.
- For each flagged endpoint, confirm with the owning team that it is genuinely retired, then disable the individual function by setting its app setting 'AzureWebJobs.<FunctionName>.Disabled' to true: 'az functionapp config appsettings set --name <app> --resource-group <rg> --settings AzureWebJobs.<FunctionName>.Disabled=true'. Disabling first lets you reverse the change quickly if a low-frequency caller reappears.
- Once a disabled endpoint has stayed quiet through a full business cycle, delete the function code from the project and redeploy so the route no longer exists, and remove its IaC definition in your Bicep or Terraform module so it cannot be reintroduced on the next deployment.
Remediation script · bash
# Close the highest-impact Function app exposure first: wildcard CORS, remote
# debugging, weak TLS, and missing client certificates, app by app.
RG=my-rg
APP=ordersapiprod
# 1. Replace wildcard CORS with the origins that actually call the app.
az functionapp cors remove -g "$RG" -n "$APP" --allowed-origins "*"
az functionapp cors add -g "$RG" -n "$APP" \
--allowed-origins https://app.contoso.com https://admin.contoso.com
# 2. Turn off remote debugging and require modern TLS.
az functionapp config set -g "$RG" -n "$APP" \
--remote-debugging-enabled false \
--min-tls-version 1.2
# 3. Require incoming client certificates where the app expects them.
az functionapp update -g "$RG" -n "$APP" \
--set clientCertEnabled=true --set clientCertMode=Required
# 4. Put App Service Authentication (Easy Auth) in front of an HTTP-triggered app
# so anonymous callers are rejected before they reach your code.
az webapp auth update -g "$RG" -n "$APP" \
--enabled true \
--action LoginWithAzureActiveDirectory \
--aad-client-id "$CLIENT_ID" \
--aad-token-issuer-url "https://sts.windows.net/$TENANT_ID/"
# 5. Ratchet it shut: audit any future app that ships without authentication.
# Look the built-in policy up by its exact display name, never hardcode the GUID.
pid=$(az policy definition list \
--query "[?displayName=='Function apps should have authentication enabled'].name" -o tsv)
az policy assignment create \
--name audit-funcapp-auth \
--policy "$pid" \
--scope "/subscriptions/00000000-0000-0000-0000-000000000000" Full walkthrough (console steps, edge cases and verification) in the lesson Harden Azure Function apps.
Is "Unused API endpoints should be disabled and removed from Function Apps (Preview)" a false positive?
A genuinely seasonal or low-frequency endpoint, for example a quarter-end reconciliation function or a disaster-recovery webhook that is only invoked during a failover, will be flagged as Inactive because it legitimately sees no traffic for 30 days. Keep it, document why it exists and who owns it, and treat the flag as confirmation that the endpoint is correctly dormant rather than a defect to remediate.
More Azure Functions controls
- Authentication should be enabled on API endpoints hosted in Function Apps (Preview)
- CORS should not allow every resource to access Function Apps
- FTPS should be required in function apps
- Function apps should have Client Certificates (Incoming client certificates) enabled
- Remote debugging should be turned off for Function App
- TLS should be updated to the latest version for function apps