gcp-memorystore-get-auth-string-exposes-credential

redis.instances.getAuthString retrieves the Redis AUTH string (UUID), which is the shared credential granting full Redis data-plane access to any in-VPC client that possesses it. This is the Memorystore "master key" credential grab.

derived gcp emits ExposesCredential

match

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

{'instance': None} Contains {'auth_string': None}

where

node_type(?instance) == Cache node_type(?auth_string) == Credential ?instance.authEnabled == true

emit

source typeCache
target typeCredential
source?instance
target?auth_string
permissionsredis.instances.getAuthString
conditionsiam_permission
state logicACTIVE when: the CanReadCredential input is ACTIVE (redis.instances.getAuthString permission held) AND instance.authEnabled is true (the AUTH string is meaningful only when AUTH is enabled). CONDITIONAL(iam_permission) when the CanReadCredential input is CONDITIONAL. BLOCKED if the CanReadCredential input is BLOCKED (IAM deny on getAuthString). Do NOT emit if instance.authEnabled is false — the AUTH string is not the access control mechanism when AUTH is disabled (use gcp-memorystore-no-auth- data-access instead).

Narrative

{instance.name} exposes the Redis AUTH string (UUID) credential. Any principal holding redis.instances.getAuthString can retrieve it via the Memorystore API; any in-VPC client that possesses this string can authenticate to {instance.name} and access all Redis keys.

Raw rule rules/derived/gcp/memorystore.yaml

id: gcp-memorystore-get-auth-string-exposes-credential
emits: ExposesCredential
description: redis.instances.getAuthString retrieves the Redis AUTH string (UUID), which is the shared
  credential granting full Redis data-plane access to any in-VPC client that possesses it. This is the
  Memorystore "master key" credential grab.
match:
- - instance: null
  - Contains
  - auth_string: null
where:
- node_type(?instance) == Cache
- node_type(?auth_string) == Credential
- ?instance.authEnabled == true
emit:
  source_type: Cache
  target_type: Credential
  source: ?instance
  target: ?auth_string
  permissions:
  - redis.instances.getAuthString
  conditions:
  - iam_permission
  state_logic: "ACTIVE when: the CanReadCredential input is ACTIVE (redis.instances.getAuthString permission\
    \ held) AND instance.authEnabled is true (the AUTH string is meaningful only when AUTH is enabled).\
    \ CONDITIONAL(iam_permission) when the CanReadCredential input is CONDITIONAL. BLOCKED if the CanReadCredential\
    \ input is BLOCKED (IAM deny on getAuthString). Do NOT emit if instance.authEnabled is false \u2014\
    \ the AUTH string is not the access control mechanism when AUTH is disabled (use gcp-memorystore-no-auth-\
    \ data-access instead)."
  confidence: min(contributing_confidences) * 0.95
  derived_from:
  - '<Contains edge: instance -> AUTH string Credential>'
  - <instance.authEnabled == true>
  false_positive_note: "Only emit when AUTH is enabled on the instance (authEnabled=true). When AUTH is\
    \ disabled, the AUTH string is irrelevant \u2014 any in-VPC client already has full access without\
    \ credentials. The ExposesCredential edge here documents the control-plane credential-grab path; it\
    \ does NOT by itself yield data access \u2014 the attacker must also have network reach to port 6379/6380,\
    \ which is modeled separately by gcp-memorystore-auth-string-grants-data-read and gcp-memorystore-auth-string-grants-data-write.\
    \ Do NOT apply a key_permission gate: Memorystore does not use CMEK. Never emit ExposedToInternet."
  narrative: '{instance.name} exposes the Redis AUTH string (UUID) credential. Any principal holding redis.instances.getAuthString
    can retrieve it via the Memorystore API; any in-VPC client that possesses this string can authenticate
    to {instance.name} and access all Redis keys.'
move · open · esc close