AI Security Review
scanned 11d ago · by lpm-firewall-aiNo confirmed malicious attack surface was found. The risky primitives are aligned with a universal server CLI: serving HTTP, loading user entry files, optional env files, and explicit fetch requests.
Static reason
One or more suspicious static signals were detected.
Trigger
User invokes srvx CLI or imports server adapters
Impact
User-requested local server/fetch operations only; no unconsented install-time or import-time compromise identified
Mechanism
server runtime and CLI helper behavior
Rationale
Static inspection shows a legitimate server package with CLI-driven child process, dynamic local entry loading, static file serving, and explicit fetch support. There is no lifecycle execution, hidden exfiltration, persistence, destructive behavior, or remote payload retrieval.
Evidence
package.jsonbin/srvx.mjsdist/cli.mjsdist/loader.mjsdist/static.mjsdist/adapters/node.mjsdist/adapters/bun.mjsdist/adapters/deno.mjsdist/_chunks/_utils2.mjs
Decision evidence
public snapshotAI called this Clean at 93.0% confidence as Benign with low false-positive risk.
Evidence for block
- dist/cli.mjs imports node:child_process fork
- dist/loader.mjs dynamically imports user-selected server entry
- dist/cli.mjs fetch mode can request user-supplied remote URLs
- dist/cli.mjs reads .env files and @file request bodies when CLI is invoked
Evidence against
- package.json has no install/postinstall lifecycle scripts
- bin/srvx.mjs only forwards to dist/cli.mjs main
- fork in dist/cli.mjs re-executes the package CLI for watch/env-file behavior
- dynamic import in dist/loader.mjs loads local user server entrypoints, not remote code
- network behavior is explicit server/fetch CLI functionality
- No credential harvesting, persistence, destructive writes, or exfiltration endpoints found
Behavioral surface
ChildProcessDynamicRequireEnvironmentVarsFilesystemNetworkShell
HighEntropyStringsUrlStrings
WildcardDependency
Source & flagged code
4 flagged · loading sourcedist/cli.mjsView file
4import { fileURLToPath } from "node:url";
L5: import { fork } from "node:child_process";
L6: import { createReadStream, existsSync, statSync } from "node:fs";
High
372async function forkCLI(args, runtimeArgs) {
L373: const child = fork(fileURLToPath(globalThis.__SRVX_BIN__ || new URL("../bin/srvx.mjs", import.meta.url)), [...args], { execArgv: [...process.execArgv, ...runtimeArgs].filter(Boolea...
L374: child.on("error", (error) => {
High
4Cross-file remote execution chain: dist/cli.mjs spawns dist/loader.mjs; helper contains network access plus dynamic code execution.
L4: import { fileURLToPath } from "node:url";
L5: import { fork } from "node:child_process";
L6: import { createReadStream, existsSync, statSync } from "node:fs";
...
L11: try {
L12: if (!process.env.NODE_ENV) process.env.NODE_ENV = cliOpts.prod ? "production" : "development";
L13: let server;
...
L90: }
L91: async function cliFetch(cliOpts) {
L92: const stdin = cliOpts.stdin || process.stdin;
L93: const stdout = cliOpts.stdout || process.stdout;
L94: const stderr = cliOpts.stderr || process.stderr;
...
L103: if (cliOpts.verbose && loaded.url) {
High
Cross File Remote Execution Context
Source spawns a local helper that also contains network and dynamic execution context; review data flow before blocking.
dist/cli.mjsView on unpkg · L4dist/loader.mjsView file
41if (opts.interceptHttpListen !== false) {
L42: const loaded = await interceptListen(() => import(url), opts);
L43: mod = loaded.res;
Medium
Dynamic Require
Package source references dynamic require/import behavior.
dist/loader.mjsView on unpkg · L41Findings
3 High4 Medium4 Low
HighChild Processdist/cli.mjs
HighShelldist/cli.mjs
HighCross File Remote Execution Contextdist/cli.mjs
MediumDynamic Requiredist/loader.mjs
MediumNetwork
MediumEnvironment Vars
MediumWildcard Dependency
LowScripts Present
LowFilesystem
LowHigh Entropy Strings
LowUrl Strings