registry  /  @openafw/openafw  /  0.10.1

@openafw/openafw@0.10.1

The local firewall for AI agents: route and repair them, and keep your secrets off the model, the API relay, and the supply chain. Local credential masking, per-route model routing, and security detectors on the wire. Free and fully open source.

AI Security Review

scanned 5d ago · by lpm-firewall-ai

No confirmed malicious attack surface was found by static inspection. The package is a user-invoked AI-agent firewall/proxy CLI with local daemon, routing, web search/fetch tools, and optional update/service commands.

Static reason
One or more suspicious static signals were detected.
Trigger
User runs afw, afw-tap, afw-tools, daemon, wire, service, update, or launch-wrapper commands.
Impact
Expected package behavior includes local config writes, local daemon HTTP traffic, upstream model/search requests, and optional service/update changes; no hidden install-time execution or credential exfiltration was identified.
Mechanism
local proxy/firewall CLI with explicit configuration and user-invoked subprocess/network operations
Rationale
Scanner findings map to expected AFW functionality: local daemon/proxy operation, user-invoked agent wrapping, configured provider requests, and guarded web tools. There is no lifecycle execution, hidden import-time behavior, unconsented exfiltration, destructive action, or AI-agent control-surface mutation outside explicit CLI workflows.
Evidence
package.jsondist/bin/afw.jsdist/bin/tap.jsdist/bin/tools.jsdist/secrets-Bwiz887p.jsdist/backends-Cks6xMcx.js~/.afw/*~/.claude/settings.json~/.claude.json~/Library/Application Support/Claude/claude_desktop_config.json~/.openclaw/openclaw.json~/.config/opencode/opencode.json~/.hermes/config.yaml~/.hermes/.env~/.codex/config.toml~/.codex/auth.json~/.config/Cursor/User/settings.json~/.gemini/.env

Decision evidence

public snapshot
AI called this Clean at 90.0% confidence as Benign with low false-positive risk.
Evidence for block
    Evidence against
    • package.json has no install/postinstall lifecycle hooks; binaries are user-invoked CLI entries.
    • dist/bin/tap.js only spawns the command after an explicit '--' and posts parsed JSON frames to local AFW daemon by default.
    • dist/bin/tools.js web_fetch blocks localhost, private IP literals, link-local, and metadata hosts before fetching.
    • dist/secrets-Bwiz887p.js stores AFW config/secrets under AFW_HOME or ~/.afw with atomic writes, not import-time exfiltration.
    • dist/bin/afw.js child_process usage is tied to daemon launch, service management, explicit agent wrapping, lsof probing, and user-triggered update flows.
    • Network endpoints are package-aligned model/search/update providers such as OpenAI, Anthropic, Brave, DuckDuckGo, Baidu, and npm registry.
    Behavioral surface
    Source
    ChildProcessCryptoEnvironmentVarsFilesystemNetworkShell
    Supply chain
    HighEntropyStringsMinifiedUrlStrings
    ManifestNo manifest risk signals triggered.
    scanned 7 file(s), 1.69 MB of source, external domains: afw-unconfigured.invalid, api.anthropic.com, api.cerebras.ai, api.deepinfra.com, api.deepseek.com, api.fireworks.ai, api.groq.com, api.mistral.ai, api.moonshot.ai, api.novita.ai, api.openai.com, api.search.brave.com, api.stepfun.ai, api.together.ai, api.together.xyz, api.venice.ai, api.xiaomimimo.com, api.z.ai, app.fireworks.ai, auth.openai.com, build.nvidia.com, chatgpt.com, claude.ai, cloud.cerebras.ai, console.anthropic.com, console.groq.com, console.mistral.ai, deepinfra.com, html.duckduckgo.com, integrate.api.nvidia.com, novita.ai, openafw.com, openrouter.ai, platform.claude.com, platform.deepseek.com, platform.moonshot.ai, platform.openai.com, qianfan.baidubce.com, react.dev, registry.npmjs.org, venice.ai, www.w3.org, z.ai

    Source & flagged code

    6 flagged · loading source
    dist/bin/afw.jsView file
    5import process$1 from "node:process"; L6: import { execFileSync, spawn } from "node:child_process"; L7: import { basename, delimiter, dirname, extname, isAbsolute, join, normalize, sep } from "node:path";
    High
    Child Process

    Package source references child process execution.

    dist/bin/afw.jsView on unpkg · L5
    1871if (process$2.versions?.electron) parseOptions$1.from = "electron"; L1872: const execArgv = process$2.execArgv ?? []; L1873: if (execArgv.includes("-e") || execArgv.includes("--eval") || execArgv.includes("-p") || execArgv.includes("--print")) parseOptions$1.from = "eval";
    High
    Shell

    Package source references shell execution.

    dist/bin/afw.jsView on unpkg · L1871
    5import process$1 from "node:process"; L6: import { execFileSync, spawn } from "node:child_process"; L7: import { basename, delimiter, dirname, extname, isAbsolute, join, normalize, sep } from "node:path"; ... L13: import { parse } from "jsonc-parser"; L14: import { createServer } from "node:http"; L15: import { Buffer as Buffer$1 } from "node:buffer"; ... L24: import { join as join$1 } from "path"; L25: import { gunzipSync, gzipSync } from "node:zlib"; L26: import Database from "better-sqlite3"; ... L68: * Constructs the CommanderError class L69: * @param {number} exitCode suggested exit code which could be used with process.exit L70: * @param {string} code an id string representing the error
    Medium
    Install Persistence

    Source writes installer persistence such as shell profile or service configuration.

    dist/bin/afw.jsView on unpkg · L5
    dist/bin/tap.jsView file
    20const SERVER = readFlag(flags, "--server") ?? "unknown"; L21: const DAEMON_URL = process.env.AFW_DAEMON_URL ?? "http://localhost:9877"; L22: const child = spawn(cmd, cmdArgs, { stdio: [ L23: "pipe",
    High
    Same File Env Network Execution

    A single source file combines environment access, network access, and code or shell execution; review context before blocking.

    dist/bin/tap.jsView on unpkg · L20
    8if (sep < 0) { L9: process.stderr.write("afw-tap: missing -- separator; expected --agent X --server Y -- <cmd> [args...]\n"); L10: process.exit(2); ... L20: const SERVER = readFlag(flags, "--server") ?? "unknown"; L21: const DAEMON_URL = process.env.AFW_DAEMON_URL ?? "http://localhost:9877"; L22: const child = spawn(cmd, cmdArgs, { stdio: [ L23: "pipe",
    High
    Command Output Exfiltration

    Source combines command execution, command-output handling, and outbound requests; review data flow before blocking.

    dist/bin/tap.jsView on unpkg · L8
    dist/bin/tools.jsView file
    6//#region src/core/web-search/fetch.ts L7: const FETCH_USER_AGENT = "afw-tools/0.1 (+https://openafw.com)"; L8: const DEFAULT_MAX_BYTES = 1024 * 1024; ... L51: } L52: /** Reject URLs that point at the local machine, private networks, L53: * link-local space, or cloud metadata endpoints. Operates on the URL ... L143: return { L144: text: new TextDecoder("utf-8", { fatal: false }).decode(merged), L145: truncated ... L214: function send(msg) { L215: process.stdout.write(`${JSON.stringify(msg)}\n`); L216: }
    High
    Cloud Metadata Access

    Source reaches cloud instance metadata or link-local credential endpoints.

    dist/bin/tools.jsView on unpkg · L6

    Findings

    5 High4 Medium4 Low
    HighChild Processdist/bin/afw.js
    HighShelldist/bin/afw.js
    HighSame File Env Network Executiondist/bin/tap.js
    HighCommand Output Exfiltrationdist/bin/tap.js
    HighCloud Metadata Accessdist/bin/tools.js
    MediumNetwork
    MediumEnvironment Vars
    MediumInstall Persistencedist/bin/afw.js
    MediumStructural Risk Force Deep Review
    LowScripts Present
    LowFilesystem
    LowHigh Entropy Strings
    LowUrl Strings