gcp-gcs-escalate-via-hmac-key

Generating an HMAC key for a Service Account with greater GCS-scoped access and using it via the S3-compatible GCS API constitutes privilege escalation (storage-scoped only, not full SA impersonation).

derived gcp emits CanEscalateTo

match

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

{'principal': None} CanCreateCredentialFor {'sa': None}

where

edge comes from gcp-gcs-hmac-key-create (scope_qualifier: gcs_s3_compatible_api_only) ?sa has read/write/admin permissions on GCS buckets that ?principal cannot access (as evidenced by CanReadData/CanWriteData roles or bucket IAM bindings)

emit

source typeIdentity
target typeIdentity
source?principal
target?sa
permissionsstorage.hmacKeys.create
conditionsiam_permission role_compatibility
state logicInherits state from the CanCreateCredentialFor contributor (gcp-gcs-hmac-key-create): ACTIVE when hmacKeys.create is confirmed and the target SA has demonstrably greater GCS access (via sampled bucket IAM bindings or role assignments) than the calling principal; CONDITIONAL when actAs grant uncertainty downgrades CanCreateCredentialFor; BLOCKED if hmacKeys.create is denied. Scope limited to GCS S3-compatible operations (not full SA impersonation across all Google APIs — HMAC keys authenticate only to the GCS S3-compatible XML API endpoint).

Narrative

{principal.name} can generate an HMAC key for {sa.name} (which has greater GCS-scoped access to buckets). Using the key's S3-compatible credential, {principal.name} can access buckets {sa.name} can reach - GCS storage-scoped privilege escalation (NOT full SA impersonation across Google APIs).

Raw rule rules/derived/gcp/gcs.yaml

id: gcp-gcs-escalate-via-hmac-key
emits: CanEscalateTo
description: Generating an HMAC key for a Service Account with greater GCS-scoped access and using it
  via the S3-compatible GCS API constitutes privilege escalation (storage-scoped only, not full SA impersonation).
match:
- - principal: null
  - CanCreateCredentialFor
  - sa: null
where:
- 'edge comes from gcp-gcs-hmac-key-create (scope_qualifier: gcs_s3_compatible_api_only)'
- ?sa has read/write/admin permissions on GCS buckets that ?principal cannot access (as evidenced by CanReadData/CanWriteData
  roles or bucket IAM bindings)
emit:
  source_type: Identity
  target_type: Identity
  source: ?principal
  target: ?sa
  permissions:
  - storage.hmacKeys.create
  conditions:
  - iam_permission
  - role_compatibility
  scope_qualifier: gcs_s3_compatible_api_only
  state_logic: "Inherits state from the CanCreateCredentialFor contributor (gcp-gcs-hmac-key-create):\
    \ ACTIVE when hmacKeys.create is confirmed and the target SA has demonstrably greater GCS access (via\
    \ sampled bucket IAM bindings or role assignments) than the calling principal; CONDITIONAL when actAs\
    \ grant uncertainty downgrades CanCreateCredentialFor; BLOCKED if hmacKeys.create is denied. Scope\
    \ limited to GCS S3-compatible operations (not full SA impersonation across all Google APIs \u2014\
    \ HMAC keys authenticate only to the GCS S3-compatible XML API endpoint)."
  confidence: min(contributing_confidences) * 0.85
  derived_from:
  - '?principal CanCreateCredentialFor ?sa (via gcp-gcs-hmac-key-create, scope: gcs_s3_api)'
  - ?sa has greater GCS bucket access than ?principal
  false_positive_note: "CRITICAL: HMAC keys authenticate ONLY to the GCS S3-compatible XML API (s3.googleapis.com\
    \ / storage.googleapis.com S3 endpoint). The JSON API at storage.googleapis.com/storage/v1 is a separate\
    \ authentication domain. A HMAC key does NOT grant iam.*, cloudfunctions.*, or other GCP APIs \u2014\
    \ privilege escalation is STORAGE-SCOPED ONLY, not full SA impersonation. This rule emits CanEscalateTo\
    \ (not full CanImpersonate) to signal GCS-scoped escalation. DO NOT compare broad IAM privilege_level\
    \ fields across different API families \u2014 instead, sample bucket IAM bindings to confirm the target\
    \ SA has greater storage.objects.get / storage.objects.create reach than the principal. Escalation\
    \ is spurious if both SAs have identical GCS bucket access \u2014 emit POTENTIAL or CONDITIONAL, not\
    \ ACTIVE. can-control.yaml and credential-chains.yaml handle broader (full-API) escalation roll-ups;\
    \ cite them for GCS-scoped findings that transition to org-level escalation, do not duplicate."
  narrative: "{principal.name} can generate an HMAC key for {sa.name} (which has greater GCS-scoped access\
    \ to buckets). Using the key's S3-compatible credential, {principal.name} can access buckets {sa.name}\
    \ can reach \u2014 GCS storage-scoped privilege escalation (NOT full SA impersonation across Google\
    \ APIs)."
move · open · esc close