Skip to main content

Documentation 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.

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 read 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

Read this section before deploying FANGS in any environment where a missed detection has real consequences. These are architectural limitations, not bugs.
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 outside watched_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.
ParameterValueSource
Memory limit512 MBDefaultMemoryBytes
CPU limit1 vCPUDefaultNanoCPUs (1 × 10⁹ nanocpus)
PID limit256DefaultPidsLimit
Network modebridgeDefaultNetworkMode
host networkForbiddenRejected by driver
CapabilitiesAll dropped (CapDrop: ALL)buildCreatePayload
Privilege escalationBlocked (no-new-privileges:true)SecurityOpt
Restart policynobuildCreatePayload
Container user0:0 (root)BuildSandboxScan
/tmptmpfs, 256 MB, noexecbuildCreatePayload
/runtmpfs, 16 MBbuildCreatePayload
Open files (nofile)1024 soft / 2048 hardulimits
File size (fsize)256 MBulimits
Stop timeout5 s, then force-removeDefaultStopTimeout
Image pull policymissing (pull once)DefaultPullPolicy
The container user is 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:
1

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.
2

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.
3

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.
4

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.
5

Set up a baseline before trusting results

Every package needs at least one clean baseline run before deviations are meaningful. Use fangs package add <name> to trigger an immediate kickoff scan. That first run becomes the baseline. Subsequent releases are compared against it.

Threat Matrix Summary

ThreatFANGS responseGap?
New exfil destination added to postinstallDetected — net_new_destination deviation
New DNS lookup for C2 hostnameDetected — net_new_dns deviation
New TLS SNI for data exfilDetected — net_new_https_host deviation
Read of /root/.ssh/id_rsa (new)Detected — fs_new_path_read, severity crit
New shell spawn in postinstall hookDetected — proc_new_exec deviation
Attack re-uses already-baselined destinationNot detected
Payload only fires when NODE_ENV=productionNot detected (sandbox has no such env)
File read outside watched_pathsNot detected
Content of TLS-encrypted exfil streamNot detected (only destination is recorded)
Events during cgroup registration windowPossibly missed (partially mitigated)

Build docs developers (and LLMs) love