azure-la-http-trigger-internet-exposed
A Logic App with a public HTTP (Request) trigger and no IP allowlist is triggerable from the internet.
match
A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.
where
node_type(?workflow) ==
Workflow
workflow has a trigger of type Request (HTTP)
workflow is Enabled
accessControl.triggers.allowedCallerIpAddresses is absent or empty (no IP restriction)
emit
| source type | Messaging |
|---|---|
| target type | AnonymousIdentity |
| source | <Logic App workflow> |
| target | <AnonymousIdentity> |
| conditions | network_reachability |
| state logic | CONDITIONAL(network_reachability): the HTTP trigger is publicly reachable but still requires the SAS callback URL (not truly anonymous — the URL is a bearer secret). ACTIVE only if the callback URL is widely known or embedded in public documentation/code. In practice emit CONDITIONAL(network_reachability) for all HTTP triggers without IP allowlist; upgrade to ACTIVE if evidence shows the URL is publicly known. |
Narrative
Logic App {workflow.name} exposes a public HTTP trigger (Request trigger + no IP allowlist) triggerable by any actor with the SAS callback URL, potentially driving its managed identity {mi.name} from the internet.
Raw rule rules/derived/azure/logicapps.yaml
id: azure-la-http-trigger-internet-exposed
emits: ExposedToInternet
description: A Logic App with a public HTTP (Request) trigger and no IP allowlist is triggerable from
the internet.
match:
- - workflow: null
- ExecutesAs
- mi: null
where:
- node_type(?workflow) == Workflow
- workflow has a trigger of type Request (HTTP)
- workflow is Enabled
- accessControl.triggers.allowedCallerIpAddresses is absent or empty (no IP restriction)
emit:
source_type: Messaging
target_type: AnonymousIdentity
source: <Logic App workflow>
target: <AnonymousIdentity>
permissions: []
conditions:
- network_reachability
state_logic: "CONDITIONAL(network_reachability): the HTTP trigger is publicly reachable but still requires\
\ the SAS callback URL (not truly anonymous \u2014 the URL is a bearer secret). ACTIVE only if the\
\ callback URL is widely known or embedded in public documentation/code. In practice emit CONDITIONAL(network_reachability)\
\ for all HTTP triggers without IP allowlist; upgrade to ACTIVE if evidence shows the URL is publicly\
\ known."
confidence: 0.8
derived_from:
- '<ExecutesAs edge: ?workflow -> ?mi>'
- trigger type == Request in workflow definition
false_positive_note: "The HTTP trigger callback URL contains a SAS signature \u2014 it is NOT a fully\
\ anonymous endpoint. Any actor with the URL can trigger the workflow, but the URL must first be obtained\
\ (via listCallbackUrl/action, from run history, or from public disclosure). Emit CONDITIONAL(network_reachability)\
\ not ACTIVE unless the URL is confirmed publicly known. An IP allowlist (accessControl.triggers.allowedCallerIpAddresses)\
\ restricts triggering to named IPs/ranges \u2014 condition network_reachability for allowlisted triggers.\
\ A Disabled workflow does not respond to HTTP triggers."
narrative: Logic App {workflow.name} exposes a public HTTP trigger (Request trigger + no IP allowlist)
triggerable by any actor with the SAS callback URL, potentially driving its managed identity {mi.name}
from the internet.