Command Palette

Search for a command to run...

UnylyUnyly
Browse all

Fwxray

FreeNot checked

Diff two firmware images and surface exactly what changed: new binaries, flipped config flags, added certs, and shifted entropy regions.

GitHubEmbed

About

Diff two firmware images and surface exactly what changed: new binaries, flipped config flags, added certs, and shifted entropy regions.

README

FWXRAY

FWXRAY

Diff two firmware images and surface exactly what changed: new binaries, flipped config flags, added certs, and shifted entropy regions.

PyPI CI License: COCL 1.0 Suite

IoT / OT / Embedded — firmware, buses, and device security.

pip install cognis-fwxray
fwxray diff old.bin new.bin     # → human-readable OTA changelog in seconds

🔎 Example output

Real, reproducible output from the tool — runs offline:

$ fwxray-emit --version
fwxray 0.1.6
$ fwxray-emit --help
usage: fwxray [-h] [--version] COMMAND ...

X-ray two firmware images and produce a human-readable changelog of what an OTA touched: changed sections, flipped flags, and entropy shifts.

positional arguments:
  COMMAND
    diff      diff two firmware images
    feeds     manage the OSV / CISA-KEV data feeds (edge/air-gap)
    scan      diff two firmware images and enrich added components via OSV/KEV
    inspect   passively inspect a single firmware image (offline, read-only)
    pull      AUTHORIZED-ONLY: read a live firmware image off a device you own

options:
  -h, --help  show this help message and exit
  --version   show program's version number and exit

examples:
  fwxray diff old.bin new.bin
  fwxray diff old.bin new.bin --format json > changelog.json
  fwxray diff v1.bin v2.bin --block 2048 --entropy-threshold 0.5

Blocks above are real fwxray output — reproduce them from a clone.

Sample result format (illustrative values — run on your own data for real findings):

{
"findings": [
    {
        "id": "123456",
        "title": "Suspicious Network Traffic",
        "description": "Potential malicious activity detected on port 443.",
        "severity": "high",
        "created": "2023-02-15T14:30:00Z"
    },
    {
        "id": "789012",
        "title": "Unusual File Access",
        "description": "User 'johndoe' accessed a file with unusual permissions.",
        "severity": "medium",
        "created": "2023-02-15T14:35:00Z"
    }
]
}

Usage — step by step

  1. Install (Python 3.9+):
    pip install fwxray
    
  2. X-ray two firmware images and print a human-readable changelog of what an OTA touched (changed sections, flipped flags, entropy shifts, string deltas):
    fwxray diff old.bin new.bin
    
  3. Tune entropy-shift sensitivity and the block size for finer/coarser analysis:
    fwxray diff v1.bin v2.bin --block 2048 --entropy-threshold 0.5
    
  4. Read the output: the report groups changes under Sections / Flags / Entropy shifts / Strings. Use --format json for machine consumption; the process exits 1 when the two images differ (and 0 when byte-for-byte identical).
  5. Capture an OTA changelog in CI:
    fwxray diff old.bin new.bin --format json > changelog.json
    

Contents

Why fwxray?

Vendor 'security update' transparency — paste two .bin URLs in CI, get a human-readable changelog of what the OTA actually touched, perfect for viral 'they secretly added telemetry' threads.

fwxray is single-purpose, scriptable, and self-hostable: point it at a target, get prioritized results in the format your workflow already speaks (table · JSON · SARIF), gate CI on it, and let agents drive it over MCP.

Features

  • ✅ Shannon Entropy · Block Entropy Profile
  • ✅ Carve Sections (magic-signature firmware carving)
  • ✅ Extract Strings · Diff Strings · Diff Firmware
  • Passive single-image inspection (inspect) — entropy, sections, flags, and security indicators, fully offline
  • ✅ Component vulnerability enrichment via OSV + CISA-KEV and a bundled 262k-record offline vuln DB
  • Active acquisition (pull) — read a live image off a device you own, authorization-gated and OFF by default
  • ✅ Runs on Linux/macOS/Windows · Docker · devcontainer
  • ✅ Ports in Python, JavaScript, Go, Rust, and Shell (ports/)

Quick start

pip install cognis-fwxray
fwxray --version
fwxray diff old.bin new.bin                    # human-readable changelog
fwxray diff old.bin new.bin --format json      # machine-readable
fwxray diff old.bin new.bin --format sarif      # GitHub code-scanning
# exit code is 1 when the images differ (CI gate), 0 when identical

Passive vs. active modes

fwxray is defensive, authorized-use-only tooling. It has two clearly separated modes.

Passive (default — always safe)

Passive mode works only on firmware images you already have on disk. It never touches a device and never touches the network (feed enrichment uses a local cache / the bundled offline vuln DB). This is everything you normally run:

fwxray diff old.bin new.bin            # diff two images
fwxray inspect fw.bin                   # X-ray ONE image: entropy, sections,
                                        #   flags, and security indicators
fwxray scan old.bin new.bin --offline   # diff + component vuln enrichment (air-gap)

inspect surfaces descriptive indicators an analyst cares about — embedded private keys, hardcoded credentials, debug flags, telnet daemons — and exits 1 when a warning-level indicator is present (CI gate).

Active (pull) — AUTHORIZED USE ONLY, OFF by default

⚠️ AUTHORIZED-USE-ONLY. Active mode reads a live firmware image off a connected device/interface you physically control (an MTD/flash partition, a block device, a local capture endpoint). Reading firmware off hardware you do not own or are not authorized to test may be illegal. You are responsible for your scope. fwxray never targets a remote/network host.

Active mode is locked down by construction:

  • OFF by default. pull refuses to run unless you pass --authorized.
  • Scope-enforced. The source must match an explicit --allow allowlist (or FWXRAY_DEVICE_ALLOWLIST). An empty scope authorizes nothing; an out-of-scope source is refused, never silently read.
  • Rate-limited. Reads are throttled (--max-bytes-per-sec) and bounded by a hard --max-bytes ceiling.
  • Loud banner. Every authorized pull prints an authorized-use-only banner.
# refused — active mode is off by default
fwxray pull /dev/mtd0

# authorized, scoped, rate-limited acquisition into a file for passive analysis
fwxray pull /dev/mtd0 --authorized --allow '/dev/mtd*' \
       --max-bytes-per-sec 8388608 --out device.bin
fwxray inspect device.bin               # then analyze it passively

Exit codes: 3 = refused (not authorized / out of scope), 2 = read error, 0 = acquired.

Example

$ fwxray diff old.bin new.bin
FWXRAY firmware changelog
  old: old.bin  (2165 bytes, H=4.2396)
  new: new.bin  (2247 bytes, H=4.3792)
  size delta: +82 bytes

== Flags / config ==
  ~ analytics: 'off' -> 'on'
  ~ telemetry_optout: 'true' -> 'false'
  + metrics_endpoint: 'https://collect.northgate-telemetry.example'

== Entropy shifts ==
  (no significant entropy shifts)

== Strings ==
  +5 added / -3 removed

Demos

Each folder in demos/ is a self-contained, real-use-case scenario: a deterministic make_images.py that writes old.bin / new.bin in the real firmware-image input format, plus a SCENARIO.md (where the data came from, the exact run command, what to expect, and how to act). All eleven are exercised by the test suite.

Demo Situation Headline finding
01-basic First OTA diff flag flips + entropy tail
02-clean Identical images (control) none — exit 0
03-mixed Typical point release version bump + new asset + entropy
04-telemetry-added "Stability fix" adds telemetry opt-out cleared, metrics endpoint added
05-debug-backdoor RC ships with debug on telnet/root-SSH/console re-enabled
06-cert-rotation Benign CA rotation (control) single expected PEM swap
07-encrypted-partition Rootfs becomes encrypted high-entropy region spike
08-version-downgrade Rollback/downgrade attack fw_version moves backward
09-identical-resign No-op re-publish (control) none — exit 0
10-squashfs-grow Feature update squashfs grows + new applets
11-vuln-component-bump OTA bundles a vulnerable lib log4j-core 2.14.1 flagged CISA-KEV known-exploited
python -m fwxray diff demos/05-debug-backdoor/old.bin demos/05-debug-backdoor/new.bin
python -m fwxray diff demos/04-telemetry-added/old.bin demos/04-telemetry-added/new.bin --format sarif

# component vulnerability scan (OSV + CISA-KEV); --offline for air-gap
python -m fwxray scan demos/11-vuln-component-bump/old.bin demos/11-vuln-component-bump/new.bin

Data feeds — component vulnerability enrichment (edge / air-gap)

An OTA that bumps a bundled library leaves the library's name and version in the firmware's strings (OpenSSL 1.0.2k, BusyBox v1.30.1, log4j-core-2.14.1). fwxray scan turns that into a real finding: it parses the added component strings, queries OSV.dev for known vulnerabilities affecting that exact version, and cross-references every CVE against the CISA Known Exploited Vulnerabilities catalog — raising a KNOWN-EXPLOITED flag, the highest-priority "patch this now" signal for a fielded device. scan exits non-zero whenever a known-exploited component is present, so it gates CI / OTA promotion.

Feeds consumed

id source URL
osv OSV.dev vulnerability query (package+version → vulns, all ecosystems) https://api.osv.dev/v1/query
cisa-kev CISA Known Exploited Vulnerabilities catalog https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json

Both are authoritative and keyless. The catalog lives in fwxray/data_feeds_2026.json; ingestion is the standard-library-only fwxray/datafeeds.py (no pip deps).

Commands

fwxray feeds list                      # the feeds this tool consumes + cache freshness
fwxray feeds update cisa-kev           # fetch + cache (online)
fwxray feeds get cisa-kev --offline    # re-serve from the local cache, no network
fwxray scan old.bin new.bin            # diff + enrich (online)
fwxray scan old.bin new.bin --offline  # enrich from the cached snapshot (air-gap)

Edge / air-gap workflow

Every fetch is cached to COGNIS_FEEDS_CACHE (default ~/.cache/cognis-feeds) and can be re-served with --offline, so a disconnected device keeps working from its last snapshot. To move feeds across an air gap by sneakernet:

# on a connected staging box:
fwxray feeds update cisa-kev
python -m fwxray.datafeeds snapshot-export feeds.tar.gz

# carry feeds.tar.gz to the enclave, then on the air-gapped device:
python -m fwxray.datafeeds snapshot-import feeds.tar.gz
COGNIS_FEEDS_CACHE=~/.cache/cognis-feeds fwxray scan old.bin new.bin --offline

cisa-kev is a bulk catalog that caches cleanly. osv is a per-query POST API, so for fully-offline OSV resolution pre-resolve the component→vulns map on the connected box (see fwxray.feeds.build_offline_index) and ship it with the snapshot; demos/11-vuln-component-bump/demo_enrich.py shows the entire flow running with zero network against the committed fixtures.

Defensive / authorized-use intelligence only.

Architecture

flowchart LR
  OLD[old.bin] --> P[fwxray diff<br/>carve · entropy · strings · flags]
  NEW[new.bin] --> P
  P --> OUT[changelog<br/>table · JSON · SARIF]

Use it from any AI stack

fwxray is interoperable with every popular way of using AI:

  • MCP serverfwxray mcp (Claude Desktop, Cursor, Cognis.Studio, uncensored-fleet)
  • OpenAI-compatible / JSON — pipe fwxray diff old.bin new.bin --format json into any agent or LLM
  • LangChain · CrewAI · AutoGen · LlamaIndex — wrap the CLI/JSON as a tool in one line
  • CI / scripts — exit codes + SARIF for non-AI pipelines

How it compares

Cognis fwxray binwalk + diffoscope
Self-hostable, no account varies
Single command, zero config ⚠️
JSON + SARIF for CI varies
MCP-native (AI agents)
Polyglot ports (JS/Go/Rust)
Open license ✅ COCL varies

Built in the spirit of binwalk + diffoscope, re-framed the Cognis way. Missing a credit? Open a PR.

Integrations

Pipes into your stack: SARIF for code-scanning, JSON for anything, an MCP server (fwxray mcp) for AI agents, and a webhook forwarder for SIEM/Slack/Jira. See docs/INTEGRATIONS.md.

Install — every way, every platform

pip install "git+https://github.com/cognis-digital/fwxray.git"    # pip (works today)
pipx install "git+https://github.com/cognis-digital/fwxray.git"   # isolated CLI
uv tool install "git+https://github.com/cognis-digital/fwxray.git" # uv
pip install cognis-fwxray                                          # PyPI (when published)
docker run --rm ghcr.io/cognis-digital/fwxray:latest --help        # Docker
brew install cognis-digital/tap/fwxray                             # Homebrew tap
curl -fsSL https://raw.githubusercontent.com/cognis-digital/fwxray/main/install.sh | sh
Linux macOS Windows Docker Cloud
scripts/setup-linux.sh scripts/setup-macos.sh scripts/setup-windows.ps1 docker run ghcr.io/cognis-digital/fwxray DEPLOY.md (AWS/Azure/GCP/k8s)

Related Cognis tools

  • canzap — Replay, fuzz, and assert on CAN bus traffic from a .pcap or SocketCAN interface with a tiny YAML DSL.
  • sbomb — Generate a CycloneDX SBOM directly from an unpacked firmware root filesystem and flag components with known CVEs and EOL kernels.
  • mqttspy — Passively map an MQTT broker: enumerate topics, detect unauthenticated writes, spot PII/secrets in payloads, and emit a risk report.
  • uefiscan — Audit UEFI firmware dumps for missing Secure Boot keys, unsigned modules, S3 boot-script vulns, and known SMM threats.
  • modpot — Spin up a high-interaction Modbus/DNP3 ICS honeypot that logs attacker register reads/writes as structured JSON.
  • keyhunt — Scan firmware blobs and filesystem dumps for hardcoded private keys, API tokens, default creds, and weak RSA/ECC material.

Explore the suite → 🗂️ all 170+ tools · ⭐ awesome-cognis · 🔗 cognis-sources · 🤖 uncensored-fleet · 🧠 engram

Contributing

PRs, new rules, and demo scenarios are welcome under the collaboration-pull model — see CONTRIBUTING.md and SECURITY.md.

⭐ If fwxray saved you time, star it — it genuinely helps others find it.

Interoperability

{} composes with the 300+ tool Cognis suite — JSON in/out and a shared OpenAI-compatible /v1 backbone. See INTEROP.md for the suite map, composition patterns, and reference stacks.

License

Source-available under the Cognis Open Collaboration License (COCL) v1.0 — free for personal, internal-evaluation, research, and educational use; commercial / production use requires a license ([email protected]). See LICENSE.


Cognis Digital · one of 170+ tools in the Cognis Neural Suite · Making Tomorrow Better Today

Bundled vulnerability database

Ships fwxray/cognis_vulndb.jsonl.gz262,351 real vulnerabilities (OSV across 7 ecosystems) with detailed metadata; offline stdlib loader vulndb_local.VulnDB, air-gap ready.

from github.com/cognis-digital/fwxray

Installing Fwxray

This server has no published package — it is built from source. Open the repository and follow its README.

▸ github.com/cognis-digital/fwxray

FAQ

Is Fwxray MCP free?

Yes, Fwxray MCP is free — one-click install via Unyly at no cost.

Does Fwxray need an API key?

No, Fwxray runs without API keys or environment variables.

Is Fwxray hosted or self-hosted?

Self-hosted: the server runs locally on your machine via the install command above.

How do I install Fwxray in Claude Desktop, Claude Code or Cursor?

Open Fwxray on unyly.org, pick your client tab (Claude Desktop, Claude Code, Cursor) and press Install — the config is generated automatically, no JSON editing.

Related MCPs

Compare Fwxray with

Not sure what to pick?

Find your stack in 60 seconds

Author?

Embed badge for your README

Browse similar

All development MCPs