Files
Hermes Agent a58f16224c deps: Hopper 6.6.2 from the vendor's signed feed (no REA move)
`make check-updates` failed with BEHIND-REA on both Hopper rows: the vendor's
publisher-signed release feed moved its Ubuntu/Mint entry from Hopper 6.6.1 to
6.6.2 on 2026-11-06 16:22 UTC. REA 6.8.0 admits a Linux Hopper only when the
installed launcher is the feed's *current* main_exe_hash, so the old pin was
already wrong - and the build layer would have refused outright ("Hopper feed
moved: Hopper-6.6.2-Linux-demo.deb is no longer Hopper-6.6.1-Linux-demo.deb").

rea-agents itself is current: 6.8.0 is the newest npm release *and* the newest
github tag (v6.8.0, 2026-10-25), and its release notes list nothing pending for
Hopper beyond the feed-admission rule already implemented. So nothing else moved:
same REA_VERSION, same Node 24.22.1, same bundled skill (v49 / 229 tools), same
Ghidra 12.1.4, same helper tools (unicorn stays held at 2.1.2 because pwntools
4.15.0 excludes 2.1.3/2.1.4; Node 24.22.2, frida 17.26.1, uv 0.13.7,
supergateway 4.2.1, mitmproxy 12.3.1, pwndbg 2026.10.28 and Ghidra 12.2 are
newer upstream but wait for the next REA release per docs/UPDATES.md).

Re-pinned to the feed's row:
  HOPPER_DEMO_VERSION    6.6.1     -> 6.6.2
  HOPPER_DEB_SHA1        a2c28339..-> 9b46788160ba0b37f9050e0aa23a1372b3ecff53
  HOPPER_DEB_BYTES       35749234  -> 35749280
  HOPPER_LAUNCHER_SHA256 74b51599..-> 226800f154d766664bad5c45912f3a606ffa894316f97464f3c37f01fab5fb82

None of it was taken on trust: the .deb was downloaded (35,749,280 bytes,
sha1 9b467881...), its detached PGP signature verified against the vendor key
whose primary fingerprint is 7C2D73BAFAF5B9A710A69DA1A26DF815099B1BCD - the one
REA pins as HOPPER_LINUX_PRIMARY_FINGERPRINT - and opt/hopper/bin/Hopper hashed
out of the unpacked package (226800f1...), which is what the feed claims. The
build re-checks all four against the live feed, verifies bytes + SHA-1 and the
installed launcher, and bakes the signed evidence under
/home/rea/.cache/rea/hopper-releases/226800f1.../ (archive, release.json,
public-key.asc) so admission works offline; `rea doctor --provider hopper --json`
reports hopper-version healthy, reported_release_version 6.6.2,
source signed_package_cache.

Verified: scripts/build-all.sh (all four rebuilt; Hopper layer 3 min, the rest
cache hits), scripts/verify-all-engines.sh - all 121/0/3, ghidra 109/0/8, hopper
102/0/7, ida 94/0/11, 0 failures, exit 0 on every image; runs 20261107T091717Z /
20261107T092924Z / 20261107T094115Z / 20261107T094312Z. Counts are identical to
the 6.6.1 round; docs/verify-engines.txt regenerated and the sweep recorded in
docs/VERIFICATION.md. `make check-updates` is back to 0 actionable / 0 unknown /
0 unverifiable.

Docs that name the shipped Hopper build follow the pin (README, ARCHITECTURE,
MULTIARCH, BYO-LICENSES, TROUBLESHOOTING, vendor/README, the checker's header
comment); the 6.6.1 and 6.6.0 records in docs/VERIFICATION.md keep the versions
they actually ran.
2026-11-07 09:46:07 +00:00

282 lines
11 KiB
YAML

# =============================================================================
# rea-agent : REA + full reverse-engineering toolchain, MCP-ready
#
# Four images, one service each - pick the engine you actually use:
#
# docker compose up -d # rea-agent (Ghidra + Hopper)
# docker compose --profile ghidra up -d rea-ghidra # Ghidra only
# docker compose --profile hopper up -d rea-hopper # Hopper only
# docker compose --profile ida up -d rea-ida # no engine; bring your own IDA
#
# Named services above are the reliable form: a plain `--profile ghidra up -d`
# also starts `rea-agent`, because a service without a profile always starts.
# `make up-ghidra` / `up-hopper` / `up-ida` do the right thing for you.
#
# Every image carries the same auxiliary toolchain (firmware extraction,
# captures, browsers, managed code, Android, debuggers, cross toolchains,
# binfmt/QEMU); the images differ only in the native analysis engine and in
# what /usr/local/share/rea/engine.env advertises. See docs/IMAGES.md.
#
# Optional overlays:
# -f compose.http.yml publish REA's MCP surface over Streamable HTTP
# -f compose.ida.yml IDA registration (IDA Pro / Home; see docs/ida-variants.md)
#
# Copy .env.example to .env and adjust before the first `up`.
# =============================================================================
name: rea-agent
# --- shared build arguments --------------------------------------------------
x-build-args: &build-args
REA_VERSION: ${REA_VERSION:-6.8.0}
NODE_VERSION: ${NODE_VERSION:-24.22.1}
GHIDRA_VERSION: ${GHIDRA_VERSION:-12.1.4}
GHIDRA_ZIP: ${GHIDRA_ZIP:-ghidra_12.1.4_PUBLIC_20260921.zip}
GHIDRA_SHA256: ${GHIDRA_SHA256:-}
HOPPER_DEB_URL: ${HOPPER_DEB_URL:-}
HOPPER_DEMO_VERSION: ${HOPPER_DEMO_VERSION:-6.6.2}
HOPPER_DEB_SHA1: ${HOPPER_DEB_SHA1:-9b46788160ba0b37f9050e0aa23a1372b3ecff53}
HOPPER_DEB_BYTES: ${HOPPER_DEB_BYTES:-35749280}
HOPPER_LAUNCHER_SHA256: ${HOPPER_LAUNCHER_SHA256:-226800f154d766664bad5c45912f3a606ffa894316f97464f3c37f01fab5fb82}
INSTALL_CHROME: ${INSTALL_CHROME:-1}
INSTALL_PLAYWRIGHT: ${INSTALL_PLAYWRIGHT:-1}
INSTALL_PWNDBG: ${INSTALL_PWNDBG:-1}
INSTALL_WINE: ${INSTALL_WINE:-1}
INSTALL_CROSS_TOOLCHAINS: ${INSTALL_CROSS_TOOLCHAINS:-1}
# vendor/ida/*.run is installed only when INSTALL_IDA=1
INSTALL_IDA: ${INSTALL_IDA:-auto}
REA_UID: ${REA_UID:-1000}
REA_GID: ${REA_GID:-1000}
# --- engine-independent runtime environment ---------------------------------
# Engine paths (GHIDRA_INSTALL_DIR, HOPPER_LAUNCHER_PATH, IDADIR) are NOT here:
# each service sets the ones its own image actually ships, and the image's
# /usr/local/share/rea/engine.env supplies them for `docker run` / bare `rea` invocations.
#
# NOTE: REA rejects *empty* values for its own REA_* settings
# ("configuration_invalid: Too small: expected string to have >=1 characters"),
# so optional settings are never listed with an empty default. Put them in
# ./config/rea.env (loaded through env_file, which only defines variables that
# are actually present).
x-rea-env: &rea-env
# --- auxiliary engines ------------------------------------------------
REA_PWNTOOLS_PYTHON: /opt/venvs/pwntools/bin/python
REA_PWNDBG_GDB: /usr/bin/gdb
REA_PWNDBG_GDBINIT: /opt/pwndbg/gdbinit.py
REA_PWNDBG_VENV_PATH: /opt/pwndbg/.venv
REA_WABT_BIN_DIRECTORY: /opt/wabt/bin
REA_JADX_MCP_JAR: /opt/jadx/jadx-headless-mcp-0.7.1-all.jar
REA_APKTOOL_COMMAND: /usr/local/bin/apktool
REA_ADB_PATH: /usr/bin/adb
REA_BINWALK_COMMAND: /usr/local/bin/binwalk
REA_UNBLOB_COMMAND: /opt/venvs/unblob/bin/unblob
REA_TSHARK_COMMAND: /usr/bin/tshark
REA_CAPINFOS_COMMAND: /usr/bin/capinfos
REA_SIGROK_COMMAND: /usr/bin/sigrok-cli
REA_MITMDUMP_COMMAND: /opt/venvs/mitmproxy/bin/mitmdump
REA_ILSPY_CMD_PATH: /opt/dotnet-tools/ilspycmd
# --- JDK (jadx, apktool, ilspycmd) and MCP client shaping -------------
JAVA_HOME: /usr/lib/jvm/java-21-openjdk-amd64
REA_MCP_INPUT_SCHEMA_PROFILE: ${REA_MCP_INPUT_SCHEMA_PROFILE:-compact}
REA_BROWSER_NO_SANDBOX: ${REA_BROWSER_NO_SANDBOX:-1}
PLAYWRIGHT_BROWSERS_PATH: /opt/ms-playwright
REA_LOG_LEVEL: ${REA_LOG_LEVEL:-info}
REA_ENTRYPOINT_DOCTOR: ${REA_ENTRYPOINT_DOCTOR:-1}
TMPDIR: /tmp/rea
# --- environment that only matters when an engine is present -----------------
x-ghidra-env: &ghidra-env
GHIDRA_INSTALL_DIR: ${GHIDRA_INSTALL_DIR:-/opt/ghidra}
REA_GHIDRA_STARTUP_TIMEOUT_MS: ${REA_GHIDRA_STARTUP_TIMEOUT_MS:-900000}
GHIDRA_HEADLESS_MAXMEM: ${GHIDRA_HEADLESS_MAXMEM:-4G}
x-hopper-env: &hopper-env
HOPPER_LAUNCHER_PATH: ${HOPPER_LAUNCHER_PATH:-/opt/hopper/bin/Hopper}
HOPPER_STATE_DIR: ${HOPPER_STATE_DIR:-/home/rea/.local/share/hopper}
REA_HOPPER_STARTUP_TIMEOUT_MS: ${REA_HOPPER_STARTUP_TIMEOUT_MS:-300000}
# IDA is bring-your-own in every image; these are the mount/registration
# defaults (see docs/ida-variants.md).
x-ida-env: &ida-env
IDADIR: ${IDADIR:-/opt/ida}
REA_IDA_MCP_LOCAL_PORT: ${REA_IDA_MCP_LOCAL_PORT:-8745}
services:
# ===========================================================================
# rea-agent : Ghidra + Hopper (the "all engines" image, default service)
# ===========================================================================
rea-agent:
build:
context: .
dockerfile: Dockerfile
args:
<<: *build-args
REA_ENGINE: all
image: ${REA_IMAGE:-ghcr.io/alexmi256/rea-agent:6.8.0-linux-amd64}
container_name: ${REA_CONTAINER_NAME:-rea-agent}
platform: linux/amd64
init: true
restart: unless-stopped
# The image ships user `rea` (uid/gid 1000). Match your host user so files
# written into ./work are readable without sudo.
user: "${REA_UID:-1000}:${REA_GID:-1000}"
working_dir: /work
# Chromium, Playwright and Ghidra all want more /dev/shm than the 64 MiB
# Docker default.
shm_size: ${REA_SHM_SIZE:-1gb}
environment:
<<: [*rea-env, *ghidra-env, *hopper-env, *ida-env]
env_file:
- path: ./config/rea.env
required: false
volumes: &rea-volumes
# Analysis workspace: targets to inspect, snapshots, exported Evidence.
- ./work:/work
# Read-only sample drop-box (what you ask the agent to analyse).
- ${REA_TARGETS_DIR:-./targets}:/targets:ro
# Overrides + secrets that must not live in a layer:
# config/rea.env extra REA_* overrides
# config/ida-mcp.json IDA MCP registration
# config/ida/ida.hexlic IDA licence file
# config/hopper/* Hopper state (see docs/BYO-LICENSES.md)
- ./config:/etc/rea:ro
# IDA install (bring your own). Empty by default -> harmless no-op.
- ${IDA_INSTALL_DIR:-./vendor/ida}:/opt/ida:ro
# Hopper licence/state (optional; see docs/BYO-LICENSES.md).
- ${HOPPER_STATE_VOLUME:-./vendor/hopper-state}:/home/rea/.local/share/hopper
healthcheck:
test: ["CMD", "/usr/local/bin/rea-agent-healthcheck"]
interval: 60s
timeout: 90s
start_period: 120s
retries: 3
# ===========================================================================
# rea-ghidra : Ghidra only (broadest architecture coverage, no Hopper)
# ===========================================================================
rea-ghidra:
build:
context: .
dockerfile: Dockerfile
args:
<<: *build-args
REA_ENGINE: ghidra
image: ${REA_GHIDRA_IMAGE:-ghcr.io/alexmi256/rea-agent-ghidra:6.8.0-linux-amd64}
container_name: ${REA_GHIDRA_CONTAINER_NAME:-rea-agent-ghidra}
profiles: ["ghidra"]
platform: linux/amd64
init: true
restart: unless-stopped
user: "${REA_UID:-1000}:${REA_GID:-1000}"
working_dir: /work
shm_size: ${REA_SHM_SIZE:-1gb}
environment:
# REA_ANALYSIS_PROVIDER is already baked into this image's engine.env;
# list it here only to make the choice visible/overridable.
<<: [*rea-env, *ghidra-env, *ida-env]
REA_ANALYSIS_PROVIDER: ${REA_GHIDRA_PROVIDER:-ghidra}
env_file:
- path: ./config/rea.env
required: false
volumes:
- ./work:/work
- ${REA_TARGETS_DIR:-./targets}:/targets:ro
- ./config:/etc/rea:ro
- ${IDA_INSTALL_DIR:-./vendor/ida}:/opt/ida:ro
- rea-ghidra-home:/home/rea
healthcheck:
test: ["CMD", "/usr/local/bin/rea-agent-healthcheck"]
interval: 60s
timeout: 90s
start_period: 120s
retries: 3
# ===========================================================================
# rea-hopper : Hopper only (small, headless demo or your own licensed DEB)
# ===========================================================================
rea-hopper:
build:
context: .
dockerfile: Dockerfile
args:
<<: *build-args
REA_ENGINE: hopper
image: ${REA_HOPPER_IMAGE:-ghcr.io/alexmi256/rea-agent-hopper:6.8.0-linux-amd64}
container_name: ${REA_HOPPER_CONTAINER_NAME:-rea-agent-hopper}
profiles: ["hopper"]
platform: linux/amd64
init: true
restart: unless-stopped
user: "${REA_UID:-1000}:${REA_GID:-1000}"
working_dir: /work
shm_size: ${REA_SHM_SIZE:-1gb}
environment:
<<: [*rea-env, *hopper-env, *ida-env]
REA_ANALYSIS_PROVIDER: ${REA_HOPPER_PROVIDER:-hopper}
env_file:
- path: ./config/rea.env
required: false
volumes:
- ./work:/work
- ${REA_TARGETS_DIR:-./targets}:/targets:ro
- ./config:/etc/rea:ro
- ${HOPPER_STATE_VOLUME:-./vendor/hopper-state}:/home/rea/.local/share/hopper
- rea-hopper-home:/home/rea
healthcheck:
test: ["CMD", "/usr/local/bin/rea-agent-healthcheck"]
interval: 60s
timeout: 90s
start_period: 120s
retries: 3
# ===========================================================================
# rea-ida : no bundled engine. Mount your own IDA (Pro/Home/Free) install and
# licence, register an IDA MCP endpoint, and REA analyses natively through it.
# IDA Free cannot be used headlessly (no idalib) - see docs/ida-variants.md.
# ===========================================================================
rea-ida:
build:
context: .
dockerfile: Dockerfile
args:
<<: *build-args
REA_ENGINE: ida
image: ${REA_IDA_IMAGE:-ghcr.io/alexmi256/rea-agent-ida:6.8.0-linux-amd64}
container_name: ${REA_IDA_CONTAINER_NAME:-rea-agent-ida}
profiles: ["ida"]
platform: linux/amd64
init: true
restart: unless-stopped
user: "${REA_UID:-1000}:${REA_GID:-1000}"
working_dir: /work
shm_size: ${REA_SHM_SIZE:-1gb}
environment:
<<: [*rea-env, *ida-env]
REA_IDA_MCP_CONFIG: ${REA_IDA_MCP_CONFIG:-/etc/rea/ida-mcp.json}
env_file:
- path: ./config/rea.env
required: false
volumes:
- ./work:/work
- ${REA_TARGETS_DIR:-./targets}:/targets:ro
- ./config:/etc/rea:ro
- ${IDA_INSTALL_DIR:-./vendor/ida}:/opt/ida:ro
- ${IDA_LICENSE_DIR:-./config/ida}:/etc/rea/ida:ro
- ${IDA_MCP_CONFIG_FILE:-./config/ida-mcp.json}:/etc/rea/ida-mcp.json:ro
- rea-ida-home:/home/rea
healthcheck:
test: ["CMD", "/usr/local/bin/rea-agent-healthcheck"]
interval: 60s
timeout: 90s
start_period: 120s
retries: 3
volumes:
rea-home:
name: ${REA_HOME_VOLUME:-rea-agent-home}
rea-ghidra-home:
name: ${REA_HOME_VOLUME:-rea-agent-home}-ghidra
rea-hopper-home:
name: ${REA_HOME_VOLUME:-rea-agent-home}-hopper
rea-ida-home:
name: ${REA_HOME_VOLUME:-rea-agent-home}-ida