This check flags Azure App Services that accept traffic from any IP address with no access restrictions in place. An unrestricted app is reachable by anyone on the internet, including bots and attackers probing for weak endpoints. Lock it down by adding IP allow rules that scope access to your VNet, Front Door, or known office ranges.
Azure App Service makes it trivially easy to ship a web app or API. You push your code, Azure provisions a public endpoint, and within minutes you have a running service on the internet. That convenience comes with a default that catches a lot of teams off guard: unless you explicitly say otherwise, your App Service answers requests from every IP address on the planet.
The appservice_noaccessrestriction check looks for exactly this. If an App Service has no IP access restrictions configured on its main site (or its SCM/Kudu deployment endpoint), Lensix flags it as exposed.
What this check detects
Azure App Service supports a feature called access restrictions, a set of allow and deny rules evaluated in priority order against incoming requests. Each rule can match an IPv4 or IPv6 CIDR range, a Virtual Network service tag, or a service endpoint. When the rule list is empty, App Service applies an implicit "allow all" and any client can reach the app.
This check inspects two things for each App Service:
- The main site access restrictions (the public app endpoint at
https://yourapp.azurewebsites.net) - The SCM site access restrictions (the Kudu deployment and management endpoint at
https://yourapp.scm.azurewebsites.net)
If either has no restriction rules, the resource is considered open to the public internet.
Note: Access restrictions operate at the network layer, before your application code runs. A request that fails the rule set gets an HTTP 403 from the platform itself, so your app never sees it. This is different from authentication, which happens inside your app or via Easy Auth after the request is already accepted.
Why it matters
An open App Service endpoint is a standing invitation for anyone who can resolve its hostname. Here is what that exposure looks like in practice.
Internal apps that were never meant to be public
Plenty of App Services host admin dashboards, internal tooling, staging environments, or backend APIs that are only supposed to be consumed by other services. When these get a default public endpoint, they sit on the internet with nothing but application-level auth (if that) standing between an attacker and your data. A misconfigured route, a debug endpoint left enabled, or an unauthenticated health check can leak far more than you intended.
The SCM/Kudu endpoint is a high-value target
The SCM site is the management plane for your App Service. It exposes deployment, file system browsing, environment variables, process explorer, and a web-based console. If the SCM endpoint is reachable and an attacker gets hold of valid credentials or a stolen deployment token, they can read your secrets, modify your code, or run commands inside the app's environment.
Danger: Leaving the SCM endpoint open to the public dramatically widens your attack surface. Connection strings, app settings, and deployment credentials are all accessible through Kudu. Treat an open SCM site as a credential exposure risk, not just an availability one.
Reconnaissance and automated probing
Automated scanners crawl the azurewebsites.net namespace constantly. An exposed app gets fingerprinted, probed for known CVEs in the framework it runs, and tested against common paths like /.env, /admin, and /api/swagger. Restricting access removes your app from that pool entirely. If a scanner cannot reach the endpoint, it cannot enumerate it.
Compliance impact
Frameworks like PCI DSS, SOC 2, and ISO 27001 expect network segmentation and least-privilege access controls around systems that handle sensitive data. An App Service open to 0.0.0.0/0 is a finding auditors will flag, and "we rely on app-level auth" is rarely an acceptable answer on its own.
How to fix it
The fix is to add access restriction rules that allow only the sources that legitimately need to reach the app, and let the implicit deny handle everything else.
Option 1: Azure Portal
- Open your App Service in the Azure Portal.
- In the left menu, go to Settings → Networking.
- Under Inbound traffic configuration, select Public network access and then Access restriction.
- Click Add to create a rule. Give it a name, set Action to Allow, choose IPv4 as the type, and enter the CIDR range you want to permit (for example
203.0.113.0/24). - Repeat for each trusted source. Once at least one allow rule exists, App Service automatically denies everything else.
- Switch to the Advanced tool site (SCM) tab and decide whether it should inherit the main site rules or use its own. For most cases, restrict it to your deployment pipeline ranges only.
Option 2: Azure CLI
Add an allow rule for a known IP range on the main site:
az webapp config access-restriction add \
--resource-group my-rg \
--name my-app \
--rule-name "office-network" \
--action Allow \
--ip-address 203.0.113.0/24 \
--priority 100
Restrict the SCM site to your CI/CD egress range:
az webapp config access-restriction add \
--resource-group my-rg \
--name my-app \
--rule-name "pipeline-agents" \
--action Allow \
--ip-address 198.51.100.0/24 \
--priority 100 \
--scm-site true
You can also lock access down to a specific virtual network subnet, which is the cleaner pattern for backend services:
az webapp config access-restriction add \
--resource-group my-rg \
--name my-app \
--rule-name "vnet-backend" \
--action Allow \
--vnet-name my-vnet \
--subnet backend-subnet \
--priority 100
Warning: If you add an allow rule that does not include your own current IP or your deployment pipeline, you can immediately lock yourself and your CI/CD out of the app. Add the rules for your management and deployment sources first, verify connectivity, then tighten further.
Option 3: Terraform
Define restrictions declaratively so they are version-controlled and reproducible. For a Linux Web App:
resource "azurerm_linux_web_app" "app" {
name = "my-app"
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
service_plan_id = azurerm_service_plan.plan.id
site_config {
ip_restriction {
name = "office-network"
action = "Allow"
ip_address = "203.0.113.0/24"
priority = 100
}
ip_restriction {
name = "vnet-backend"
action = "Allow"
virtual_network_subnet_id = azurerm_subnet.backend.id
priority = 110
}
scm_ip_restriction {
name = "pipeline-agents"
action = "Allow"
ip_address = "198.51.100.0/24"
priority = 100
}
}
}
Tip: If your app sits behind Azure Front Door or Application Gateway, restrict the App Service to accept traffic only from that service rather than from end-user IPs. Use the AzureFrontDoor.Backend service tag plus the X-Azure-FDID header check so traffic must come through your specific Front Door instance, not just any Front Door.
Verify the result
After applying rules, confirm the configuration:
az webapp config access-restriction show \
--resource-group my-rg \
--name my-app
Test from a disallowed source. You should get an HTTP 403 from the platform:
curl -I https://my-app.azurewebsites.net
# Expect: HTTP/1.1 403 Ip Forbidden
How to prevent it from happening again
One-off remediation does not scale. New App Services keep getting created, and the public default reasserts itself every time. Bake the guardrails into your platform instead.
Azure Policy
Use a built-in or custom Azure Policy to audit or deny App Services without IP restrictions. Assign it at the management group or subscription level so coverage is automatic:
{
"if": {
"allOf": [
{ "field": "type", "equals": "Microsoft.Web/sites" },
{
"anyOf": [
{ "field": "Microsoft.Web/sites/config.ipSecurityRestrictions[*]", "exists": "false" },
{ "count": { "field": "Microsoft.Web/sites/config.ipSecurityRestrictions[*]" }, "equals": 0 }
]
}
]
},
"then": { "effect": "audit" }
}
Start with audit to measure your current exposure, then move to deny once teams have adopted the pattern.
CI/CD gates with policy-as-code
Catch the misconfiguration before it ever reaches Azure. Tools like Checkov, tfsec, or Conftest can scan Terraform in your pipeline and fail the build when an App Service lacks restrictions. A simple Checkov gate:
checkov -d ./infra --check CKV_AZURE_88
Tip: Pair the IaC scan in your pull request pipeline with continuous Lensix monitoring on the live environment. The pipeline catches what is defined in code, and Lensix catches drift, manual portal changes, and resources created outside your IaC workflow.
Secure-by-default modules
If your teams provision App Services through a shared Terraform module or Bicep template, set the restrictions inside the module so every consumer inherits them. Make the open case the exception that requires an explicit override and a documented reason, rather than the silent default.
Best practices
- Default to deny. Build your rule set as a list of explicit allows so anything you forgot to permit is blocked, not exposed.
- Lock down SCM separately. The deployment endpoint rarely needs the same access as the main site. Scope it to your pipeline and break-glass admin ranges only.
- Prefer private networking for backends. For APIs and internal services, use VNet integration with private endpoints instead of public IP allow lists. That keeps traffic off the public internet entirely.
- Front your public apps with a WAF. Put Azure Front Door or Application Gateway with WAF in front of public-facing apps, then restrict the App Service to accept traffic only from that gateway.
- Avoid maintaining huge IP lists by hand. Use service tags and subnet-based rules where possible. Hardcoded IP lists drift and rot quickly.
- Review restrictions during change reviews. Treat any change that widens access as a security-relevant change worth a second set of eyes.
- Test your 403 path. After every change, confirm that a disallowed source actually gets blocked. A rule that looks correct but uses the wrong priority can quietly allow more than intended.
Network access restrictions are one of the cheapest, highest-leverage controls available on App Service. They cost nothing, take minutes to apply, and shrink your attack surface from "the entire internet" to "the handful of sources that should ever reach this app." Make them the default, enforce them in code, and monitor for drift so the default never quietly reverts.

