aws-kinesis-read-stream-data

kinesis:GetRecords + kinesis:GetShardIterator lets a principal read raw records from the stream, enabling data exfiltration or credential harvest if records carry sensitive content.

derived aws emits CanReadData

match

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

{'principal': None} HasPermission {'stream': None}

where

node_type(?stream) == GenericMessaging ?stream.provider_type == 'AWS::Kinesis::Stream' ?principal has EFFECTIVE kinesis:GetRecords AND kinesis:GetShardIterator on ?stream ARN

emit

source typeIdentity
target typeMessaging
source?principal
target?stream
permissionskinesis:GetRecords kinesis:GetShardIterator
conditionsiam_permission resource_policy key_permission
state logicACTIVE when both kinesis:GetRecords and kinesis:GetShardIterator are confirmed EFFECTIVE on the stream ARN (identity-based policy + no resource- policy deny + no SCP deny) AND the stream uses no KMS encryption (or the principal also holds kms:Decrypt on the stream's CMK — the key_permission gate). CONDITIONAL(key_permission) when the stream has server-side encryption (EncryptionType: KMS) and kms:Decrypt on the CMK is not confirmed — the principal can call GetRecords but receives ciphertext they cannot decrypt. credential-chains decrypt-gates-secret-read upgrades to ACTIVE when CanDecrypt is confirmed. CONDITIONAL(resource_policy) when a resource policy deny or a missing grant caps the effective permission.

Narrative

{principal.name} has effective kinesis:GetRecords and kinesis:GetShardIterator on {stream.name} and can read raw record batches from the stream. If records carry sensitive data, this enables CanExfiltrate (rolled up by the data-plane rules); if records carry embedded credentials (ContainsSecret), credential- chains read-secret-yields-identity produces CanImpersonate over the credential's target identity.

Raw rule rules/derived/aws/kinesis.yaml

id: aws-kinesis-read-stream-data
emits: CanReadData
description: kinesis:GetRecords + kinesis:GetShardIterator lets a principal read raw records from the
  stream, enabling data exfiltration or credential harvest if records carry sensitive content.
match:
- - principal: null
  - HasPermission
  - stream: null
where:
- node_type(?stream) == GenericMessaging
- ?stream.provider_type == 'AWS::Kinesis::Stream'
- ?principal has EFFECTIVE kinesis:GetRecords AND kinesis:GetShardIterator on ?stream ARN
emit:
  source_type: Identity
  target_type: Messaging
  source: ?principal
  target: ?stream
  permissions:
  - kinesis:GetRecords
  - kinesis:GetShardIterator
  conditions:
  - iam_permission
  - resource_policy
  - key_permission
  state_logic: "ACTIVE when both kinesis:GetRecords and kinesis:GetShardIterator are confirmed EFFECTIVE\
    \ on the stream ARN (identity-based policy + no resource- policy deny + no SCP deny) AND the stream\
    \ uses no KMS encryption (or the principal also holds kms:Decrypt on the stream's CMK \u2014 the key_permission\
    \ gate). CONDITIONAL(key_permission) when the stream has server-side encryption (EncryptionType: KMS)\
    \ and kms:Decrypt on the CMK is not confirmed \u2014 the principal can call GetRecords but receives\
    \ ciphertext they cannot decrypt. credential-chains decrypt-gates-secret-read upgrades to ACTIVE when\
    \ CanDecrypt is confirmed. CONDITIONAL(resource_policy) when a resource policy deny or a missing grant\
    \ caps the effective permission."
  confidence: min(contributing_confidences) * 0.95
  derived_from:
  - ?principal HasPermission ?stream (kinesis:GetRecords + kinesis:GetShardIterator effective permission)
  - "credential-chains:decrypt-gates-secret-read (KMS-encrypted stream gate \u2014 cited not re-derived)"
  false_positive_note: "Two permissions are required together: kinesis:GetShardIterator (to obtain a shard\
    \ cursor) AND kinesis:GetRecords (to read the batch). Granting only one does not yield data access.\
    \ For KMS-encrypted streams (EncryptionType: KMS), the caller also needs kms:Decrypt on the stream's\
    \ CMK \u2014 without it, GetRecords returns encrypted ciphertext and CanReadData must be CONDITIONAL(key_permission)\
    \ rather than ACTIVE. Enhanced fan-out consumers (kinesis:SubscribeToShard) provide an equivalent\
    \ read path but require a registered consumer ARN via kinesis:RegisterStreamConsumer first \u2014\
    \ model as a separate edge if SubscribeToShard is the confirmed access method. ListShards alone does\
    \ not grant data access."
  narrative: '{principal.name} has effective kinesis:GetRecords and kinesis:GetShardIterator on {stream.name}
    and can read raw record batches from the stream. If records carry sensitive data, this enables CanExfiltrate
    (rolled up by the data-plane rules); if records carry embedded credentials (ContainsSecret), credential-
    chains read-secret-yields-identity produces CanImpersonate over the credential''s target identity.'
move · open · esc close