HackBlue

Tools · AWS detection and investigation · 05 / 24

GuardDuty: the four clocks on a finding

Copy CreatedAt, UpdatedAt, EventFirstSeen, and EventLastSeen as separate times, and mark a sample so practice output is not filed as a live incident.

11 min read · practice only with authorization

Write the record, not a retelling

A GuardDuty finding is a JSON record with an id. The case note should carry that id, the account, the Region, the type string, and the severity number, copied from get-findings. A sentence you wrote from memory is harder to check later, and it drops the id that lets someone open the same record.

Severity is a number on that record. Copy the number. Do not swap in a word such as “high” unless you also keep the number beside it, because the bands are a reading of the number, not a second field.

Snippet
aws guardduty get-findings --detector-id "$DET" --finding-ids "$FID" \
  --query 'Findings[0].{Id:Id,Account:AccountId,Region:Region,Type:Type,Sev:Severity}'

Four times, four meanings

CreatedAt is when GuardDuty opened this finding record. UpdatedAt is when the record was last changed, which can be the moment you generated a sample or the moment the count went up. Service.EventFirstSeen and Service.EventLastSeen bound the activity the finding is about.

Impact of mixing them: a note that says “this happened at 14:02” might be the time you clicked generate, not the activity window. Control: write all four, with their field names, and use the event window when you say when the activity was.

The sample marker is part of the note

create-sample-findings writes records so you can practice the shape. Those records are not an incident. The list criteria key service.additionalInfo.sample is true for them. Read Service.AdditionalInfo on the finding you opened and record that marker next to the id.

What not to trust: a type string that sounds urgent, on a record that is flagged as a sample. The type describes the scenario the sample was built from. The marker says it was generated for the lab.

Worked case: a sample generated this afternoon

In the sandbox you generate one sample and open it at 14:02 UTC. CreatedAt and UpdatedAt are both within a minute of 14:02. EventFirstSeen and EventLastSeen sit on an earlier date that shipped with the sample. The type name is long and specific. Nothing in the account was changed by that type name.

The note has one line: sample true, finding id, account, Region, type, severity number, and the four times labeled. It does not page anyone. It does not say the activity occurred at 14:02. When you are done, archive the samples so the next person does not mix them with a later real record.

Snippet
finding: <id>
account: 111122223333  region: us-east-1
sample: true
severity: <number from the record>
CreatedAt:       2026-11-04T14:02:11Z
UpdatedAt:       2026-11-04T14:02:11Z
EventFirstSeen:  <from Service>
EventLastSeen:   <from Service>

Diagram

Clocks on one GuardDuty finding

Label each time with the field it came from.

  • CreatedAt

    When this finding record was opened.

  • UpdatedAt

    When the record last changed, including a lab generate.

  • EventFirstSeen

    Start of the activity the finding describes.

  • EventLastSeen

    Most recent activity included in the finding.

Check yourself

1. Which pair bounds the activity the finding describes?

2. UpdatedAt on a sample you just generated usually means what?

3. What should the note say when service.additionalInfo.sample is true?