aws-timestream-read-data-contains-secret

Reading data from a Timestream table that contains secret material yields the ability to read those secrets, enabling credential-chain pivots.

derived aws emits CanReadSecret

match

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

{'principal': None} CanReadData {'table': None} {'table': None} ContainsSecret {'secret': None}

where

node_type(?table) == Data ?table.provider_type == 'AWS::Timestream::Table' node_type(?secret) == Secret

emit

source typeIdentity
target typeSecret
source?principal
target?secret
conditionsiam_permission key_permission
state logicINHERIT_WEAKEST(CanReadData, ContainsSecret): if CanReadData is CONDITIONAL(key_permission) (table encrypted with CMK, decrypt not yet confirmed) then CONDITIONAL(key_permission); if CanReadData is BLOCKED then BLOCKED; else ACTIVE. ContainsSecret is a zero-cost structural link and never downgrades on its own.

Narrative

{principal.name} can read data from {table.name} ({perm:CanReadData}), and {table.name} contains {secret.name} (secret material ingested as measures or dimensions); {principal.name} can therefore read {secret.name}.

Raw rule rules/derived/aws/timestream.yaml

id: aws-timestream-read-data-contains-secret
emits: CanReadSecret
description: Reading data from a Timestream table that contains secret material yields the ability to
  read those secrets, enabling credential-chain pivots.
match:
- - principal: null
  - CanReadData
  - table: null
- - table: null
  - ContainsSecret
  - secret: null
where:
- node_type(?table) == Data
- ?table.provider_type == 'AWS::Timestream::Table'
- node_type(?secret) == Secret
emit:
  source_type: Identity
  target_type: Secret
  source: ?principal
  target: ?secret
  permissions: []
  conditions:
  - iam_permission
  - key_permission
  state_logic: 'INHERIT_WEAKEST(CanReadData, ContainsSecret): if CanReadData is CONDITIONAL(key_permission)
    (table encrypted with CMK, decrypt not yet confirmed) then CONDITIONAL(key_permission); if CanReadData
    is BLOCKED then BLOCKED; else ACTIVE. ContainsSecret is a zero-cost structural link and never downgrades
    on its own.'
  confidence: min(contributing_confidences) * 0.95
  derived_from:
  - ?principal CanReadData ?table
  - ?table ContainsSecret ?secret
  false_positive_note: 'Only emit when the ContainsSecret link is explicitly evidenced (analyst or automated
    scan asserted that the table''s data includes credential material); do not emit speculatively. Inherit
    the key_permission gate from CanReadData: if the table is CMK-encrypted and CanReadData is CONDITIONAL(key_permission),
    so is CanReadSecret; cite credential-chains:decrypt-gates-secret-read to upgrade when the decrypt
    is confirmed.'
  narrative: '{principal.name} can read data from {table.name} ({perm:CanReadData}), and {table.name}
    contains {secret.name} (secret material ingested as measures or dimensions); {principal.name} can
    therefore read {secret.name}.'
move · open · esc close