AI Security Review
scanned 1d ago · by lpm-firewall-aiNo confirmed malicious attack surface. The package is a CLI that manages Bitagent Gateway targets, auth, and explicit project wiring for Claude settings.
Static reason
One or more suspicious static signals were detected.
Trigger
User invokes agw commands such as agw init, login, target, doctor, or completion.
Impact
Can write local gateway config and project Claude env settings when explicitly commanded; no install-time execution or unconsented agent control mutation found.
Mechanism
User-invoked gateway CLI configuration and API client
Rationale
Static inspection shows a documented Bitagent Gateway CLI with no lifecycle hook and no import-time execution beyond normal CLI startup. The sensitive Claude settings writes are explicit agw init behavior, package-aligned, and not unconsented install-time mutation.
Evidence
package.jsonREADME.mddist/main.js~/.agw/config.json~/.agw/auth-token~/.agw/sessions/<hash>~/.agw/caps/<hash>.json~/.claude-gateway/config.json.agw.json.claude/settings.local.json
Network endpoints5
gateway.bitagent.devcompat.bitagent.devregistry.npmjs.org/-/package/bitspark-agw/dist-tags127.0.0.1:3301127.0.0.1:3300
Decision evidence
public snapshotAI called this Clean at 93.0% confidence as Benign with low false-positive risk.
Evidence for block
Evidence against
- package.json has no npm lifecycle hooks; only bin agw -> dist/main.js.
- dist/main.js main() only runs CLI dispatch after user invokes agw.
- agw init writes .claude/settings.local.json and .agw.json only as documented user-invoked project wiring.
- Network calls use configured/default Bitagent gateway admin/compat URLs and npm registry version check.
- Shell profile references are completion instructions printed to stdout, not automatic persistence.
- No credential harvesting or exfiltration beyond user-supplied gateway auth/session use.
Behavioral surface
ChildProcessCryptoEnvironmentVarsFilesystemNetworkShell
HighEntropyStringsUrlStrings
NoLicense
Source & flagged code
2 flagged · loading sourcedist/main.jsView file
22176patternName = generic_password
severity = medium
line = 22176
matchedText = if (!fro...t) {
Medium
70const here = dirname(fileURLToPath(import.meta.url));
L71: return JSON.parse(readFileSync(join(here, "..", "..", "package.json"), "utf-8")).version ?? "0.0.0";
L72: } catch {
...
L386: function defaultTarget(host, port) {
L387: return { adminUrl: `http://${host}:${port}`, compatUrl: `http://${host}:${port - 1}` };
L388: }
...
L457: ensureLegacyMigration();
L458: const hostOverride = strFlag(args.flags["host"]) ?? process.env["AGW_HOST"];
L459: const portOverride = strFlag(args.flags["port"]) ?? process.env["AGW_PORT"];
...
L470: flagTarget: strFlag(args.flags["target"]),
L471: cwd: process.cwd(),
L472: defaultHost: host,
Medium
Install Persistence
Source writes installer persistence such as shell profile or service configuration.
dist/main.jsView on unpkg · L70Findings
4 Medium5 Low
MediumSecret Patterndist/main.js
MediumNetwork
MediumEnvironment Vars
MediumInstall Persistencedist/main.js
LowScripts Present
LowFilesystem
LowHigh Entropy Strings
LowUrl Strings
LowNo License