gcp-kms-sign-forge-identity
Signing as a key that anchors an identity (JWKS/JWT/code-signing) forges that identity.
match
A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.
where
CryptoKey.purpose == ASYMMETRIC_SIGN — a MAC key has no public key and can NEVER be a trust anchor; SKIP MAC-derived
CanSignAs edges (gcp-kms-can-mac)
?key's public key is a published trust anchor for an identity (e.g. a JWKS/JWT issuer, workload-identity signer, code-signing identity) — established from evidence, not assumed
the anchored identity resolves to a ServiceAccount / ApplicationIdentity
emit
| source type | Identity |
|---|---|
| source | <principal> |
| target | <identity anchored by the signing key (ServiceAccount/ApplicationIdentity)> |
| permissions | cloudkms.cryptoKeyVersions.useToSign |
| conditions | iam_permission resource_policy key_permission trust_relationship |
| state logic | Inherits CanSignAs state. ACTIVE only with evidence the public key is a trust anchor accepted by a relying party; POTENTIAL when the anchor relationship is unconfirmed. BLOCKED if useToSign is denied. |
Narrative
{principal.name} can sign as {key.name}, whose public key anchors {identity.name}; forging a signed token impersonates {identity.name}.
Raw rule rules/derived/gcp/kms.yaml
id: gcp-kms-sign-forge-identity
emits: CanImpersonate
description: Signing as a key that anchors an identity (JWKS/JWT/code-signing) forges that identity.
match:
- - principal: null
- CanSignAs
- key: null
where:
- "CryptoKey.purpose == ASYMMETRIC_SIGN \u2014 a MAC key has no public key and can NEVER be a trust anchor;\
\ SKIP MAC-derived CanSignAs edges (gcp-kms-can-mac)"
- "?key's public key is a published trust anchor for an identity (e.g. a JWKS/JWT issuer, workload-identity\
\ signer, code-signing identity) \u2014 established from evidence, not assumed"
- the anchored identity resolves to a ServiceAccount / ApplicationIdentity
emit:
source_type: Identity
source: <principal>
target: <identity anchored by the signing key (ServiceAccount/ApplicationIdentity)>
permissions:
- cloudkms.cryptoKeyVersions.useToSign
conditions:
- iam_permission
- resource_policy
- key_permission
- trust_relationship
state_logic: Inherits CanSignAs state. ACTIVE only with evidence the public key is a trust anchor accepted
by a relying party; POTENTIAL when the anchor relationship is unconfirmed. BLOCKED if useToSign is
denied.
confidence: min(contributing_confidences) * 0.75
derived_from:
- <CanSignAs edge_id>
- <public-key-as-trust-anchor evidence>
false_positive_note: "Do NOT emit merely because a key can sign \u2014 most signing keys are not identity\
\ anchors. Requires concrete evidence (JWKS URI, OIDC config, code-signing trust) that a relying party\
\ accepts signatures from this key AS the target identity. Otherwise keep POTENTIAL or omit."
narrative: '{principal.name} can sign as {key.name}, whose public key anchors {identity.name}; forging
a signed token impersonates {identity.name}.'