azure-mhsm-decrypt-to-credential

A wrapped store whose wrapping key the principal can decrypt exposes the credential it holds.

derived azure emits ExposesCredential

match

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

{'principal': None} CanDecrypt {'key': None} {'wrapped': None} ContainsCredential {'cred': None} {'cred': None} CredentialsFor {'identity': None}

where

?key.provider_type == 'Microsoft.KeyVault/managedHSMs/keys' wraps(?key, ?wrapped) — ?key is the wrapping/encryption key protecting ?wrapped (evidenced DEK/keyvault wrap reference) node_class(?wrapped) in [Compute, Storage, Data, Messaging, Secret] (ExposesCredential source set) node_class(?identity) == Identity (ExposesCredential target set)

emit

source?wrapped
target?identity
permissionsMicrosoft.KeyVault/managedHsm/keys/decrypt/action Microsoft.KeyVault/managedHsm/keys/unwrap/action
conditionskey_permission
state logicinherit_weakest(CanDecrypt): ACTIVE if the CanDecrypt input is ACTIVE and the wrap relationship is evidenced; if CanDecrypt is POTENTIAL/CONDITIONAL, so is this; BLOCKED if CanDecrypt is BLOCKED

Narrative

{principal.name} can decrypt {key.name} that wraps {wrapped.name}, exposing {cred.name} - a credential that authenticates as {identity.name}.

Raw rule rules/derived/azure/managedhsm.yaml

id: azure-mhsm-decrypt-to-credential
emits: ExposesCredential
description: A wrapped store whose wrapping key the principal can decrypt exposes the credential it holds.
match:
- - principal: null
  - CanDecrypt
  - key: null
- - wrapped: null
  - ContainsCredential
  - cred: null
- - cred: null
  - CredentialsFor
  - identity: null
where:
- ?key.provider_type == 'Microsoft.KeyVault/managedHSMs/keys'
- "wraps(?key, ?wrapped) \u2014 ?key is the wrapping/encryption key protecting ?wrapped (evidenced DEK/keyvault\
  \ wrap reference)"
- node_class(?wrapped) in [Compute, Storage, Data, Messaging, Secret] (ExposesCredential source set)
- node_class(?identity) == Identity (ExposesCredential target set)
emit:
  source: ?wrapped
  target: ?identity
  permissions:
  - Microsoft.KeyVault/managedHsm/keys/decrypt/action
  - Microsoft.KeyVault/managedHsm/keys/unwrap/action
  conditions:
  - key_permission
  state_logic: 'inherit_weakest(CanDecrypt): ACTIVE if the CanDecrypt input is ACTIVE and the wrap relationship
    is evidenced; if CanDecrypt is POTENTIAL/CONDITIONAL, so is this; BLOCKED if CanDecrypt is BLOCKED'
  confidence: min(contributing_confidences) * 0.9
  derived_from:
  - ?principal CanDecrypt ?key
  - ?wrapped ContainsCredential ?cred
  - ?cred CredentialsFor ?identity
  - wraps(?key, ?wrapped)
  false_positive_note: "This is a genuinely new edge (the wrapped store -> the identity its wrapped credential\
    \ authenticates as); it does NOT re-emit the CredentialsFor input. Only fires when the material the\
    \ key wraps/encrypts is ITSELF a credential (a wrapped DEK protecting a secret store, a wrapped SP\
    \ key, an encrypted connection string) evidenced by ContainsCredential + CredentialsFor. A key used\
    \ only for disk-block/CMK envelope encryption of non-credential data does NOT yield an identity credential\
    \ \u2014 keep the CanDecrypt edge and do not emit this pivot. The decrypt-of-wrapped-credential value\
    \ lives in the contributing CanDecrypt edge; this edge only surfaces the exposure so credential-centric\
    \ queries and credential-chains.yaml can complete the impersonation roll-up."
  narrative: "{principal.name} can decrypt {key.name} that wraps {wrapped.name}, exposing {cred.name}\
    \ \u2014 a credential that authenticates as {identity.name}."
move · open · esc close