Function app has FTP and FTPS deployments disabled
Azure Function apps are evaluated for the ftps_state setting that controls FTP/FTPS deployment endpoints. Values AllAllowed or FtpsOnly indicate deployment over FTP/FTPS is enabled, while Disabled indicates both endpoints are turned off.
Risk
Enabled FTP/FTPS deployment undermines confidentiality and integrity. FTP exposes credentials in cleartext; FTPS still presents a public basic-auth endpoint susceptible to brute force and credential reuse. Compromise enables unauthorized code pushes, leading to RCE, data leakage, and service disruption.
Run this check with Prowler
Run in Prowler Cloudprowler azure --checks app_function_ftps_deployment_disabledRecommendation
Disable FTP and FTPS deployment on Function apps (ftps_state: Disabled). Adopt defense in depth: deploy via CI/CD with packaged artifacts (zip or containers), enforce least privilege publishing access, and limit exposure of build and deployment endpoints. If unavoidable, use FTPS-only with TLS 1.2 and rotate credentials promptly.
Remediation
CLI
az webapp config set --resource-group <resource-group> --name <app-name> --ftps-state DisabledTerraform
# Disable FTP and FTPS on a Function App
resource "azurerm_linux_function_app" "<example_resource_name>" {
name = "<example_resource_name>"
resource_group_name = "<example_resource_name>"
location = "<example_location>"
service_plan_id = "<example_resource_id>"
storage_account_name = "<example_resource_name>"
storage_account_access_key = "<example_secret_value>"
functions_extension_version = "~4"
site_config {
ftps_state = "Disabled" # CRITICAL: Disables both FTP and FTPS deployments
}
}NativeIaC
// Disable FTP and FTPS on an existing Function App
resource functionApp 'Microsoft.Web/sites@2022-09-01' existing = {
name: '<example_resource_name>'
}
resource webConfig 'Microsoft.Web/sites/config@2022-09-01' = {
name: 'web'
parent: functionApp
properties: {
ftpsState: 'Disabled' // CRITICAL: Disables both FTP and FTPS deployments
}
}Other
Check Code
from prowler.lib.check.models import Check, Check_Report_Azure
from prowler.providers.azure.services.app.app_client import app_client
class app_function_ftps_deployment_disabled(Check):
def execute(self) -> Check_Report_Azure:
findings = []
for (
subscription_id,
functions,
) in app_client.functions.items():
subscription_name = app_client.subscriptions.get(
subscription_id, subscription_id
)
for function in functions.values():
report = Check_Report_Azure(metadata=self.metadata(), resource=function)
report.subscription = subscription_id
report.status = "FAIL"
report.status_extended = f"Function {function.name} from subscription {subscription_name} ({subscription_id}) has {'FTP' if function.ftps_state == 'AllAllowed' else 'FTPS' if function.ftps_state == 'FtpsOnly' else 'FTP or FTPS'} deployment enabled."
if function.ftps_state == "Disabled":
report.status = "PASS"
report.status_extended = f"Function {function.name} from subscription {subscription_name} ({subscription_id}) has FTP and FTPS deployment disabled."
findings.append(report)
return findings