aws-kinesis-cross-account-publish-trust

A Kinesis stream resource policy granting kinesis:PutRecord(s) to a principal in another account is cross-account publish trust, enabling that external principal to trigger the stream's Lambda consumer.

derived aws emits CrossAccountTrust

match

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

{'stream_policy': None} HasPolicy {'stream': None}

where

node_type(?stream) == GenericMessaging ?stream.provider_type == 'AWS::Kinesis::Stream' node_type(?stream_policy) == ResourcePolicy ?stream_policy grants kinesis:PutRecord or kinesis:PutRecords to a Principal whose account != account(?stream)

emit

source typeResourcePolicy
target typeAccount
source?stream_policy
target<the external AWS account named in the stream resource policy>
permissionskinesis:PutRecord kinesis:PutRecords
conditionsresource_policy condition_expression
state logicACTIVE when the stream resource policy unconditionally grants kinesis:PutRecord or kinesis:PutRecords to a named external principal with no conditions beyond aws:PrincipalArn identity scoping. CONDITIONAL (condition_expression) when scoped by aws:SourceAccount, aws:SourceVpc, aws:PrincipalOrgID, or other conditions the external principal must satisfy. BLOCKED by an SCP or explicit deny in the stream-owner's account that prevents cross-account PutRecord. State never exceeds the weakest contributor. This edge ONLY asserts the cross-boundary publish trust; CanEnterAccount requires messaging-chains + can-control to roll up the CanWriteData + CanTrigger + CanExecuteAs chain separately.

Narrative

The resource policy on Kinesis stream {stream.name} grants kinesis:PutRecord or kinesis:PutRecords to a principal in a foreign AWS account. That external principal can publish records to this stream. If a Lambda event-source-mapping is active on {stream.name}, the external principal can trigger the bound Lambda consumer inside {stream.name}'s account (the full chain - messaging- chains + can-control - rolls this up to CanEnterAccount).

Raw rule rules/derived/aws/kinesis.yaml

id: aws-kinesis-cross-account-publish-trust
emits: CrossAccountTrust
description: A Kinesis stream resource policy granting kinesis:PutRecord(s) to a principal in another
  account is cross-account publish trust, enabling that external principal to trigger the stream's Lambda
  consumer.
match:
- - stream_policy: null
  - HasPolicy
  - stream: null
where:
- node_type(?stream) == GenericMessaging
- ?stream.provider_type == 'AWS::Kinesis::Stream'
- node_type(?stream_policy) == ResourcePolicy
- ?stream_policy grants kinesis:PutRecord or kinesis:PutRecords to a Principal whose account != account(?stream)
emit:
  source_type: ResourcePolicy
  target_type: Account
  source: ?stream_policy
  target: <the external AWS account named in the stream resource policy>
  permissions:
  - kinesis:PutRecord
  - kinesis:PutRecords
  conditions:
  - resource_policy
  - condition_expression
  state_logic: ACTIVE when the stream resource policy unconditionally grants kinesis:PutRecord or kinesis:PutRecords
    to a named external principal with no conditions beyond aws:PrincipalArn identity scoping. CONDITIONAL
    (condition_expression) when scoped by aws:SourceAccount, aws:SourceVpc, aws:PrincipalOrgID, or other
    conditions the external principal must satisfy. BLOCKED by an SCP or explicit deny in the stream-owner's
    account that prevents cross-account PutRecord. State never exceeds the weakest contributor. This edge
    ONLY asserts the cross-boundary publish trust; CanEnterAccount requires messaging-chains + can-control
    to roll up the CanWriteData + CanTrigger + CanExecuteAs chain separately.
  confidence: min(contributing_confidences)
  derived_from:
  - ?stream_policy HasPolicy ?stream (kinesis:GetResourcePolicy evidence)
  - messaging-chains:messaging-resource-policy-cross-boundary-trust (provider-agnostic form)
  - "can-control:enter-account-via-assume (downstream CanEnterAccount \u2014 cited not re-derived)"
  false_positive_note: "This rule asserts ONLY the cross-boundary publishing TRUST from the resource policy.\
    \ CanEnterAccount is NOT emitted here \u2014 it requires the separate chain: foreign-principal CanWriteData\
    \ stream \u2192 (rule 1) CanTrigger consumer \u2192 messaging-chains rule 2 CanExecuteAs \u2192 can-control\
    \ CanEnterAccount. Honor aws:PrincipalOrgID / aws:SourceAccount conditions as real controls: a policy\
    \ scoped to a specific sibling account is not open cross-account access (downgrade to CONDITIONAL).\
    \ A read-only cross-account grant (kinesis:GetRecords / kinesis:GetShardIterator to a foreign account)\
    \ does NOT feed this rule \u2014 that is cross-account read trust, a different threat model (CanReadData\
    \ / CanExfiltrate, handled by data-plane rules)."
  narrative: "The resource policy on Kinesis stream {stream.name} grants kinesis:PutRecord or kinesis:PutRecords\
    \ to a principal in a foreign AWS account. That external principal can publish records to this stream.\
    \ If a Lambda event-source-mapping is active on {stream.name}, the external principal can trigger\
    \ the bound Lambda consumer inside {stream.name}'s account (the full chain \u2014 messaging- chains\
    \ + can-control \u2014 rolls this up to CanEnterAccount)."
move · open · esc close