azure-la-http-trigger-internet-exposed

A Logic App with a public HTTP (Request) trigger and no IP allowlist is triggerable from the internet.

derived azure emits ExposedToInternet

match

A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.

{'workflow': None} ExecutesAs {'mi': None}

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 typeMessaging
target typeAnonymousIdentity
source<Logic App workflow>
target<AnonymousIdentity>
conditionsnetwork_reachability
state logicCONDITIONAL(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.
move · open · esc close