Verify a report against the originals
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#
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#
- 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#
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:
INC-0142, SourcesExample datasetText 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…89053 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.
Hash each original
Compute the SHA-256 of each file you hold.
In the folder that holds the originalsShell sha256sum 14_13_19.ulg uas04-orin-journal.json uas04-orin-samples.jsonl rc1-receive.jsonlIn the folder that holds the originalsShell shasum -a 256 14_13_19.ulg uas04-orin-journal.json uas04-orin-samples.jsonl rc1-receive.jsonlPowerShell, in the folder that holds the originalsPowerShell Get-FileHash -Algorithm SHA256 -Path .\14_13_19.ulg, .\uas04-orin-journal.json, .\uas04-orin-samples.jsonl, .\rc1-receive.jsonlPowerShell prints the hash in capital letters. Compare it without regard to case.
Each command prints one 64-digit hash per file. For the companion journal, the example dataset records this line:
Expected output for the journalExample datasetText a0741c955f3301a6dffc1a85c93e0eb315e53227c790f517ff7d484e98e0cdf4 uas04-orin-journal.jsonCompare 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.
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.jsonLine 18,314 sed -n '18314p' uas04-orin-journal.jsonE1, memory above threshold uas04-orin-samples.jsonlRows 2,811 to 2,813 sed -n '2811,2813p' uas04-orin-samples.jsonlE6, the heartbeat gap rc1-receive.jsonlLines 1,118 and 1,119 sed -n '1118,1119p' rc1-receive.jsonlIn 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
MESSAGEmust match E3's excerpt exactly:E3, the excerptExample dataset, INC-0142Text 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:0The same line carries
__REALTIME_TIMESTAMP1790260324118000, 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_IDbegins 9b2e4c1d, the boot ID the process samples share with the journal.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:
E2, the record in the evidence inspectorExample dataset, INC-0142Text 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 1999The timestamp counts microseconds from boot. PX4 ULog explains how Foxborne anchors it to UTC.
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_kibvalues 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.3fires on "More than 3 s without a HEARTBEAT". The two receive lines readrecv_utc14: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.
Confirm the marking
The marking sits at the top and bottom of every page, with the designation indicator on the first page.
CUI- Controlled by
- Your organization
- Controlled by
- Your office
- CUI category
- EXPT
- Dissemination
- FEDCON
The marking banner and designation indicator of a CUI report. The organization, office and contact shown here are examples. 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.
Verify the audit trail, if the review needs it
Someone with the Auditor or Admin role opens Audit log in the deployment.
- Type the incident ID into Filter by person, action or object, or pick Evidence or Reports.
- Read the entries, such as Viewed evidence, Edited report, Aligned clock by hand and Exported case file, each with its person, time and detail.
- Select Verify chain. The console reads "Recomputing each hash from the entry and the hash before it." and ends with Chain intact. Every entry matches.
- 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.
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.