gcp-firestore-explicit-contains-secret

A Firestore database contains collections or document field names whose names indicate credential material (API keys, SA keys, OAuth tokens, database passwords).

explicit gcp emits ContainsSecret

match (record)

{ "api": "firestore.projects.databases.get + datastore.namespaces.list", "field": "collectionGroup.collectionId | kind.name", "resource_type": "google.firestore.Database" }

where

collection or kind name matches a credential-indicator pattern: e.g. 'apiKeys', 'serviceAccountKeys', 'secrets', 'credentials', 'tokens', 'oauthTokens', 'passwords', 'privateKeys', 'accessKeys' OR database/collection labels or annotations explicitly classify content as credential storage

emit

source typeData
target typeSecret
source<Firestore Database / NoSQLDatabase node>
target<Secret node (heuristic classification from collection name)>
state logicACTIVE when collection/kind name pattern match is strong (e.g. exact names 'apiKeys', 'serviceAccountKeys', 'secrets', 'credentials'); POTENTIAL when the match is weak (generic name like 'config', 'settings', 'data' that may or may not contain secrets). Confidence: 0.60 for weak name-only match; 0.80 for strong name match (exact credential- indicator term); 0.90 when collection name + database labels corroborate.

Narrative

Firestore database {database.name} contains a collection whose name indicates credential material (e.g. 'apiKeys', 'serviceAccountKeys', 'credentials'); a principal with datastore.entities.get can read these documents and potentially obtain credentials for another identity. See credential-chains.yaml for the roll-up to CanImpersonate.

Raw rule rules/explicit/gcp-firestore.yaml

id: gcp-firestore-explicit-contains-secret
emits: ContainsSecret
description: A Firestore database contains collections or document field names whose names indicate credential
  material (API keys, SA keys, OAuth tokens, database passwords).
match_record:
  api: firestore.projects.databases.get + datastore.namespaces.list
  resource_type: google.firestore.Database
  field: collectionGroup.collectionId | kind.name
where:
- 'collection or kind name matches a credential-indicator pattern: e.g. ''apiKeys'', ''serviceAccountKeys'',
  ''secrets'', ''credentials'', ''tokens'', ''oauthTokens'', ''passwords'', ''privateKeys'', ''accessKeys'''
- OR database/collection labels or annotations explicitly classify content as credential storage
emit:
  source_type: Data
  target_type: Secret
  source: <Firestore Database / NoSQLDatabase node>
  target: <Secret node (heuristic classification from collection name)>
  permissions: []
  conditions: []
  state_logic: 'ACTIVE when collection/kind name pattern match is strong (e.g. exact names ''apiKeys'',
    ''serviceAccountKeys'', ''secrets'', ''credentials''); POTENTIAL when the match is weak (generic name
    like ''config'', ''settings'', ''data'' that may or may not contain secrets). Confidence: 0.60 for
    weak name-only match; 0.80 for strong name match (exact credential- indicator term); 0.90 when collection
    name + database labels corroborate.'
  confidence: "0.70 (heuristic \u2014 raise to 0.85 when collection name exactly matches a credential-indicator\
    \ term)"
  derived_from:
  - google.firestore.Database collectionGroup.collectionId or kind.name heuristic classification
  false_positive_note: "HEURISTIC assertion \u2014 NEVER read document content to confirm. A collection\
    \ named 'users' does NOT indicate credentials; a collection named 'apiKeys' or 'serviceAccountKeys'\
    \ very likely does. Emit with POTENTIAL state for weak matches; ACTIVE for strong matches where the\
    \ collection name is explicitly a credential-indicator term. Do NOT emit CanReadSecret directly from\
    \ this rule \u2014 only ContainsSecret. The credential-chains linchpin (read-secret-yields-identity)\
    \ then chains ContainsSecret + CanReadData -> CredentialsFor -> CanImpersonate. ALWAYS cite credential-chains\
    \ in derived_from for the roll-up. Firestore collection names visible via datastore.namespaces.list\
    \ / indexes.list without datastore.entities.get \u2014 collector can enumerate collection structure\
    \ without reading documents."
  narrative: Firestore database {database.name} contains a collection whose name indicates credential
    material (e.g. 'apiKeys', 'serviceAccountKeys', 'credentials'); a principal with datastore.entities.get
    can read these documents and potentially obtain credentials for another identity. See credential-chains.yaml
    for the roll-up to CanImpersonate.
move · open · esc close