Skip to main content
emnode
Compliance Medium severity MCSB PV-2

Microsoft Defender for Cloud · Azure App Service

Web apps should request an SSL certificate for all incoming requests

Written and reviewed by Emnode · Last reviewed

What does the recommendation "Web apps should request an SSL certificate for all incoming requests" check?

Flags any App Service web app whose 'Incoming client certificates' setting is off, meaning the 'clientCertEnabled' property is false. When enabled, the app asks every caller to present a client certificate during the TLS handshake so your code can authenticate the caller via mutual TLS. The check is audit-only: it reports the configuration state but does not remediate it. It does not validate whether your application actually inspects the forwarded certificate, and does not check certificate chains or expiry. Note that HTTP/2 and TLS 1.3 are incompatible with the renegotiation-based client-certificate configurations, namely the Optional Interactive User mode and any clientCertExclusionPaths: to keep working over HTTP/2 the certificate must be negotiated during the initial TLS handshake using Required or Optional mode with no exclusion paths.

Why does "Web apps should request an SSL certificate for all incoming requests" matter?

Without incoming client certificates, an internal API or back-office web app accepts any caller who can reach its public hostname, leaving authentication entirely to application code that may be missing, misconfigured or bypassable. Requiring a client certificate adds a transport-layer gate, so an unauthenticated request is rejected at the front end before it ever touches your code. For a service-to-service or partner integration this is the difference between a private endpoint and one that anyone on the internet can probe. The business consequence of skipping it is a directly reachable app that becomes the soft entry point for data exfiltration or lateral movement.

How do I fix "Web apps should request an SSL certificate for all incoming requests"?

  1. In the portal, open the app, go to Settings, Configuration, General settings, and set 'Incoming client certificates' to Require, or run 'az webapp update --name <app> --resource-group <rg> --set clientCertEnabled=true' to flip the property on.
  2. Set the certificate mode to suit your traffic: 'az resource update --name <app> --resource-group <rg> --namespace Microsoft.Web --resource-type sites --set properties.clientCertMode=Required' enforces it for every path, while 'Optional' requests a certificate but still allows callers that do not present one. Use clientCertExclusionPaths to exempt health probes or anonymous routes.
  3. Bake it into infrastructure as code so it cannot regress: in a Bicep 'Microsoft.Web/sites' resource set 'properties.clientCertEnabled: true' and 'properties.clientCertMode: 'Required''. To audit estate-wide, look up the built-in policy and assign it: pid=$(az policy definition list --query "[?displayName=='Web apps should request an SSL certificate for all incoming requests'].name" -o tsv); az policy assignment create --name require-app-client-certs --policy "$pid" --scope <scope>.

Remediation script · bash

SUB="/subscriptions/00000000-0000-0000-0000-000000000000"
RG="rg-app-prod"

# Harden every app that is not already HTTPS-only.
for app in $(az webapp list -g "$RG" \
    --query "[?!httpsOnly].name" -o tsv); do
  # 1. Force HTTPS on the site itself.
  az webapp update -g "$RG" -n "$app" --https-only true
  # 2. Turn off the remote debugger.
  az webapp config set -g "$RG" -n "$app" --remote-debugging-enabled false
  # 3. Drop any wildcard CORS origin (replace with your own origins after).
  az webapp cors remove -g "$RG" -n "$app" --allowed-origins '*'
  echo "$app: HTTPS forced, remote debugging off, wildcard CORS removed"
done

# Ratchet it shut: deny any future app that is not HTTPS-only.
# Look the built-in policy up by display name, never hardcode the GUID.
pid=$(az policy definition list \
  --query "[?displayName=='App Service apps should only be accessible over HTTPS'].name" -o tsv)
az policy assignment create \
  --name deny-appservice-http \
  --policy "$pid" \
  --scope "$SUB"

Full walkthrough (console steps, edge cases and verification) in the lesson Harden Azure App Service apps.

Is "Web apps should request an SSL certificate for all incoming requests" a false positive?

A public-facing web app that authenticates users with sign-in tokens or an external identity provider will flag here, and that is an acceptable exception: browser clients cannot present client certificates seamlessly, so forcing mutual TLS would break ordinary visitors. Reserve this control for service-to-service and partner integrations, and document the exemption for genuinely public apps rather than enabling it everywhere.