azure-swa-exposes-deploy-token

A Static Web App exposes its deployment token as a credential for the CI/CD pipeline identity.

derived azure emits ExposesCredential

match

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

{'swa': None} ContainsSecret {'token': None}

where

node_type(?swa) == ApplicationPlatform # Microsoft.Web/staticSites ?token is the SWA deployment token (APIKey) from listSecrets ?pipeline_identity is the CI/CD pipeline service identity (GitHub Actions OIDC subject, Azure Pipelines service connection MI, or federated identity)

emit

source typeCompute
target typeIdentity
source?swa
target?pipeline_identity
state logicACTIVE when the SWA exists and the deploy token is not reset/rotated. BLOCKED if token is rotated.

Narrative

Static Web App {swa.name} exposes its build/deploy token as a long-lived CI/CD credential (accessible via listSecrets/action). Any principal holding this token can authenticate as the CI/CD pipeline identity {pipeline_identity.name}.

Raw rule rules/derived/azure/staticwebapps.yaml

id: azure-swa-exposes-deploy-token
emits: ExposesCredential
description: A Static Web App exposes its deployment token as a credential for the CI/CD pipeline identity.
applies_to:
- azure
match:
- - swa: null
  - ContainsSecret
  - token: null
where:
- 'node_type(?swa) == ApplicationPlatform   # Microsoft.Web/staticSites'
- ?token is the SWA deployment token (APIKey) from listSecrets
- ?pipeline_identity is the CI/CD pipeline service identity (GitHub Actions OIDC subject, Azure Pipelines
  service connection MI, or federated identity)
emit:
  source_type: Compute
  target_type: Identity
  source: ?swa
  target: ?pipeline_identity
  permissions: []
  state_logic: ACTIVE when the SWA exists and the deploy token is not reset/rotated. BLOCKED if token
    is rotated.
  confidence: 0.9
  derived_from:
  - ?swa ContainsSecret ?token (azure-swa-deploy-token-contains-secret)
  false_positive_note: "The deploy token authorizes CDN content pushes as the CI/CD pipeline; it does\
    \ not grant ARM RBAC roles or Entra app credentials. The token is a symmetric secret \u2014 rotation\
    \ invalidates it (emit BLOCKED or remove). Do not derive CanExecuteAs from this edge alone; cicd-chains\
    \ produces CanExecuteAs from the CanModifyCode edge combined with ExecutesAs on a runner, not from\
    \ ExposesCredential directly. credential-chains may chain this to CredentialsFor(pipeline_identity)\
    \ for identity-centric queries."
  narrative: Static Web App {swa.name} exposes its build/deploy token as a long-lived CI/CD credential
    (accessible via listSecrets/action). Any principal holding this token can authenticate as the CI/CD
    pipeline identity {pipeline_identity.name}.
move · open · esc close