aws-kinesis-cross-account-read-trust
A Kinesis stream resource policy granting read actions (GetRecords/GetShardIterator/SubscribeToShard) to a foreign account enables that account to read the stream's records, supporting data exfiltration.
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'
node_type(?stream_policy) == ResourcePolicy
?stream_policy grants kinesis:GetRecords or kinesis:GetShardIterator or kinesis:SubscribeToShard 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:GetRecords kinesis:GetShardIterator kinesis:SubscribeToShard |
| conditions | resource_policy condition_expression |
| state logic | ACTIVE when the stream resource policy unconditionally grants kinesis:GetRecords, kinesis:GetShardIterator, or kinesis:SubscribeToShard 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. BLOCKED by an SCP or explicit deny in the stream-owner's account that prevents cross-account GetRecords. This edge asserts cross-boundary read TRUST; CanReadData cross- boundary is rolled up by data-plane rules and credential-chains (if records carry secrets). |
Narrative
The resource policy on Kinesis stream {stream.name} grants kinesis:GetRecords, kinesis:GetShardIterator, or kinesis:SubscribeToShard to a principal in a foreign AWS account. That external principal can read records from this stream, enabling data exfiltration (especially if records carry sensitive data or credentials).
Raw rule rules/derived/aws/kinesis.yaml
id: aws-kinesis-cross-account-read-trust
emits: CrossAccountTrust
description: A Kinesis stream resource policy granting read actions (GetRecords/GetShardIterator/SubscribeToShard)
to a foreign account enables that account to read the stream's records, supporting data exfiltration.
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:GetRecords or kinesis:GetShardIterator or kinesis:SubscribeToShard 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:GetRecords
- kinesis:GetShardIterator
- kinesis:SubscribeToShard
conditions:
- resource_policy
- condition_expression
state_logic: ACTIVE when the stream resource policy unconditionally grants kinesis:GetRecords, kinesis:GetShardIterator,
or kinesis:SubscribeToShard 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. BLOCKED by an SCP or explicit deny in the stream-owner's
account that prevents cross-account GetRecords. This edge asserts cross-boundary read TRUST; CanReadData
cross- boundary is rolled up by data-plane rules and credential-chains (if records carry secrets).
confidence: min(contributing_confidences)
derived_from:
- ?stream_policy HasPolicy ?stream (kinesis:GetResourcePolicy evidence)
- "data-plane:CanReadData-rollup (downstream CanReadData \u2014 cited not re-derived)"
false_positive_note: 'This rule asserts ONLY the cross-boundary read TRUST from the resource policy.
CanReadData cross-boundary is emitted by the data-plane rules and credential- chains, not here. Honor
aws:PrincipalOrgID / aws:SourceAccount conditions as real controls: a policy scoped to a specific
sibling account is not open read access (downgrade to CONDITIONAL). A read-only cross-account grant
(GetRecords alone without GetShardIterator) has limitations but is still a capability (GetRecords
requires a pre-obtained shard iterator from GetShardIterator, but an attacker holding both can read
freely). Distinguish from rule 2 (publish-trust): this rule covers read-only access, while rule 2
covers publish/trigger access.'
narrative: The resource policy on Kinesis stream {stream.name} grants kinesis:GetRecords, kinesis:GetShardIterator,
or kinesis:SubscribeToShard to a principal in a foreign AWS account. That external principal can read
records from this stream, enabling data exfiltration (especially if records carry sensitive data or
credentials).