Back to blog
AzureBest PracticesCloud SecurityServerless

Azure App Service Not HTTPS-Only: Risks and Remediation

Learn why an Azure App Service that allows HTTP traffic is a risk, and how to enforce HTTPS-only with CLI, Terraform, Bicep, and Azure Policy.

TL;DR

This check flags Azure App Services that accept plaintext HTTP traffic, leaving requests open to interception and tampering. Flip the httpsOnly property to true so every HTTP request gets a 301 redirect to HTTPS.

Azure App Service makes it trivially easy to deploy a web app, and just as easy to leave it listening on plain HTTP. By default a new App Service responds on both http:// and https:// endpoints. Unless you explicitly turn on the HTTPS-only setting, anyone who hits the bare HTTP URL gets served over an unencrypted channel. This Lensix check, appservice_nohttps, looks for exactly that: an App Service where HTTPS is not enforced.


What this check detects

The check inspects the httpsOnly property on each Azure App Service (Web App, API App, or Function App) in your subscription. When that property is false, the service accepts connections on both HTTP and HTTPS. When it is true, App Service automatically redirects any inbound HTTP request to its HTTPS equivalent with a 301 response.

In plain terms, a failing result means a client can reach your application over an unencrypted connection, and nothing stops them from doing so.

Note: HTTPS-only is separate from your TLS version setting and from certificate binding. App Service serves a managed certificate on the default *.azurewebsites.net hostname out of the box, so HTTPS works immediately. The httpsOnly flag only controls whether plaintext HTTP is also allowed.


Why it matters

Allowing HTTP traffic is not a theoretical problem. It opens up a few concrete failure modes.

Credentials and session tokens travel in the clear

If a user logs in over http://, their username, password, and any session cookie are transmitted as plaintext. Anyone positioned on the network path, a compromised Wi-Fi access point, a malicious ISP-level actor, or an attacker doing ARP spoofing on a shared network, can read or replay them. Even if your app eventually redirects to HTTPS at the application layer, the first request already leaked.

Man-in-the-middle injection

Unencrypted responses can be modified in transit. An attacker can inject malicious JavaScript, rewrite download links, or strip out security headers before the response reaches the browser. The user has no way to tell the page was tampered with.

Cookie leakage without the Secure flag

If HTTP is permitted, cookies that lack the Secure attribute will be sent over plaintext connections. This is a common way session identifiers leak even when most of the traffic is encrypted.

Warning: Several compliance frameworks treat plaintext transmission of sensitive data as a finding. PCI DSS, HIPAA, and SOC 2 all expect encryption in transit. An App Service serving cardholder data or PHI over HTTP can directly fail an audit.

Business impact

Beyond the direct security risk, browsers now mark non-HTTPS pages as "Not secure," which erodes user trust. Some browser features (geolocation, service workers, the clipboard API) refuse to run outside a secure context, so an HTTP fallback can quietly break functionality.


How to fix it

The fix is a single property change. Below are the common ways to apply it.

Azure CLI

az webapp update \
  --resource-group myResourceGroup \
  --name myAppService \
  --set httpsOnly=true

For a Function App the command is the same, since Function Apps are App Service resources under the hood.

Azure Portal

  1. Open the App Service in the Azure Portal.
  2. Under Settings, select Configuration.
  3. Go to the General settings tab.
  4. Set HTTPS Only to On.
  5. Click Save.

Warning: Enabling HTTPS-only redirects all HTTP traffic. If you have callers, webhooks, or health probes hardcoded to the http:// URL that do not follow redirects, they will break. Audit those clients before flipping the switch in production, or expect a few 301s they may not handle.

Terraform

resource "azurerm_linux_web_app" "example" {
  name                = "my-app-service"
  resource_group_name = azurerm_resource_group.example.name
  location            = azurerm_resource_group.example.location
  service_plan_id     = azurerm_service_plan.example.id

  https_only = true

  site_config {}
}

For the older azurerm_app_service resource the attribute is also https_only = true.

Bicep / ARM

{
  "type": "Microsoft.Web/sites",
  "apiVersion": "2022-09-01",
  "name": "myAppService",
  "location": "[resourceGroup().location]",
  "properties": {
    "httpsOnly": true,
    "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', 'myPlan')]"
  }
}

Tip: While you are in there, also raise the minimum TLS version. Set minTlsVersion to 1.2 (or 1.3 where supported) so the encrypted connection itself is not negotiated down to a weak protocol. In CLI: az webapp config set --resource-group myResourceGroup --name myAppService --min-tls-version 1.2.


How to prevent it from happening again

Fixing one App Service is easy. Keeping every future deployment compliant is the real goal. Bake the requirement into the places where infrastructure is defined and shipped.

Enforce with Azure Policy

Azure has a built-in policy definition, "App Service apps should only be accessible over HTTPS." Assigning it with a Deny effect blocks creation of non-compliant App Services across a subscription or management group.

az policy assignment create \
  --name 'require-appservice-https' \
  --display-name 'App Service must be HTTPS only' \
  --policy 'a4af4a39-4135-47fb-b175-47fbdf85311d' \
  --scope '/subscriptions/<subscription-id>' \
  --params '{ "effect": { "value": "Deny" } }'

The policy ID above is the built-in definition. With Deny in place, a deployment that leaves httpsOnly off is rejected before it ever runs.

Tip: Start the policy in Audit mode for a week to find existing offenders without breaking deployments, then switch it to Deny once you have remediated the backlog.

Catch it in CI/CD

If you deploy with Terraform or Bicep, scan the plan before it reaches Azure. A tool like checkov catches a missing HTTPS-only setting in seconds.

checkov -d ./infra --framework terraform

The relevant check is CKV_AZURE_14 (App Service uses HTTPS). Add it as a required step in your pull request pipeline so no merge can ship an HTTP-enabled app.

Use a secure module default

Wrap App Service creation in an internal Terraform module that sets https_only = true and a sane minimum_tls_version by default. Teams that consume the module get the secure setting for free and have to go out of their way to disable it.


Best practices

  • Always pair HTTPS-only with a strong minimum TLS version. Enforcing HTTPS while allowing TLS 1.0 is only half the job.
  • Set the Secure and HttpOnly flags on cookies at the application level, so even a stray HTTP request cannot leak session data.
  • Add an HSTS header (Strict-Transport-Security) so browsers refuse to connect over HTTP after the first visit. App Service does not add it for you, so set it in your app or via a reverse proxy.
  • Bind a custom domain with a managed certificate. App Service Managed Certificates are free and auto-renew, removing the temptation to fall back to HTTP because a cert expired.
  • Audit non-default hostnames. HTTPS-only applies to all bindings, but a misconfigured custom domain without a certificate can still surface HTTP. Verify each binding after adding it.
  • Scan continuously, not just once. Drift happens. A continuous check like Lensix appservice_nohttps catches an App Service that someone toggled back to HTTP during troubleshooting and forgot to revert.

HTTPS-only is one of the cheapest security wins in Azure. It costs nothing, takes one property change, and closes off an entire class of network-level attacks. Enforce it everywhere, gate it in your pipeline, and let policy keep it that way.