Fwxray
FreeNot checkedDiff two firmware images and surface exactly what changed: new binaries, flipped config flags, added certs, and shifted entropy regions.
About
Diff two firmware images and surface exactly what changed: new binaries, flipped config flags, added certs, and shifted entropy regions.
README
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
fwxrayoutput — 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
- Install (Python 3.9+):
pip install fwxray - 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 - Tune entropy-shift sensitivity and the block size for finer/coarser analysis:
fwxray diff v1.bin v2.bin --block 2048 --entropy-threshold 0.5 - Read the output: the report groups changes under Sections / Flags / Entropy
shifts / Strings. Use
--format jsonfor machine consumption; the process exits1when the two images differ (and0when byte-for-byte identical). - Capture an OTA changelog in CI:
fwxray diff old.bin new.bin --format json > changelog.json
Contents
- Why fwxray? · Features · Quick start · Example · Demos · Architecture · AI stack · How it compares · Integrations · Install anywhere · Related · Contributing
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.
pullrefuses to run unless you pass--authorized. - Scope-enforced. The source must match an explicit
--allowallowlist (orFWXRAY_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-bytesceiling. - 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 server —
fwxray mcp(Claude Desktop, Cursor, Cognis.Studio, uncensored-fleet) - OpenAI-compatible / JSON — pipe
fwxray diff old.bin new.bin --format jsoninto 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
fwxraysaved 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.
Bundled vulnerability database
Ships fwxray/cognis_vulndb.jsonl.gz — 262,351 real vulnerabilities (OSV across 7 ecosystems) with detailed metadata; offline stdlib loader vulndb_local.VulnDB, air-gap ready.
Installing Fwxray
This server has no published package — it is built from source. Open the repository and follow its README.
▸ github.com/cognis-digital/fwxrayFAQ
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
GitHub
PRs, issues, code search, CI status
by GitHubFilesystem
Secure file operations with configurable access controls.
Memory
Knowledge graph-based persistent memory system.
Template MCP Server
A CLI tool to create a new Model Context Protocol server project with TypeScript support, dual transport options, and an extensible structure
by mcpdotdirectAmap Maps Mcp Server
MCP server for using the AMap Maps API
by duxiaohuiSupabase
Database, auth and storage
by SupabaseEverything
Reference / test server with prompts, resources, and tools.
Git
Tools to read, search, and manipulate Git repositories.
Sequential Thinking
Dynamic and reflective problem-solving through thought sequences.
Time
Time and timezone conversion capabilities.
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
