Microsoft Defender for Cloud · Azure App Service
FTPS should be required in API apps
Written and reviewed by Emnode · Last reviewed
What does the recommendation "FTPS should be required in API apps" check?
Flags any App Service API app whose FTP/FTPS deployment endpoint still accepts plain FTP, that is, where 'siteConfig.ftpsState' is left at the default 'AllAllowed' rather than 'FtpsOnly' or 'Disabled'. The check looks only at the deployment file-transfer channel; it does not assess your app's HTTPS-only setting, the minimum TLS version negotiated for client web traffic, or whether the publishing credentials themselves are strong. It also does not disable FTP altogether, it only requires that any FTP session be encrypted.
Why does "FTPS should be required in API apps" matter?
Azure's FTP publishing endpoint is reachable over the public internet, and with plain FTP both the publishing username and password and the entire code payload travel in clear text. Anyone able to observe the path, a compromised network segment, a hostile Wi-Fi hop or an on-path proxy, can capture those credentials and gain full write access to your application's content, letting them plant a web shell or backdoor that runs with the app's identity. Requiring FTPS encrypts the session so deployment secrets and source cannot be lifted in transit, which is also a baseline expectation under PCI DSS and HIPAA for any sensitive data crossing a network.
How do I fix "FTPS should be required in API apps"?
- Set the FTP state to 'FTPS Only' on the API app: in the portal open the app, go to Settings then Configuration then General settings and change 'FTP state' to 'FTPS only' (or 'Disabled' if you never deploy over FTP). With the CLI: az webapp config set --resource-group <rg> --name <app> --ftps-state FtpsOnly.
- Bake the setting into your infrastructure so new apps are born compliant: in Bicep or ARM set 'ftpsState' to 'FtpsOnly' inside the 'siteConfig' block of the Microsoft.Web/sites resource, and redeploy.
- Enforce it estate-wide with Azure Policy. The API-app-specific built-in definition is deprecated, so assign the current replacement 'App Service apps should require FTPS only' instead, looking the id up by display name rather than pasting a GUID: pid=$(az policy definition list --query "[?displayName=='App Service apps should require FTPS only'].name" -o tsv); az policy assignment create --name require-ftps --policy "$pid" --scope <scope>.
Remediation script · bash
# Close the highest-impact plaintext doors first: the Redis non-SSL port,
# then HTTPS-only + a modern TLS floor on every web app.
# Redis: disable the non-SSL port 6379 and require TLS 1.2 (clients use 6380).
for cache in $(az redis list --query "[?enableNonSslPort].name" -o tsv); do
rg=$(az redis list --query "[?name=='$cache'].resourceGroup" -o tsv)
az redis update --name "$cache" --resource-group "$rg" \
--set enableNonSslPort=false minimumTlsVersion=1.2
echo "$cache: non-SSL port disabled, min TLS 1.2"
done
# Web apps: enforce HTTPS only and raise the TLS floor.
for app in $(az webapp list --query "[?httpsOnly==\`false\`].name" -o tsv); do
rg=$(az webapp list --query "[?name=='$app'].resourceGroup" -o tsv)
az webapp update --name "$app" --resource-group "$rg" --https-only true
az webapp config set --name "$app" --resource-group "$rg" --min-tls-version 1.2
echo "$app: HTTPS only, min TLS 1.2"
done
# Functions follow the same pattern with az functionapp update --set httpsOnly=true.
# Ratchet it shut: assign the built-in deny policy for web apps over HTTPS only.
az policy assignment create \
--name require-https-webapp \
--policy a4af4a39-4135-47fb-b175-47fbdf85311d \
--scope "/subscriptions/00000000-0000-0000-0000-000000000000" Full walkthrough (console steps, edge cases and verification) in the lesson Enforce encryption in transit across Azure services.
Is "FTPS should be required in API apps" a false positive?
An API app that has FTP publishing switched off entirely will not flag, which is the strongest posture. If you genuinely need an unencrypted FTP path, for example a legacy build agent that cannot speak FTPS pushing to an isolated, non-production app behind a private endpoint with no sensitive content, the finding is a deliberate accepted exception; document it and exempt that resource from the policy rather than relaxing the default for every app.
More Azure App Service controls
- API App should only be accessible over HTTPS
- CORS should not allow every resource to access API Apps
- CORS should not allow every resource to access Web Applications
- Ensure API app has Client Certificates Incoming client certificates set to On
- FTPS should be required in web apps
- Java should be updated to the latest version for API apps
- Managed identity should be used in API apps
- Managed identity should be used in web apps
- Microsoft Defender for App Service should be enabled
- PHP should be updated to the latest version for API apps
- Python should be updated to the latest version for API apps
- Remote debugging should be turned off for API App