FANGS is a delta detector, not a malware classifier. It runs each new npm package release in a sandboxed Docker container, captures every syscall and network connection from the host kernel via eBPF, and flags whatever is new relative to that package’s rolling baseline. A package that has always readDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/irchaosclub/FANGS/llms.txt
Use this file to discover all available pages before exploring further.
node_modules/lodash/* and talked to registry.npmjs.org but suddenly reads /root/.ssh/id_rsa and dials 1.2.3.4:31337 becomes one or more deviation rows for an operator to triage. Understanding what FANGS can and cannot detect is essential before relying on it in a production environment.
What FANGS Detects
FANGS surfaces six categories of behavioral deviation. Each represents a kernel-level observation that is new relative to the package’s established baseline.New Network Destinations
Any IP:port pair the package dials that was not seen in prior baseline runs. Detected via eBPF
connect/sendmsg probes at the socket layer.New DNS Lookups
Hostnames resolved via
getaddrinfo or equivalent that never appeared in prior runs. Captured before the connection attempt regardless of whether it succeeds.New HTTPS Hosts (TLS SNI)
Server Name Indication values extracted from the TLS
ClientHello. These are captured even when the underlying IP address is shared infrastructure (CDN, cloud front-end).New File Reads
File paths opened for reading that fall under a configured
watched_paths prefix and were not present in prior runs. Credential paths (/root/.ssh/, /etc/shadow) receive elevated severity.New File Writes
File paths opened for writing under a watched prefix that are new to this package. Writes to
/tmp and /run are watched but frequently suppressed via the global allow-list.New Process Spawns
Processes started by the install script (or any child process) whose executable path was not observed in prior runs — for example, a new
curl or bash invocation added to a postinstall hook.What FANGS Does NOT Detect or Prevent
FANGS has five important detection gaps: 1. Attacks that stay within the baseline. Any malicious behavior that reuses network destinations, file paths, and processes already present in the baseline is invisible to FANGS. An attacker who studies a package’s prior behavior and mimics it exactly will produce zero deviations. 2. Production-only payloads. Supply-chain attacks that activate based on environment variable checks, system hostname, time-of-day, or the presence of real credentials will not fire inside the sandbox. The sandbox has no real credentials, no production hostnames, and no secret environment variables. 3. File access outsidewatched_paths. Only paths matching a configured watched_paths prefix are tracked. Any file the package reads or writes outside those prefixes generates no events and therefore no deviations. Review and extend your watched_paths list regularly.
4. Encrypted channel content. TLS payload bytes are never inspected. FANGS records that a connection was made to a destination, and that a particular SNI was used — it does not record what data was sent or received.
5. Cgroup registration races. There is a brief window between container start and the eBPF sensor registering the container’s cgroup ID in its kernel map. Events emitted in that window may be missed. FANGS partially mitigates this with a parent-cgroup approach that widens the tracking scope, but it is not a complete fix.
Sandbox Constraints
The Docker sandbox that FANGS runs install scripts in is intentionally constrained. These limits reduce the blast radius if the sandbox is compromised, but they do not make the runner host safe to treat as trusted.| Parameter | Value | Source |
|---|---|---|
| Memory limit | 512 MB | DefaultMemoryBytes |
| CPU limit | 1 vCPU | DefaultNanoCPUs (1 × 10⁹ nanocpus) |
| PID limit | 256 | DefaultPidsLimit |
| Network mode | bridge | DefaultNetworkMode |
host network | Forbidden | Rejected by driver |
| Capabilities | All dropped (CapDrop: ALL) | buildCreatePayload |
| Privilege escalation | Blocked (no-new-privileges:true) | SecurityOpt |
| Restart policy | no | buildCreatePayload |
| Container user | 0:0 (root) | BuildSandboxScan |
/tmp | tmpfs, 256 MB, noexec | buildCreatePayload |
/run | tmpfs, 16 MB | buildCreatePayload |
| Open files (nofile) | 1024 soft / 2048 hard | ulimits |
| File size (fsize) | 256 MB | ulimits |
| Stop timeout | 5 s, then force-remove | DefaultStopTimeout |
| Image pull policy | missing (pull once) | DefaultPullPolicy |
0:0 (root) because BuildSandboxScan explicitly sets User: "0:0" — npm’s postinstall scripts often require root to write into the package directory, so the sandbox allows it. The DefaultUser constant (1000:1000) is the fallback applied only when SandboxSpec.User is left empty; scan workloads always override it. The remaining constraints (dropped capabilities, no-new-privileges, PID and memory limits) still apply.
The Docker driver communicates with the daemon over
/var/run/docker.sock using a purpose-built stdlib HTTP client (no third-party SDK). The runner binary requires CAP_BPF and access to the Docker socket, which is why fangs-runner must be started with sudo.Production Deployment Requirements
The defaults are designed for a single-host, single-operator, localhost-only setup. Before deploying into an environment where a malicious package’s exfiltration attempt actually matters, you must address the following:Enable mTLS
Turn on mutual TLS between the orchestrator and every runner. Without mTLS, anyone on the network can register a runner and receive scan jobs — potentially intercepting what packages FANGS is watching or receiving a job that lets them observe orchestrator internals. See the TLS-mTLS wiki page for the certificate lifecycle and production checklist.
Isolate the runner host
The runner executes attacker-supplied code inside a Docker sandbox. The sandbox limits damage, but a sufficiently motivated attacker may escape it. Treat the runner host as potentially compromised: do not co-locate it with systems that hold real secrets, and do not grant the runner host any network access it does not need.
Configure at least one notifier
Add a notifier via
fangs notifier add so that deviations are pushed to Slack, Discord, or a SIEM the moment they are detected. Without a notifier, operators must poll the dashboard or run fangs pending manually.Review and extend watched_paths
The default
watched_paths list in config/orchestrator.yaml covers common credential locations (/root/.ssh/, /etc/shadow, /etc/) and utility paths. Extend it to match the secrets and sensitive files present in your environment.Threat Matrix Summary
| Threat | FANGS response | Gap? |
|---|---|---|
| New exfil destination added to postinstall | Detected — net_new_destination deviation | — |
| New DNS lookup for C2 hostname | Detected — net_new_dns deviation | — |
| New TLS SNI for data exfil | Detected — net_new_https_host deviation | — |
Read of /root/.ssh/id_rsa (new) | Detected — fs_new_path_read, severity crit | — |
| New shell spawn in postinstall hook | Detected — proc_new_exec deviation | — |
| Attack re-uses already-baselined destination | Not detected | ✗ |
Payload only fires when NODE_ENV=production | Not detected (sandbox has no such env) | ✗ |
File read outside watched_paths | Not detected | ✗ |
| Content of TLS-encrypted exfil stream | Not detected (only destination is recorded) | ✗ |
| Events during cgroup registration window | Possibly missed (partially mitigated) | ✗ |