HackBlue

Tools · AWS detection and investigation · 11 / 24

CloudTrail Lake: two account ids on one row

userIdentity.accountId is the caller’s account. recipientAccountId is the account that received the call. Write both. Do not say “our account” from only one of them.

11 min read · practice only with authorization

The caller and the receiver

A CloudTrail row can carry two account ids. userIdentity.accountId is the account of the identity that made the call. recipientAccountId is the account that received it. In a single-account lab they are often the same. When a role in one account calls a service in another, they differ. The row is about that pair, not about “the account” as a single word.

Quoting only the caller’s account hides where the API landed. Quoting only the receiver hides who called.

Equal ids are still two fields

When the two values match, write both anyway, or write “same value in both fields.” A later row in the same note may differ. A reader who saw one id last time cannot tell whether you checked the other.

The principal ARN sits with the caller. It does not replace recipientAccountId. A role name from the caller’s account can act on a bucket or a trail in the receiving account.

What to file

File eventTime, eventName, both account ids, and the principal ARN if you need the caller. Say which field each number came from. If your question was “what happened in account A,” say whether A was the caller, the receiver, or both.

Worked case: a call that landed in the sandbox

A lab query returns one row. userIdentity.accountId is 111122223333. recipientAccountId is 222233334444, the sandbox you are reviewing. eventName is ListBuckets. A draft says the sandbox’s own user listed buckets, because the reviewer was looking at the sandbox id and grabbed the first account field in the JSON.

The note quotes both fields by name. The caller is an identity in 111122223333. The call was received in 222233334444. The sandbox did not originate the call. Any follow-up on “who in the sandbox” waits on a row where the caller’s account is the sandbox.

Snippet
eventTime: 2026-11-03T17:12:00Z
eventName: ListBuckets
userIdentity.accountId: 111122223333
recipientAccountId: 222233334444
write: caller in 111122223333, received by the sandbox
not: the sandbox's own user

Diagram

Name both account fields

  1. Caller

    The account on the identity.

    Field
    userIdentity.accountId
  2. Receiver

    The account that got the call.

    Field
    recipientAccountId
  3. Same value

    Still write both, or say they match.

    Note
    same value in both fields
  4. Question

    Say which account your sentence is about.

    Note
    caller, receiver, or both

Check yourself

1. Which field is the account that received the API call?

2. The two account ids match. What should the note say?

3. The sandbox id is only in recipientAccountId. What is fair?