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).
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 type | Data |
|---|---|
| target type | Secret |
| source | <Firestore Database / NoSQLDatabase node> |
| target | <Secret node (heuristic classification from collection name)> |
| 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. |
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.