azure-cosmosdb-readonlykeys-exposes-credential

readonlykeys/action returns Cosmos DB read-only master keys - bypasses data-plane RBAC for read operations across all databases and containers.

derived azure emits ExposesCredential

match

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

{'principal': None} HasPermission {'account': None}

where

node_class(?account) == Data and node_type(?account) == NoSQLDatabase node_type(?account) matched provider_type == 'Microsoft.DocumentDB/databaseAccounts' ?principal has EFFECTIVE Microsoft.DocumentDB/databaseAccounts/readonlykeys/action at ?account scope NOT ?principal has EFFECTIVE Microsoft.DocumentDB/databaseAccounts/listKeys/action at ?account scope # avoid double-emit; listKeys subsumes readonlykeys

emit

source typeNoSQLDatabase
target typeAccessKey
source?account
target<read-only primary/secondary AccessKey node(s) of ?account>
permissionsMicrosoft.DocumentDB/databaseAccounts/readonlykeys/action
conditionsiam_permission
state logicif deny assignment covers readonlykeys/action: BLOCKED; elif ?account.properties.disableLocalAuth == true: CONDITIONAL(service_state); else ACTIVE. ARM-plane call — not gated by IP firewall.

Narrative

{principal.name} can call readonlykeys on {account.name} (Microsoft.DocumentDB/databaseAccounts/readonlykeys/action), retrieving the read-only primary and secondary keys. These keys bypass all Azure RBAC data-plane role assignments for read operations across all databases and containers, enabling unauthorized data exfiltration.

Raw rule rules/derived/azure/cosmosdb.yaml

id: azure-cosmosdb-readonlykeys-exposes-credential
emits: ExposesCredential
description: "readonlykeys/action returns Cosmos DB read-only master keys \u2014 bypasses data-plane RBAC\
  \ for read operations across all databases and containers."
match:
- - principal: null
  - HasPermission
  - account: null
where:
- node_class(?account) == Data and node_type(?account) == NoSQLDatabase
- node_type(?account) matched provider_type == 'Microsoft.DocumentDB/databaseAccounts'
- ?principal has EFFECTIVE Microsoft.DocumentDB/databaseAccounts/readonlykeys/action at ?account scope
- 'NOT ?principal has EFFECTIVE Microsoft.DocumentDB/databaseAccounts/listKeys/action at ?account scope  #
  avoid double-emit; listKeys subsumes readonlykeys'
emit:
  source_type: NoSQLDatabase
  target_type: AccessKey
  source: ?account
  target: <read-only primary/secondary AccessKey node(s) of ?account>
  permissions:
  - Microsoft.DocumentDB/databaseAccounts/readonlykeys/action
  conditions:
  - iam_permission
  state_logic: "if deny assignment covers readonlykeys/action: BLOCKED; elif ?account.properties.disableLocalAuth\
    \ == true: CONDITIONAL(service_state); else ACTIVE. ARM-plane call \u2014 not gated by IP firewall."
  confidence: '0.90'
  derived_from:
  - <HasPermission edge_id (readonlykeys/action)>
  false_positive_note: "Emit only when the principal has readonlykeys but NOT listKeys \u2014 listKeys\
    \ is a superset and azure-cosmosdb-listkeys-exposes-credential already covers that case. Read-only\
    \ keys bypass RBAC for read but cannot write or delete items; CanExfiltrate is still applicable (data\
    \ can be exfiltrated via read-only key). ARM-plane call, not gated by IP firewall. Cosmos DB Operator\
    \ explicitly excludes readonlyKeys/* \u2014 verify notActions. disableLocalAuth=true: same treatment\
    \ as listKeys."
  narrative: '{principal.name} can call readonlykeys on {account.name} (Microsoft.DocumentDB/databaseAccounts/readonlykeys/action),
    retrieving the read-only primary and secondary keys. These keys bypass all Azure RBAC data-plane role
    assignments for read operations across all databases and containers, enabling unauthorized data exfiltration.'
move · open · esc close