{"id":50347316,"url":"https://github.com/lycshub/malfuse","last_synced_at":"2026-05-29T20:00:49.006Z","repository":{"id":361089395,"uuid":"1252948151","full_name":"LycsHub/malFuse","owner":"LycsHub","description":"malFuse is a local HTTP proxy firewall that prevents software supply chain poisoning by intercepting package install requests and blocking malicious packages before they reach your disk. Built in Go with zero runtime dependencies.","archived":false,"fork":false,"pushed_at":"2026-05-29T05:59:14.000Z","size":183,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-29T07:29:45.709Z","etag":null,"topics":["dependency-security","malicious-package-blocker","ossf","package-manager","poisoning","poisoning-attack","security","supply-chain-attack-detection"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/LycsHub.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-29T02:59:06.000Z","updated_at":"2026-05-29T07:03:13.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/LycsHub/malFuse","commit_stats":null,"previous_names":["lycshub/malfuse"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/LycsHub/malFuse","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LycsHub%2FmalFuse","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LycsHub%2FmalFuse/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LycsHub%2FmalFuse/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LycsHub%2FmalFuse/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/LycsHub","download_url":"https://codeload.github.com/LycsHub/malFuse/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LycsHub%2FmalFuse/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33668186,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-29T02:00:06.066Z","response_time":107,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dependency-security","malicious-package-blocker","ossf","package-manager","poisoning","poisoning-attack","security","supply-chain-attack-detection"],"created_at":"2026-05-29T20:00:48.036Z","updated_at":"2026-05-29T20:00:48.994Z","avatar_url":"https://github.com/LycsHub.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 📖 malFuse — Supply Chain Firewall\n\n[中文](README_CN.md) | English\n\nmalFuse is a **local HTTP proxy firewall** that prevents **software supply chain poisoning**\nby intercepting package install requests and blocking malicious packages before they reach\nyour disk. Built in Go with zero runtime dependencies.\n\n**How it works:** pip, npm, yarn, uv, and other package managers are configured to route\nthrough malFuse. Every install request is checked against a local database of **252,637\nconfirmed malicious packages** sourced from the [OpenSSF](https://github.com/ossf/malicious-packages)\nproject, plus real-time OSV vulnerability lookups and streaming script analysis.\n\n- **Multi-ecosystem** — supports PyPI, npm, RubyGems, NuGet, Crates.io, Go modules, and more\n- **6-layer detection** — whitelist, malicious DB, cooldown, typo-squatting, OSV API, script scan\n- **Zero friction** — no CA certificates, no HTTPS interception, plain HTTP on localhost\n- **Offline capable** — SQLite-backed, works without network after initial DB setup\n\nP0 + P1 complete. P2 in progress (whitelist, CI/CD done). 252,637 malicious package records across 11 ecosystems.\n\n---\n\n# Usage\n\n## Quick Start\n\n```bash\n# 1. Generate malicious package database\n./malfuse-db --mode direct --db malfuse.db --repo ossf-malicious-packages\n\n# 2. Configure package manager\n./malfuse link\n\n# 3. Start proxy\n./malfuse start            # daemon mode (background)\n# or\n./malfuse -config config.json  # foreground\n\n# 4. Install dependencies normally (traffic routed through proxy)\npip install requests\nnpm install lodash\n```\n\n---\n\n## CLI Commands\n\n### `malfuse` — Proxy + Management\n\n```bash\n# Running\nmalfuse                         # foreground (default config.json)\nmalfuse -c /path/to/config.json # custom config\nmalfuse start                   # daemon (background)\nmalfuse stop                    # stop daemon\nmalfuse status                  # check daemon status\n\n# Package manager configuration\nmalfuse link                    # configure all installed managers\nmalfuse link --target pip       # pip only\nmalfuse link --target npm       # npm only\nmalfuse link --target pnpm      # pnpm only\nmalfuse link --target yarn      # yarn v1 only\nmalfuse unlink                  # restore all\nmalfuse unlink --target pip     # restore pip only\n\n# Whitelist management\nmalfuse allow add requests --ecosystem pypi               # allow all versions\nmalfuse allow add lodash --ecosystem npm --version 4.17.21 # allow specific version\nmalfuse allow remove requests --ecosystem pypi              # remove from whitelist\nmalfuse allow list                                          # list all\nmalfuse allow list --ecosystem npm                          # filter by ecosystem\n```\n\n### `malfuse-db` — Database Management\n\n```bash\n# Direct SQLite write (online use)\nmalfuse-db --mode direct --db malfuse.db --repo ossf-malicious-packages\n\n# Generate SQL incremental file (offline/air-gapped use)\nmalfuse-db --mode sql --output updates-20260527.sql --repo ossf-malicious-packages\n\n# Specify config (reads repo_proxy for GitHub acceleration)\nmalfuse-db --config config.json --mode direct\n```\n\n| Flag | Default | Description |\n|------|---------|-------------|\n| `--mode` | `direct` | `direct` write to SQLite / `sql` generate incremental SQL file |\n| `--db` | `malfuse.db` | SQLite database path |\n| `--repo` | `ossf-malicious-packages` | git repo cache directory |\n| `--output` | `updates-YYYYMMDDHHmm.sql` | SQL output path (sql mode only) |\n| `--config` | `config.json` | config file path (reads `repo_proxy` for proxy) |\n\n**Update mechanism:** First run does a full scan (clone + parse all OSV JSON). Subsequent runs use `git fetch` + `git diff --name-status` for incremental updates, completing in seconds.\n\n**Output:** `direct` mode writes to `malfuse.db` (WAL mode, readable by proxy concurrently). `sql` mode generates `INSERT OR REPLACE` + `DELETE` statements for importing into air-gapped databases.\n\n---\n\n## Package Manager Configuration\n\n### One-click (`malfuse link`)\n\n| Tool | Command | What it does |\n|------|---------|--------------|\n| pip | `malfuse link --target pip` | `pip config set global.index-url http://127.0.0.1:8080/pypi/simple/` |\n| npm | `malfuse link --target npm` | `npm config set registry http://127.0.0.1:8080/npm/` |\n| pnpm | `malfuse link --target pnpm` | `pnpm config set registry http://127.0.0.1:8080/npm/` |\n| yarn v1 | `malfuse link --target yarn` | `yarn config set registry http://127.0.0.1:8080/npm/` |\n\n`malfuse link` backs up original values to `~/.malfuse_backup.json`. `malfuse unlink` restores from backup.\n\n### Manual Configuration\n\nThese tools don't support CLI config commands—manual setup required:\n\n| Tool | Documentation |\n|------|---------------|\n| yarn v2+ (Berry) | [docs/yarn-v2-config.md](docs/yarn-v2-config.md) |\n| uv | [docs/uv-config.md](docs/uv-config.md) |\n| poetry | [docs/poetry-config.md](docs/poetry-config.md) |\n| conda | [docs/conda-config.md](docs/conda-config.md) |\n\n---\n\n## Blocking Granularity\n\nDifferent package managers have different proxy behaviors, resulting in different version-matching precision:\n\n| Ecosystem | Granularity | Mechanism |\n|-----------|-------------|-----------|\n| **PyPI (pip)** | Version-precise | Simple API only blocks `version=NULL` entries. Proxy rewrites HTML download links so pip's tarball requests go back through the proxy, enabling exact version matching |\n| **npm** | Package-level (all-or-nothing) | npm's `pacote` download library bypasses proxy caching, preventing precise version matching on download. Only `version=NULL` entries block at Simple API stage with 403 |\n\n### npm Version-Precise Workaround\n\nFor npm version-level control, use whitelist with all-or-nothing blocking:\n\n```bash\n# 1. Mark package as all-versions blocked (version=NULL)\nsqlite3 malfuse.db \"INSERT INTO malicious_packages VALUES ('bad-lib', NULL, 'npm', '', '');\"\n\n# 2. Whitelist the safe version\n./malfuse allow add bad-lib --ecosystem npm --version 2.0.5\n```\n\nNow `npm install bad-lib@2.0.5` passes, all other versions are blocked.\n\n### Blocking Behavior Matrix\n\n| Scenario | pip | npm |\n|----------|-----|-----|\n| DB `version=NULL` | All versions blocked | All versions blocked |\n| DB `version=\"1.0\"`, install 1.0 | Blocked (exact match on download) | Blocked (unless whitelisted) |\n| DB `version=\"1.0\"`, install 2.0 | Pass | Blocked (unless whitelisted) |\n\n---\n\n## Detection Pipeline\n\nEach install request passes through 6 checks (including whitelist). The first match stops the pipeline:\n\n| # | Check | Data Source | Result | Default |\n|---|-------|-------------|--------|---------|\n| 0 | **Whitelist** | SQLite `whitelist` table | Match → immediate PASS, skip all remaining checks | On |\n| 1 | **Malicious DB** | SQLite `malicious_packages` (252,637 records) | Match → 403 Forbidden | On |\n| 2 | **Cooldown** | `malicious_packages.published` (OSV report timestamp) | Report age \u003c 48h → 403 | Off |\n| 3 | **Typo-Squatting** | Embedded 2,790 popular packages + Levenshtein distance | Name similarity → 403 | Off |\n| 4 | **OSV API** | `api.osv.dev/v1/query` + in-memory TTL cache | Vuln found + `block_on_vuln=true` → 403 | On (log only) |\n| 5 | **Stream Script Scan** | TeeReader streaming (tar/gzip extraction) | Malicious script → connection reset | Off |\n\n**Failure policies:**\n- Whitelist / typo — no failure possible (pure memory / SQLite)\n- Malicious DB — skip on DB missing or corrupt (log WARN)\n- Cooldown — skip on missing DB or `published` field; DB-only query, no extra network calls\n- OSV API — network unreachable → pass (fail-open); `block_on_vuln=false` → log only\n- Script scan — parse/archive error → pass (fail-open)\n\n**Note:** Cooldown and typo-squatting are **off by default** due to false-positive risk and stability concerns. Enable only when you understand the trade-offs.\n\n**Script scan (#5) attack vectors covered:**\n\n| JS Ecosystem | Python Ecosystem |\n|--------------|-----------------|\n| `package.json` `scripts.preinstall/postinstall/install` | `setup.py` full content |\n| `package.json` scripts-referenced `.js` files | `__init__.py` full content |\n| Standalone `.js` files | `.pth` file `import` lines |\n| — | `pyproject.toml` `build-system.build-backend` |\n\nEach vector analyzed by three detectors: **Shannon entropy** (threshold 4.5), **code obfuscation** (base64/hex/eval chains), **network detection** (URLs/IPs).\n\n---\n\n## Health Check\n\n```bash\n$ curl http://127.0.0.1:8080/health\n{\"db\":true,\"status\":\"ok\",\"uptime\":\"2h34m5s\"}\n```\n\n| Field | Description |\n|-------|-------------|\n| `status` | `ok` (healthy) or `degraded` (DB unavailable) |\n| `db` | SQLite connection status |\n| `uptime` | Proxy process uptime |\n\n---\n\n## Configuration (config.json)\n\n```json\n{\n  \"port\": \"8080\",\n  \"host\": \"127.0.0.1\",\n  \"db_path\": \"malfuse.db\",\n  \"pid_file\": \"malfuse.pid\",\n  \"repo_proxy\": \"ghfast.top\",\n  \"logging\": {\n    \"level\": \"info\",\n    \"format\": \"text\",\n    \"output\": \"stdout\"\n  },\n  \"routing\": [\n    {\"prefix\": \"/pypi/\", \"upstream\": \"https://pypi.tuna.tsinghua.edu.cn\", \"ecosystem\": \"pypi\"},\n    {\"prefix\": \"/npm/\", \"upstream\": \"https://registry.npmmirror.com\", \"ecosystem\": \"npm\"}\n  ],\n  \"cooldown\": {\n    \"enabled\": false,\n    \"duration\": \"48h\"\n  },\n  \"typo\": {\n    \"enabled\": true,\n    \"threshold\": 2\n  },\n  \"osv\": {\n    \"enabled\": true,\n    \"block_on_vuln\": false,\n    \"ttl\": \"1h\",\n    \"base_url\": \"https://api.osv.dev\"\n  },\n  \"script_scan\": {\n    \"enabled\": false,\n    \"max_file_size\": 5242880,\n    \"max_total_size\": 52428800,\n    \"entropy\": { \"enabled\": true, \"threshold\": 4.5 },\n    \"obfuscation\": { \"enabled\": true, \"base64_min_length\": 100, \"hex_min_length\": 20 },\n    \"network\": { \"enabled\": true, \"allow_private_ips\": false }\n  }\n}\n```\n\n**Configuration reference:**\n\n| Section | Field | Description |\n|---------|-------|-------------|\n| Base | `port` / `host` | Proxy listen address |\n| Base | `db_path` | SQLite path; auto-skip DB check if file absent |\n| Base | `pid_file` | Daemon mode PID file path (default `malfuse.pid`) |\n| Base | `repo_proxy` | GitHub acceleration proxy domain (e.g. `ghfast.top`); omit for no proxy |\n| `logging` | `level` | `debug` / `info` / `warn` / `error` |\n| `logging` | `format` | `text` or `json` (JSON for log collection systems) |\n| `logging` | `output` | `stdout` or file path (file mode also writes to stdout) |\n| `routing` | `prefix` | URL prefix matching request path |\n| `routing` | `upstream` | Real registry URL (proxy internally uses HTTPS) |\n| `routing` | `ecosystem` | Ecosystem identifier (`pypi` / `npm`, used for DB + OSV queries) |\n| `cooldown` | `enabled` | Default off, must explicitly enable |\n| `cooldown` | `duration` | Block if OSV report published less than this duration ago |\n| `typo` | `threshold` | Block if Levenshtein distance ≤ this value |\n| `osv` | `block_on_vuln` | Whether to block on vulnerability found (default `false`, log only) |\n| `osv` | `ttl` | Query result cache duration |\n| `osv` | `base_url` | OSV API endpoint |\n| `script_scan` | `enabled` | Default off, must explicitly enable |\n| `script_scan` | `max_file_size` | Max single file to analyze (bytes), skip if larger |\n| `script_scan` | `max_total_size` | Max total stream size, stop scanning if exceeded |\n| `script_scan.entropy` | `threshold` | Shannon entropy threshold (~4.5 = upper bound of English text) |\n| `script_scan.obfuscation` | `base64_min_length` | Min base64 string length to trigger detection |\n| `script_scan.obfuscation` | `hex_min_length` | Min consecutive `\\xNN` count to trigger detection |\n| `script_scan.network` | `allow_private_ips` | Whether to allow private IPs (`10.x`, `192.168.x`, etc.) |\n\n---\n\n## Build\n\n```bash\nCGO_ENABLED=0 go build -o malfuse .\nCGO_ENABLED=0 go build -o malfuse-db ./cmd/malfuse-db/\n```\n\nPure Go, zero CGo dependencies. Single build runs on Linux / macOS (Intel + Apple Silicon) / Windows.\n\n---\n\n# Development\n\n## Directory Structure\n\n```\nmalFuse/\n├── main.go                    # malfuse proxy entry (cobra CLI)\n├── config.json                # Configuration\n├── cmd/\n│   └── malfuse-db/            # Database management CLI\n├── internal/\n│   ├── config/                # JSON config loading + validation\n│   ├── proxy/                 # HTTP proxy (routing, forwarding, health)\n│   ├── engine/                # Detection pipeline (whitelist, mal-db, cooldown, typo, OSV) + StreamChecker\n│   ├── scanner/               # Streaming script scan (entropy/obfuscation/network + JS/Python analysis)\n│   ├── osv/                   # OSV API client + in-memory TTL cache\n│   ├── logger/                # logrus structured logging wrapper\n│   ├── daemon/                # Background process management (PID, signals)\n│   ├── linker/                # Package manager config (pip/npm/pnpm/yarn)\n│   └── db/\n│       ├── schema/            # SQLite DDL + CRUD (WAL mode, DBExec interface)\n│       ├── ingest/            # OSV JSON 1.5.0 parsing + Git operations\n│       └── output/            # Direct DB write / SQL incremental file generation\n├── .github/workflows/         # CI/CD pipelines\n├── docs/                      # Manual configuration guides\n├── malfuse.db                 # SQLite database (generated by malfuse-db)\n└── ossf-malicious-packages/   # Git repo cache (gitignored)\n```\n\n## Running Tests\n\n```bash\n# All unit + integration tests\ngo test ./internal/...\n\n# Specific package\ngo test -v ./internal/scanner/\ngo test -v ./internal/engine/\n```\n\n130+ tests covering all packages.\n\n## Roadmap\n\n### ✅ P0 — Core Skeleton (Complete)\n\n- [x] HTTP reverse proxy + routing\n- [x] Malicious package SQLite database (252,637 records, 11 ecosystems)\n- [x] `malfuse-db` CLI (git incremental fetch + SQL offline mode)\n- [x] Detection pipeline (malicious-db / cooldown / typo / OSV)\n- [x] Streaming script scanner (entropy / obfuscation / network + JS/Python analysis)\n\n### ✅ P1 — Automation \u0026 Operations (Complete)\n\n- [x] `malfuse link` / `malfuse unlink` (pip / npm / pnpm / yarn)\n- [x] logrus structured logging (level control, JSON format, file output)\n- [x] `/health` health check endpoint\n- [x] Daemon mode (`malfuse start/stop/status`)\n- [x] End-to-end integration test suite\n\n### 🟢 P2 — Deep Scanning \u0026 Ecosystem Expansion\n\n- [x] `malfuse allow` whitelist management\n- [x] CI/CD Pipeline (test + DB auto-update + release on tag)\n- [ ] More ecosystem routes (RubyGems, NuGet, Crates.io, Go modules)\n- [ ] Docker image distribution\n- [ ] Install script AST analysis\n\n## Tech Stack\n\n| Component | Library |\n|-----------|---------|\n| CLI framework | `github.com/spf13/cobra` |\n| Structured logging | `github.com/sirupsen/logrus` |\n| SQLite | `modernc.org/sqlite` (pure Go, zero CGo) |\n| HTTP proxy | `net/http/httputil.ReverseProxy` (stdlib) |\n| Malicious package format | [OSV Schema 1.5.0](https://ossf.github.io/osv-schema/) |\n| Typo detection | Custom Levenshtein distance implementation |\n| Entropy detection | Custom Shannon Entropy implementation |\n| Obfuscation detection | regexp (stdlib) |\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flycshub%2Fmalfuse","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flycshub%2Fmalfuse","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flycshub%2Fmalfuse/lists"}