# Verify a report against the originals

URL: /investigate/verify

Check a Foxborne report with the original files and standard tools. You confirm each file's SHA-256, find every excerpt at its location, test each threshold against the raw values and confirm the marking and, when needed, the audit trail.



Every excerpt in a Foxborne report names its file and the SHA-256 of that file, with a line, row or byte offset inside it. Anyone holding the originals can check each line with standard tools and no access to the deployment. This tutorial checks INC-0142 from the example dataset, from the hashes to the audit trail.

## What you will have [#what-you-will-have]

A report you have checked yourself. Each file's hash matches, each excerpt sits where the report says and each finding's threshold holds against the raw values. You will also have confirmed the marking and, if the review calls for it, the audit trail.

## What you need [#what-you-need]

* The report or the case file, in HTML or JSON.
* The original files, from where your program keeps them, such as the fleet log archive. Take them from there rather than from the report's author.
* A shell on Linux or macOS, or PowerShell on Windows.
* For the audit trail only, the **Auditor** or **Admin** role in the deployment.

## Check the report [#check-the-report]

<Steps>
  <Step title="List the sources the report names">
    The **Sources** line in the report header gives each file with a short form of its SHA-256: the first 12 and last 4 hex digits. Foxborne took the hash when the file arrived. INC-0142 names four files:

    ```text title="INC-0142, Sources" caption="Example dataset"
    Flight log          14_13_19.ulg               sha256:f60310be1687…f69f
    Companion journal   uas04-orin-journal.json    sha256:a0741c955f33…cdf4
    Process samples     uas04-orin-samples.jsonl   sha256:c4d46f086f9c…8830
    Ground receive log  rc1-receive.jsonl          sha256:a96027361d50…8905
    ```

    **3 Evidence** repeats the short hash on every line. The full 64-digit hash is in each event's **Copy reference** and in the run's **Source files** table, where **Copy SHA-256** copies it.
  </Step>

  <Step title="Hash each original">
    Compute the SHA-256 of each file you hold.

    <Tabs items="['Linux', 'macOS', 'Windows']">
      <Tab value="Linux">
        ```bash title="In the folder that holds the originals"
        sha256sum 14_13_19.ulg uas04-orin-journal.json uas04-orin-samples.jsonl rc1-receive.jsonl
        ```
      </Tab>

      <Tab value="macOS">
        ```bash title="In the folder that holds the originals"
        shasum -a 256 14_13_19.ulg uas04-orin-journal.json uas04-orin-samples.jsonl rc1-receive.jsonl
        ```
      </Tab>

      <Tab value="Windows">
        ```powershell title="PowerShell, in the folder that holds the originals"
        Get-FileHash -Algorithm SHA256 -Path .\14_13_19.ulg, .\uas04-orin-journal.json, .\uas04-orin-samples.jsonl, .\rc1-receive.jsonl
        ```

        PowerShell prints the hash in capital letters. Compare it without regard to case.
      </Tab>
    </Tabs>

    Each command prints one 64-digit hash per file. For the companion journal, the example dataset records this line:

    ```text title="Expected output for the journal" caption="Example dataset"
    a0741c955f3301a6dffc1a85c93e0eb315e53227c790f517ff7d484e98e0cdf4  uas04-orin-journal.json
    ```
  </Step>

  <Step title="Compare the hashes">
    Match the first 12 and last 4 digits against the **Sources** line, and the whole hash against **Copy reference** when you have it. Foxborne hashes every original on arrival and never rewrites it, so a match shows that you hold the same bytes the report was built from.

    A mismatch means a different file: a later export, an edited copy or a truncated transfer. Stop there, find the original and hash it again.
  </Step>

  <Step title="Find each text excerpt at its location">
    For the journal, the samples and the receive log, the location is a line or rows in the file. Print it and compare the excerpt byte for byte.

    | Evidence                   | File                       | Location              | On Linux or macOS                              |
    | -------------------------- | -------------------------- | --------------------- | ---------------------------------------------- |
    | E3, the kernel kill        | `uas04-orin-journal.json`  | Line 18,314           | `sed -n '18314p' uas04-orin-journal.json`      |
    | E1, memory above threshold | `uas04-orin-samples.jsonl` | Rows 2,811 to 2,813   | `sed -n '2811,2813p' uas04-orin-samples.jsonl` |
    | E6, the heartbeat gap      | `rc1-receive.jsonl`        | Lines 1,118 and 1,119 | `sed -n '1118,1119p' rc1-receive.jsonl`        |

    In PowerShell, `(Get-Content .\uas04-orin-journal.json)[18313]` prints line 18,314, because PowerShell counts lines from zero.

    A journalctl JSON export holds one entry per line, so line 18,314 is the whole kill record. Its `MESSAGE` must match E3's excerpt exactly:

    ```text title="E3, the excerpt" caption="Example dataset, INC-0142"
    Out of memory: Killed process 2213 (perception_node) total-vm:11873248kB, anon-rss:6823516kB, file-rss:10240kB, shmem-rss:0kB, UID:1001 pgtables:14720kB oom_score_adj:0
    ```

    The same line carries `__REALTIME_TIMESTAMP` 1790260324118000, in microseconds since the epoch. That is 14:32:04.118 UTC on 24 Sep 2026, the time the report's sequence gives. Its `_BOOT_ID` begins 9b2e4c1d, the boot ID the process samples share with the journal.
  </Step>

  <Step title="Find the flight log excerpt">
    A flight log is binary, so its excerpt is the decoded message rather than raw text. E2 gives **Message 1,146,099, byte 53,503,302** in `14_13_19.ulg`: message 1,146,099 of 1,388,540, starting 53,503,302 bytes into the file.

    Decode the message that starts at that offset with your ULog tools, then compare its topic, timestamp and fields with the record. The report quotes the topic and the first three fields, and the evidence inspector shows the whole record:

    ```text title="E2, the record in the evidence inspector" caption="Example dataset, INC-0142"
    topic      obstacle_distance (multi_id 0)
    timestamp  1,132,793,000 µs   boot + 1132.793 s
    message    1,146,099 of 1,388,540
    offset     byte 53,503,302

    frame                       12 (MAV_FRAME_BODY_FRD)
    sensor_type                 0 (laser)
    min_distance                20 cm
    max_distance                2000 cm
    increment                   5.0 deg
    distances[0..7]             412 406 399 401 388 1999 1999 1999
    ```

    The timestamp counts microseconds from boot. [PX4 ULog](/collect/formats/px4-ulog) explains how Foxborne anchors it to UTC.
  </Step>

  <Step title="Check each rule and its threshold">
    Each finding names the rule, the version and the threshold that produced it. The console shows them in the evidence inspector's **Rule** block and on the event page. There, E1's **Rule** reads `memory_pressure 1.1: RSS at or above 6,144 MiB for 3 samples`.

    Test the threshold against the rows you printed. Rows 2,811 to 2,813 carry `rss_kib` values of 6,336,512, 6,555,648 and 6,814,720. Divided by 1,024, those are 6,188, 6,402 and 6,655 MiB: three samples in a row at or above 6,144 MiB, as the rule requires.

    E6 checks the same way. `telemetry_gap 1.3` fires on "More than 3 s without a HEARTBEAT". The two receive lines read `recv_utc` 14:32:03.912 and 14:32:10.874, 6.962 s apart.

    A finding keeps the version and threshold that made it. If the **Rules** page now shows a later version, the report still stands on the one it names. See [Thresholds, scopes and overrides](/rules/configure).
  </Step>

  <Step title="Confirm the marking">
    The marking sits at the top and bottom of every page, with the designation indicator on the first page.

    <Figure caption="The marking banner and designation indicator of a CUI report. The organization, office and contact shown here are examples.">
      <MarkingBanner level="cui" />

      <DesignationIndicator by="Your organization" office="Your office" category="EXPT" control="FEDCON" poc="poc@example.mil" />
    </Figure>

    Compare the category, the dissemination control and the point of contact with your program's marking guide. The marking comes from **Settings** in the deployment. If it is wrong, an admin corrects it and the report is exported again.
  </Step>

  <Step title="Verify the audit trail, if the review needs it">
    Someone with the **Auditor** or **Admin** role opens **Audit log** in the deployment.

    1. Type the incident ID into **Filter by person, action or object**, or pick **Evidence** or **Reports**.
    2. Read the entries, such as **Viewed evidence**, **Edited report**, **Aligned clock by hand** and **Exported case file**, each with its person, time and detail.
    3. Select **Verify chain**. The console reads "Recomputing each hash from the entry and the hash before it." and ends with &#x2A;*Chain intact. Every entry matches.**
    4. To check the chain offline, select **Export** and choose **JSON Lines** or **CSV**. "The export includes each entry’s hash and the hash before it, so it can be verified offline."

    Each entry's **Entry** cell shows its number and the first 8 digits of its hash. Its tooltip holds the full hash and the hash before it. See [Audit log](/security/audit-log).
  </Step>
</Steps>

## What you have now [#what-you-have-now]

* Each file's SHA-256 matches the report, so you hold the originals it was built from.
* Each text excerpt matches its line or rows byte for byte, and the flight log excerpt matches its decoded message.
* Each finding's threshold holds against the raw values.
* The marking fits your program's guide.
* If the review needed it, the audit chain is intact.

## Next [#next]

<Cards>
  <Card title="Evidence integrity" href="/concepts/evidence-integrity" icon="shield">
    Hashing on arrival and write-once originals.
  </Card>

  <Card title="Audit log" href="/security/audit-log" icon="audit">
    How the hash chain works and how to verify it.
  </Card>

  <Card title="journalctl JSON exports" href="/collect/formats/journald" icon="terminal">
    The journal fields Foxborne reads.
  </Card>

  <Card title="PX4 ULog" href="/collect/formats/px4-ulog" icon="drone">
    What a flight log holds and how it is anchored.
  </Card>
</Cards>
