Get started
Download.
Verify. Run.
One static binary, no installation. Copy it to the host, run it with sudo, and read the results in the terminal UI or as JSON. Commands below follow the architecture you pick.
01Requirements
Ubuntu 18.04, 20.04, 22.04, 24.04, 26.04, on amd64 or arm64. Run dpkg --print-architecture on the host to see which binary it needs. Other architectures, including 32-bit armhf, are not supported.
| Output | Host | Binary |
|---|---|---|
amd64 | x86-64 | ubuntu-sys-audit-linux-amd64 |
arm64 | 64-bit ARM | ubuntu-sys-audit-linux-arm64 |
Run it with sudo for full coverage. Without root it still runs, but items it cannot read are marked “Not checked” and the report warns you. The host needs no agent, compiler or extra packages.
02Download and run
Download the binary and the checksums from the latest release, check them, and run.
curl -fsSLO https://github.com/guanting112/ubuntu-sys-audit/releases/latest/download/ubuntu-sys-audit-linux-amd64curl -fsSLO https://github.com/guanting112/ubuntu-sys-audit/releases/latest/download/SHA256SUMSsha256sum --ignore-missing -c SHA256SUMSchmod +x ubuntu-sys-audit-linux-amd64sudo ./ubuntu-sys-audit-linux-amd64The opening screen disappears on its own after a moment, or on any key. The scan is already running behind it, so it costs no time.
03Verify the binary
SHA256SUMS only catches a corrupted download, because it sits next to the binaries. To confirm a binary was built by this repository’s workflow (releases after v0.1.3), check its build provenance attestation:
gh attestation verify ubuntu-sys-audit-linux-amd64 -R guanting112/ubuntu-sys-audit Releases from v0.1.4 on also carry the attestation as ubuntu-sys-audit.sigstore.json, one file for both binaries. With it, gh needs no GitHub login, so you can verify on the host itself:
curl -fsSLO https://github.com/guanting112/ubuntu-sys-audit/releases/latest/download/ubuntu-sys-audit.sigstore.jsongh attestation verify ubuntu-sys-audit-linux-amd64 -R guanting112/ubuntu-sys-audit --bundle ubuntu-sys-audit.sigstore.json04Read the results
On a terminal it opens the TUI: categories on the left, findings in the middle, and the selected finding’s detail, remediation and evidence on the right.
| Keys | Action |
|---|---|
| ↑↓ or j k | Move |
| tab | Switch pane |
| f | Filter by severity |
| / | Search |
| s | Save JSON to the current directory |
| q | Quit |
Not checked never means passed. Items that lacked permission, timed out or could not reach the network are shown as “Not checked” (skipped in JSON) and make the exit code 3 unless there are critical or high findings.
05Scan a fleet over SSH
The tool writes JSON automatically when there is no TTY, so you can collect reports over SSH:
for h in web-01 web-02 db-01; do ssh "$h" 'sudo "./ubuntu-sys-audit-linux-$(dpkg --print-architecture)"' > "audit-$h.json" echo "$h exit=$?"doneThe loop requires passwordless sudo on the host. If sudo asks for a password, allocate a TTY and save the report to a file, then fetch it. A TTY would otherwise mix the password prompt into stdout:
ssh -t "$h" 'sudo "./ubuntu-sys-audit-linux-$(dpkg --print-architecture)" --json -o audit.json > /dev/null'scp "$h:audit.json" "audit-$h.json" The report has mode 0600 and its owner is set back to the user who ran sudo, so scp can fetch it directly. -o only creates new files, so remove an old report first.
Exit codes
| Code | Meaning |
|---|---|
| 0 | Nothing to act on. |
| 1 | Medium findings. |
| 2 | Critical or high findings. |
| 3 | Some items could not be checked, so do not treat the host as clean. |
| 130 | The scan was aborted. |
06Check a specific CVE
When a CVE is announced, ask each host about it directly:
sudo ./ubuntu-sys-audit-linux-amd64 --cve CVE-2026-98432,CVE-2024-6387This runs only the lookup. It reads Canonical’s CVE data for the release, which also lists CVEs with no fix released yet, and answers each CVE: affected with a fix available, affected with no fix released, fixed in the installed version, or not affected. An affected host gets the CVE’s own priority as the severity, so exit code 2 marks the hosts a high or critical CVE reaches.
The normal scan does not list unfixed CVEs, because every host has hundreds of them in the kernel alone. Ubuntu’s data does not tell a fix in progress from a CVE still being triaged, so “no fix released” may turn out not to apply.
07Hosts without internet access
On a machine with internet access, download the OVAL file for the host’s release, copy it over and point the tool at it. The report warns you when the data is more than 14 days old.
| Release | Codename | USN feed |
|---|---|---|
| 18.04 | bionic | com.ubuntu.bionic.usn.oval.xml.bz2 |
| 20.04 | focal | com.ubuntu.focal.usn.oval.xml.bz2 |
| 22.04 | jammy | com.ubuntu.jammy.usn.oval.xml.bz2 |
| 24.04 | noble | com.ubuntu.noble.usn.oval.xml.bz2 |
| 26.04 | resolute | com.ubuntu.resolute.usn.oval.xml.bz2 |
# bionic=18.04 focal=20.04 jammy=22.04 noble=24.04 resolute=26.04curl -fsSLO https://security-metadata.canonical.com/oval/com.ubuntu.jammy.usn.oval.xml.bz2sudo ./ubuntu-sys-audit-linux-amd64 --offline --oval-file com.ubuntu.jammy.usn.oval.xml.bz2 # --cve reads the CVE feed insteadcurl -fsSLO https://security-metadata.canonical.com/oval/com.ubuntu.jammy.cve.oval.xml.bz2sudo ./ubuntu-sys-audit-linux-amd64 --offline --oval-file com.ubuntu.jammy.cve.oval.xml.bz2 --cve CVE-2026-9843208Output formats
Without a TTY the output is JSON. With one, the TUI opens unless you ask for --json or --text. -o saves a JSON copy alongside any of them, and never overwrites an existing file.
sudo ./ubuntu-sys-audit-linux-amd64 --json > report.json # JSON to stdoutsudo ./ubuntu-sys-audit-linux-amd64 --text --min-severity high # plain text, high and abovesudo ./ubuntu-sys-audit-linux-amd64 -o audit.json # TUI, and also save JSONCommon forms of credentials in command lines and configuration are masked, but this cannot catch every form. Treat reports as sensitive.
09All options
| Option | Description |
|---|---|
--json | Write JSON to stdout without opening the TUI. |
--text | Write plain text to stdout without opening the TUI. |
--min-severity LV | In text mode, list only this level and above: critical, high, medium, info, ok (default medium). Items that could not be checked are always listed. |
--cve LIST | Only look up these CVEs, separated by commas, including ones with no fix released yet. Downloads Canonical’s CVE data for this release (5 to 15 MB). |
-o, --output FILE | Also save the JSON report to a new FILE (mode 0600). An existing file is never overwritten. |
--offline | Do not use the network. CVEs are not checked unless --oval-file is given. |
--oval-file PATH | Use a local OVAL file (.xml or .xml.bz2). With --cve, this is the CVE feed. |
--proxy URL | HTTP proxy for downloading advisory data. |
--skip-fs | Skip the full filesystem scan (SUID, capabilities, temp directories). |
--fs-timeout TIME | Time limit for the full filesystem scan (default 5m). |
--no-netlink | Do not read BPF filters, which keeps the kernel from loading af_packet_diag. |
--version | Show the version. |