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.
match
A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.
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 — 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.'