Microsoft Defender for Cloud · Azure Functions
FTPS should be required in function apps
Written and reviewed by Emnode · Last reviewed
What does the recommendation "FTPS should be required in function apps" check?
Flags any function app whose 'FTP state' (the ftpsState property under Microsoft.Web/sites/config) is set to 'All allowed', which permits plain, unencrypted FTP for content deployment alongside FTPS. New function apps default to 'All allowed', so the gap is usually inherited rather than chosen. The control passes only when ftpsState is 'FTPS only' or 'Disabled'. It governs the FTP/FTPS deployment endpoint specifically: it does not check the app's inbound HTTPS-only setting, its minimum TLS version for HTTP traffic, or the SCM/Kudu site, each of which is a separate recommendation. It also says nothing about whether you actually deploy over FTP, only whether the insecure protocol is left available.
Why does "FTPS should be required in function apps" matter?
FTP carries credentials and source code in clear text, so anyone able to observe the network path, a shared office Wi-Fi, a compromised router, or a transit hop, can capture the publishing username and password and read every byte deployed. With those credentials an attacker can overwrite your function code and run arbitrary logic inside your subscription, turning a passive eavesdrop into full control of the workload. The publishing profile that holds these credentials is widely distributed to developer laptops and CI runners, which multiplies the places that secret can leak from. Because functions often hold connection strings and managed-identity access to downstream data, a hijacked deployment becomes a foothold into the data plane, not just the app. Requiring FTPS forces the channel onto TLS, so deployment traffic stays confidential even on untrusted networks and the publishing profile cannot be lifted in transit. The change is a configuration flag with no code impact, which is why this rates High: low effort to fix, severe blast radius if ignored.
How do I fix "FTPS should be required in function apps"?
- Set the FTP state to 'FTPS only' (or 'Disabled' if you never deploy over FTP) under Settings > Configuration > General settings on each function app, or run: az functionapp config set --resource-group <rg> --name <app> --ftps-state FtpsOnly
- In Bicep, pin the value so it cannot drift: add siteConfig: { ftpsState: 'FtpsOnly' } to the Microsoft.Web/sites resource, then redeploy.
- Enforce it estate-wide with the built-in policy 'Function apps should require FTPS only'. Look the definition up by name rather than pasting a GUID, then assign it: pid=$(az policy definition list --query "[?displayName=='Function apps should require FTPS only'].name" -o tsv); az policy assignment create --name require-ftps-functions --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 function apps" a false positive?
A function app set to 'Disabled' also satisfies the control, so if you have already turned FTP off entirely and deploy only through zip deploy, GitHub Actions or run-from-package, there is nothing to remediate. The recommendation never wants plain FTP; treating 'Disabled' as a pass is correct, not a gap to 'fix' by re-enabling FTPS.
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
- 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
- Unused API endpoints should be disabled and removed from Function Apps (Preview)