envtrap logoenvtrap

Runtime secret leak prevention for Node.js

EnvTrap is an in-process security agent that intercepts and blocks credential exfiltration at the module-loader, network socket, DNS, and subprocess boundaries. It runs directly inside your Node.js process without external network proxies, daemons, or native C++ addons.

Quick run without installing:
npx envtrap run node app.js

The Problem: Supply Chain Exfiltration

Modern Node.js applications rely on hundreds of deeply nested third-party packages. When a dependency is compromised—via typosquatting, account takeover, or malicious updates—it has unrestricted access to process.env and full permission to send credentials over the network.

Traditional defenses fail to address this:

  • Static scanners (SAST): Only scan code at rest. They cannot evaluate runtime variables or dynamic obfuscated exfiltration payloads.
  • Network firewalls: Cannot inspect outbound HTTPS traffic without provisioning external man-in-the-middle proxies and installing system-level certificates.
  • Node permission flags: Coarse-grained and break most npm packages that require legitimate network or disk access.

EnvTrap solves this by hooking into Node.js runtime primitives at startup, monitoring exactly what is being sent through each channel before raw bytes leave the process.

The 5 Interception Channels

EnvTrap monitors and enforces policy across every physical exit vector in the runtime:

1. Network Egress Interception (TLS & Raw Sockets)

Hooks Node's internal net.Socket and tls.TLSSocket constructors. Automatically signs an ephemeral, in-RAM Root CA to parse and scan outgoing request headers and payloads inside process memory before raw ciphertext is transmitted over the wire.

2. DNS Tunneling & Sublabel Auditing

Intercepts native dns.lookup, dns.resolve, and c-ares resolver bindings. Detects base64/hex-encoded credential substrings embedded inside domain sublabels (e.g. c3Ry...evil.org) and drops the query with a synthetic NXDOMAIN.

3. Subprocess Environment Sanitization

Wraps child_process.spawn, exec, and fork. Third-party scripts or build tools attempting to shell out to curl or inspect system variables receive an environment stripped of sensitive API keys and tokens.

4. Console & Stderr Log Stream Redaction

Hooks low-level write descriptors on process.stdout and process.stderr. Prevents accidental console.log(process.env) calls or unhandled stack traces from shipping credentials to centralized log services like Datadog, CloudWatch, or Sentry.

5. Dynamic Secret Sync & Worker Threads

When environment variables are modified at runtime or fetched from secret stores (e.g. AWS Secrets Manager, Vault), EnvTrap updates its internal baseline and propagates changes across worker_threads using MessageChannel ports without thread locks.

Quickstart

No code modifications required. Works with any Node.js application.

1. Install package (npm)
npm install -g envtrap
2. Run your application under EnvTrap
envtrap run node app.js
Alternative: Programmatic Node.js register hook
node --import envtrap/register app.js

Configuration (envtrap.json)

EnvTrap works out of the box with zero configuration. You can optionally add an envtrap.json file to customize channel actions and whitelisted destinations:

envtrap.json
{
  "$schema": "https://envtrap.dev/schema.json",
  "channels": {
    "network": "block",
    "dns": "block",
    "child_process": "block",
    "stdout": "warn"
  },
  "exclusions": {
    "domains": [
      "api.stripe.com",
      "api.github.com"
    ],
    "subprocesses": [
      "git",
      "docker"
    ],
    "secrets": [
      "PUBLIC_*",
      "NEXT_PUBLIC_*"
    ]
  }
}

Hashed Incident Reports

When an exfiltration attempt is blocked, EnvTrap prints a structured incident payload to stderr. To prevent secondary leaks into centralized log collectors (Datadog, CloudWatch), the intercepted secret value is hashed using SHA-256:

incident.json (stderr alert)
{
  "timestamp": 1701315024545,
  "incidentId": "inc_9f28a301c",
  "channel": "network",
  "action": "blocked",
  "secretName": "STRIPE_SECRET_KEY",
  "sha256": "e4b4ecc7d4a4aea379f1754c7a524a87b9e0f6c24385973b18d2f5a894b91",
  "context": {
    "protocol": "https:",
    "host": "evil-c2-collector.dev",
    "port": 443,
    "path": "/collect"
  },
  "originStack": "at Object.sendTelemetry (node_modules/malicious-pkg/dist/index.js:84:14)"
}

Model Context Protocol (MCP) Integration

EnvTrap includes a Model Context Protocol endpoint so AI coding assistants (Cursor, Claude Desktop, Antigravity) can query runtime security status and inspect intercepted alerts:

Remote MCP Endpoint
https://envtrap.vercel.app/docs/mcp
Local Stdio Runner
npx -y envtrap-mcp

Frequently Asked Questions

How does EnvTrap inspect HTTPS without an external proxy?

EnvTrap boots before third-party packages. It generates an ephemeral 2048-bit Root CA in memory and attaches hooks to the internal net.Socket and tls.TLSSocket constructors, allowing it to scan request payloads inside V8 heap memory before raw ciphertext is sent.

Does EnvTrap require root/sudo privileges or native compilers?

No. EnvTrap is pure JavaScript and Node.js built-ins. It requires no elevated OS privileges, no eBPF, and no C++ compilers. It works on local machines, Docker, Kubernetes, AWS ECS/Lambda, and Google Cloud Run.

Can a malicious package bypass EnvTrap by overriding globals?

EnvTrap executes before any dependencies are imported. It freezes its internal hooks with Object.freeze and caches direct references to native C++ bindings, preventing userland code from tampering with them.

What is the performance overhead?

In production benchmarks, EnvTrap adds <1.2ms to cold start time, <14MB of heap memory, and <1.8% latency overhead on network socket calls. Ephemeral certificates and lookup tables are stored in memory with zero disk I/O.