[GH-ISSUE #3372] [Feature] Documented Docker image for running REA's MCP server and CLI on Linux #1239

Open
opened 2026-10-16 21:03:11 +00:00 by bsakaguchi · 1 comment
Owner

Originally created by @Rinkia on GitHub (Oct 14, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/3372

Before submitting

  • I searched the open and closed issues and pull requests for a related proposal. (Searched "docker" and "container"; no related proposal found.)
  • I understand the contribution scope must be reviewed before integration; open questions are welcome here.
  • This request does not include credentials, private samples, or sensitive target data.

Area

Setup, packaging, or upgrade

Current limitation

I want to run REA isolated from my host, for two reasons: the targets I inspect are untrusted, and the host is Windows, where Linux-first providers (Ghidra, JADX, binwalk, tshark, process capture) are easier to run in Linux. REA has no Dockerfile and no container guide today. Each user has to rediscover the following:

  • Ghidra needs a full JDK 21 together with Node ≥22.19, and GHIDRA_INSTALL_DIR must point at it.
  • JADX needs the pinned jadx-headless-mcp-0.7.1-all.jar through REA_JADX_MCP_JAR, not the regular JADX release.
  • Ubuntu's chromium package is snap-only and does not work in a container. A browser therefore has to come from somewhere else (I used Playwright's Chrome for Testing), configured with REA_BROWSER_EXECUTABLE and REA_BROWSER_NO_SANDBOX=true. Docker's default seccomp profile blocks the user namespaces that Chrome's sandbox needs.
  • The MCP client must launch the container with docker run -i, and the agent must pass container paths such as /targets/app, not host paths.
  • Ghidra's JVM needs a memory cap such as --memory 3g -e GHIDRA_HEADLESS_MAXMEM=2G. My first, uncapped Ghidra run ended with error waiting for container: unexpected EOF, and Docker Desktop then stopped responding. I did not confirm the cause, so treat the memory cap as a precaution, not a diagnosed fix.

Use cases

  • Analyse untrusted binaries, APKs and websites inside a disposable, read-only-mounted container rather than on the host.
  • Use Linux-only or Linux-verified providers from Windows or macOS hosts through Docker Desktop.
  • Pin a reproducible toolchain (REA version, Ghidra version, JDK, JADX JAR digest, browser build) for a team or CI.

Desired outcome and success criteria

  • A maintained Dockerfile, or a documented example, that bundles Node, a JDK 21, Ghidra 12.1.x, the pinned JADX JAR (sha256-checked) and a Chromium-family browser.
  • A docs/docker.md page covering:
    • MCP registration with docker run -i
    • the target mount and container paths
    • memory limits
    • the browser sandbox trade-off
    • the CDP attach limitation (below)
  • Success: with a fresh image, rea doctor --provider ghidra is healthy, and Ghidra, JADX and browser operations succeed on public samples.

Expected interaction with targets

Read existing files or captured data. Launch or attach to a process (the browser, and Ghidra/JADX as owned processes).

Verification available so far

I have a prototype or observed results.

Verification details

Prototype Dockerfile (below). Host: Windows 11 with Docker Desktop (WSL2, linux/amd64, engine 29.7.2, about 7.6 GB). REA rea-agents@6.4.0. All runs used --memory 3g and a read-only /targets mount.

Check Result
rea doctor --provider ghidra healthy: true; Ghidra 12.1.4, headless, linux_x86_64 decompiler and JDK 21.0.12 all healthy
rea function /targets/hello check_key --provider ghidra (small gcc 14 -O1 ELF) exit 0; pseudocode and assembly match the source (xor 0x5a, == 0x539)
MCP over docker run -i (initialize and tools/list) serverInfo: rea 6.4.0, 170 tools
inspect-android-package on an F-Droid APK (org.billthefarmer.editor, vc 198) exit 0; JADX 0.7.1 bridge, 163 classes, 48 resources
inspect-android-method ... Editor onCreate status: complete, Java source returned
Chromium started in the container with --remote-debugging-port=9222, then list-browser-targets and inspect-web-page against https://example.com target found; scripts and DOM URLs returned

Untested: IDA, Hopper, firmware tools, tshark, process capture, arm64 hosts.

Prototype Dockerfile
FROM eclipse-temurin:21-jdk-noble
# Node 24 (REA needs >=22.19)
COPY --from=node:24-bookworm-slim /usr/local/bin/node /usr/local/bin/
COPY --from=node:24-bookworm-slim /usr/local/lib/node_modules /usr/local/lib/node_modules
RUN ln -s /usr/local/lib/node_modules/npm/bin/npm-cli.js /usr/local/bin/npm \
 && ln -s /usr/local/lib/node_modules/npm/bin/npx-cli.js /usr/local/bin/npx \
 && apt-get update && apt-get install -y --no-install-recommends procps unzip curl \
 && rm -rf /var/lib/apt/lists/*
# Ghidra 12.1.4 (version REA verifies against)
RUN curl -fsSL -o /tmp/g.zip https://github.com/NationalSecurityAgency/ghidra/releases/download/Ghidra_12.1.4_build/ghidra_12.1.4_PUBLIC_20260921.zip \
 && unzip -q /tmp/g.zip -d /opt && mv /opt/ghidra_12.1.4_PUBLIC /opt/ghidra && rm /tmp/g.zip
ENV GHIDRA_INSTALL_DIR=/opt/ghidra
# JADX engine pinned by REA (docs/android-analysis.md)
RUN mkdir -p /opt/jadx && curl -fsSL -o /opt/jadx/jadx-headless-mcp-0.7.1-all.jar https://github.com/1013503897/jadx-headless-mcp/releases/download/v0.7.1/jadx-headless-mcp-0.7.1-all.jar \
 && echo '6e5eacf500b64292bfb73c49797c1958f6ee44646e43e868039ae7feb573ff75  /opt/jadx/jadx-headless-mcp-0.7.1-all.jar' | sha256sum -c -
ENV REA_JADX_MCP_JAR=/opt/jadx/jadx-headless-mcp-0.7.1-all.jar
RUN npm install -g rea-agents@6.4.0
# Chromium matching REA's playwright-core (Ubuntu's chromium is snap-only)
ENV PLAYWRIGHT_BROWSERS_PATH=/opt/ms-playwright
RUN npx -y playwright-core@1.58.2 install --with-deps chromium \
 && ln -s "$(find /opt/ms-playwright -path '*chrome-linux*/chrome' -type f | head -1)" /usr/local/bin/chromium \
 && chmod -R a+rX /opt/ms-playwright
ENV REA_BROWSER_EXECUTABLE=/usr/local/bin/chromium
# Chrome's own sandbox needs user namespaces, which Docker's seccomp blocks; the container is the sandbox
ENV REA_BROWSER_NO_SANDBOX=true
RUN useradd -m rea
USER rea
WORKDIR /targets
ENTRYPOINT ["rea"]
CMD ["mcp"]

MCP registration (Claude Code):

claude mcp add --scope local rea -- docker run -i --rm --memory 3g -e GHIDRA_HEADLESS_MAXMEM=2G -v /host/targets:/targets:ro rea

Alternatives considered

  • Running natively on the host. That works, but it gives no isolation from untrusted targets and needs a per-host install of JDK, Ghidra, JADX and a browser.
  • A generic devcontainer. Same toolchain questions, and it isn't documented for REA either.

Possible direction

  • Start with a documentation page and an example Dockerfile in docs/, which needs no release or registry commitment. A published image (for example on GHCR) could follow later.
  • Open question: CDP attach tools (list_browser_targets, inspect_web_page) need a browser that is already running with --remote-debugging-port on loopback in the same network namespace. REA never launches that browser. When the MCP client starts a fresh docker run -i --rm container per session, no such browser exists. The options are to document a long-running container that starts Chromium first, or to support a container entrypoint that does so.
  • Open question: is REA_BROWSER_NO_SANDBOX=true acceptable in a documented setup, or would you rather ship a seccomp profile that allows Chrome's sandbox?

References

  • docs/installation.md (Ghidra JDK and host-platform rules, the Linux ps prerequisite)
  • docs/android-analysis.md (pinned JADX JAR and its sha256)
  • docs/browser-observation.md (CDP endpoint requirements and the minimal-Linux-container note)
Originally created by @Rinkia on GitHub (Oct 14, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/3372 ### Before submitting - [x] I searched the open and closed issues and pull requests for a related proposal. (Searched "docker" and "container"; no related proposal found.) - [x] I understand the contribution scope must be reviewed before integration; open questions are welcome here. - [x] This request does not include credentials, private samples, or sensitive target data. ### Area Setup, packaging, or upgrade ### Current limitation I want to run REA isolated from my host, for two reasons: the targets I inspect are untrusted, and the host is Windows, where Linux-first providers (Ghidra, JADX, binwalk, tshark, process capture) are easier to run in Linux. REA has no Dockerfile and no container guide today. Each user has to rediscover the following: - Ghidra needs a full JDK 21 together with Node ≥22.19, and `GHIDRA_INSTALL_DIR` must point at it. - JADX needs the pinned `jadx-headless-mcp-0.7.1-all.jar` through `REA_JADX_MCP_JAR`, not the regular JADX release. - Ubuntu's `chromium` package is snap-only and does not work in a container. A browser therefore has to come from somewhere else (I used Playwright's Chrome for Testing), configured with `REA_BROWSER_EXECUTABLE` and `REA_BROWSER_NO_SANDBOX=true`. Docker's default seccomp profile blocks the user namespaces that Chrome's sandbox needs. - The MCP client must launch the container with `docker run -i`, and the agent must pass container paths such as `/targets/app`, not host paths. - Ghidra's JVM needs a memory cap such as `--memory 3g -e GHIDRA_HEADLESS_MAXMEM=2G`. My first, uncapped Ghidra run ended with `error waiting for container: unexpected EOF`, and Docker Desktop then stopped responding. I did not confirm the cause, so treat the memory cap as a precaution, not a diagnosed fix. ### Use cases - Analyse untrusted binaries, APKs and websites inside a disposable, read-only-mounted container rather than on the host. - Use Linux-only or Linux-verified providers from Windows or macOS hosts through Docker Desktop. - Pin a reproducible toolchain (REA version, Ghidra version, JDK, JADX JAR digest, browser build) for a team or CI. ### Desired outcome and success criteria - A maintained `Dockerfile`, or a documented example, that bundles Node, a JDK 21, Ghidra 12.1.x, the pinned JADX JAR (sha256-checked) and a Chromium-family browser. - A `docs/docker.md` page covering: - MCP registration with `docker run -i` - the target mount and container paths - memory limits - the browser sandbox trade-off - the CDP attach limitation (below) - Success: with a fresh image, `rea doctor --provider ghidra` is healthy, and Ghidra, JADX and browser operations succeed on public samples. ### Expected interaction with targets Read existing files or captured data. Launch or attach to a process (the browser, and Ghidra/JADX as owned processes). ### Verification available so far I have a prototype or observed results. ### Verification details Prototype Dockerfile (below). Host: Windows 11 with Docker Desktop (WSL2, linux/amd64, engine 29.7.2, about 7.6 GB). REA `rea-agents@6.4.0`. All runs used `--memory 3g` and a read-only `/targets` mount. | Check | Result | |---|---| | `rea doctor --provider ghidra` | `healthy: true`; Ghidra 12.1.4, headless, `linux_x86_64` decompiler and JDK 21.0.12 all healthy | | `rea function /targets/hello check_key --provider ghidra` (small gcc 14 `-O1` ELF) | exit 0; pseudocode and assembly match the source (`xor 0x5a`, `== 0x539`) | | MCP over `docker run -i` (`initialize` and `tools/list`) | `serverInfo: rea 6.4.0`, 170 tools | | `inspect-android-package` on an F-Droid APK (`org.billthefarmer.editor`, vc 198) | exit 0; JADX 0.7.1 bridge, 163 classes, 48 resources | | `inspect-android-method ... Editor onCreate` | `status: complete`, Java source returned | | Chromium started in the container with `--remote-debugging-port=9222`, then `list-browser-targets` and `inspect-web-page` against `https://example.com` | target found; scripts and DOM URLs returned | Untested: IDA, Hopper, firmware tools, tshark, process capture, arm64 hosts. <details><summary>Prototype Dockerfile</summary> ```dockerfile FROM eclipse-temurin:21-jdk-noble # Node 24 (REA needs >=22.19) COPY --from=node:24-bookworm-slim /usr/local/bin/node /usr/local/bin/ COPY --from=node:24-bookworm-slim /usr/local/lib/node_modules /usr/local/lib/node_modules RUN ln -s /usr/local/lib/node_modules/npm/bin/npm-cli.js /usr/local/bin/npm \ && ln -s /usr/local/lib/node_modules/npm/bin/npx-cli.js /usr/local/bin/npx \ && apt-get update && apt-get install -y --no-install-recommends procps unzip curl \ && rm -rf /var/lib/apt/lists/* # Ghidra 12.1.4 (version REA verifies against) RUN curl -fsSL -o /tmp/g.zip https://github.com/NationalSecurityAgency/ghidra/releases/download/Ghidra_12.1.4_build/ghidra_12.1.4_PUBLIC_20260921.zip \ && unzip -q /tmp/g.zip -d /opt && mv /opt/ghidra_12.1.4_PUBLIC /opt/ghidra && rm /tmp/g.zip ENV GHIDRA_INSTALL_DIR=/opt/ghidra # JADX engine pinned by REA (docs/android-analysis.md) RUN mkdir -p /opt/jadx && curl -fsSL -o /opt/jadx/jadx-headless-mcp-0.7.1-all.jar https://github.com/1013503897/jadx-headless-mcp/releases/download/v0.7.1/jadx-headless-mcp-0.7.1-all.jar \ && echo '6e5eacf500b64292bfb73c49797c1958f6ee44646e43e868039ae7feb573ff75 /opt/jadx/jadx-headless-mcp-0.7.1-all.jar' | sha256sum -c - ENV REA_JADX_MCP_JAR=/opt/jadx/jadx-headless-mcp-0.7.1-all.jar RUN npm install -g rea-agents@6.4.0 # Chromium matching REA's playwright-core (Ubuntu's chromium is snap-only) ENV PLAYWRIGHT_BROWSERS_PATH=/opt/ms-playwright RUN npx -y playwright-core@1.58.2 install --with-deps chromium \ && ln -s "$(find /opt/ms-playwright -path '*chrome-linux*/chrome' -type f | head -1)" /usr/local/bin/chromium \ && chmod -R a+rX /opt/ms-playwright ENV REA_BROWSER_EXECUTABLE=/usr/local/bin/chromium # Chrome's own sandbox needs user namespaces, which Docker's seccomp blocks; the container is the sandbox ENV REA_BROWSER_NO_SANDBOX=true RUN useradd -m rea USER rea WORKDIR /targets ENTRYPOINT ["rea"] CMD ["mcp"] ``` MCP registration (Claude Code): ```bash claude mcp add --scope local rea -- docker run -i --rm --memory 3g -e GHIDRA_HEADLESS_MAXMEM=2G -v /host/targets:/targets:ro rea ``` </details> ### Alternatives considered - Running natively on the host. That works, but it gives no isolation from untrusted targets and needs a per-host install of JDK, Ghidra, JADX and a browser. - A generic devcontainer. Same toolchain questions, and it isn't documented for REA either. ### Possible direction - Start with a documentation page and an example Dockerfile in `docs/`, which needs no release or registry commitment. A published image (for example on GHCR) could follow later. - Open question: CDP attach tools (`list_browser_targets`, `inspect_web_page`) need a browser that is already running with `--remote-debugging-port` on loopback in the same network namespace. REA never launches that browser. When the MCP client starts a fresh `docker run -i --rm` container per session, no such browser exists. The options are to document a long-running container that starts Chromium first, or to support a container entrypoint that does so. - Open question: is `REA_BROWSER_NO_SANDBOX=true` acceptable in a documented setup, or would you rather ship a seccomp profile that allows Chrome's sandbox? ### References - `docs/installation.md` (Ghidra JDK and host-platform rules, the Linux `ps` prerequisite) - `docs/android-analysis.md` (pinned JADX JAR and its sha256) - `docs/browser-observation.md` (CDP endpoint requirements and the minimal-Linux-container note)
Author
Owner

@Rinkia commented on GitHub (Oct 15, 2026):

Requesting a scope decision for the Docker image, so that #3420 can either proceed or be narrowed. The review there (HOLD, P1) is right that the recipe meets existing rules for which this issue has no decision yet.

What the image does today (#3420 @ f47521e03):

  • Bundles a JDK 21 base, Node 24, Ghidra 12.1.4 (downloaded during the image build), the pinned jadx-headless-mcp 0.7.1 JAR (sha256-checked) and Playwright's Chrome for Testing, together with rea-agents.
  • Sets REA_BROWSER_NO_SANDBOX=true image-wide, because Docker's default seccomp profile blocks the user namespaces that Chromium's sandbox needs. Without the flag, Chromium exits with No usable sandbox!.
  • Changes nothing on the host. The only host-side state is the image and the caller's own docker run mounts.

Rules it meets (AGENTS.md):

  • "Ghidra and IDA are bring-your-own."
  • "Installers must not install or upgrade unrelated software, including Homebrew, Node.js, npm, Java, or Ghidra."

Questions:

  1. Bundled toolchain. Is an opt-in container image, built by the user from docker/Dockerfile, an acceptable place to bundle Node, the JDK, Ghidra and the JADX JAR, or should those rules apply to images too? If they apply, the narrowed alternative is an image containing only rea-agents (plus Node as its runtime), with Ghidra, the JADX JAR and a browser supplied by the caller through mounted volumes and the existing GHIDRA_INSTALL_DIR / REA_JADX_MCP_JAR / REA_BROWSER_EXECUTABLE settings.
  2. Browser sandbox. Which of these is acceptable?
    • (a) keep REA_BROWSER_NO_SANDBOX=true image-wide, documented as "the container is the isolation boundary";
    • (b) remove it from the image and document it as an explicit -e REA_BROWSER_NO_SANDBOX=true opt-in at docker run time;
    • (c) keep Chromium's sandbox, with a documented seccomp profile that permits user namespaces.
  3. Verification. Which checks would you want before integration (for example a CI job that builds the image and runs rea doctor --provider ghidra / --provider jadx), or is documentation-level evidence enough for a recipe that REA doesn't publish?

Until there's a decision, #3420 stays on hold. I'm happy to narrow it to whichever option you choose.

<!-- gh-comment-id:6187422549 --> @Rinkia commented on GitHub (Oct 15, 2026): Requesting a scope decision for the Docker image, so that #3420 can either proceed or be narrowed. The review there (HOLD, P1) is right that the recipe meets existing rules for which this issue has no decision yet. **What the image does today (#3420 @ `f47521e03`):** - Bundles a JDK 21 base, Node 24, Ghidra 12.1.4 (downloaded during the image build), the pinned `jadx-headless-mcp` 0.7.1 JAR (sha256-checked) and Playwright's Chrome for Testing, together with `rea-agents`. - Sets `REA_BROWSER_NO_SANDBOX=true` image-wide, because Docker's default seccomp profile blocks the user namespaces that Chromium's sandbox needs. Without the flag, Chromium exits with `No usable sandbox!`. - Changes nothing on the host. The only host-side state is the image and the caller's own `docker run` mounts. **Rules it meets (AGENTS.md):** - "Ghidra and IDA are bring-your-own." - "Installers must not install or upgrade unrelated software, including Homebrew, Node.js, npm, Java, or Ghidra." **Questions:** 1. **Bundled toolchain.** Is an opt-in container image, built by the user from `docker/Dockerfile`, an acceptable place to bundle Node, the JDK, Ghidra and the JADX JAR, or should those rules apply to images too? If they apply, the narrowed alternative is an image containing only `rea-agents` (plus Node as its runtime), with Ghidra, the JADX JAR and a browser supplied by the caller through mounted volumes and the existing `GHIDRA_INSTALL_DIR` / `REA_JADX_MCP_JAR` / `REA_BROWSER_EXECUTABLE` settings. 2. **Browser sandbox.** Which of these is acceptable? - (a) keep `REA_BROWSER_NO_SANDBOX=true` image-wide, documented as "the container is the isolation boundary"; - (b) remove it from the image and document it as an explicit `-e REA_BROWSER_NO_SANDBOX=true` opt-in at `docker run` time; - (c) keep Chromium's sandbox, with a documented seccomp profile that permits user namespaces. 3. **Verification.** Which checks would you want before integration (for example a CI job that builds the image and runs `rea doctor --provider ghidra` / `--provider jadx`), or is documentation-level evidence enough for a recipe that REA doesn't publish? Until there's a decision, #3420 stays on hold. I'm happy to narrow it to whichever option you choose.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#1239
No description provided.