registry  /  @blksails/pi-web-server  /  0.3.1

@blksails/pi-web-server@0.3.1

AI Security Review

scanned 2h ago · by lpm-firewall-ai

LPM treats this as warn-only first-party agent extension lifecycle risk. No install-time attack behavior is established. The package deliberately exposes user-requested, admin-gated Pi extension management and runs supplied agent code in an isolated runner subprocess.

Static reason
No blocking static signals were detected.
Trigger
An administrator requests extension installation/removal, or the host launches the runner with a selected agent entry.
Impact
A permitted caller can change the Pi agent extension/configuration surface and execute the selected agent's code; this is a real agent-management capability, not hidden package behavior.
Mechanism
Admin-gated Pi CLI extension lifecycle and subprocess loading of user agent modules.
Rationale
The package is not concretely malicious, but it contains a meaningful first-party AI-agent extension lifecycle capability and explicit agent-config mutation surface. Downgrade to warn rather than block because these paths are user/API-triggered, constrained, and not install-time or stealthy.
Evidence
package.jsonrunner-bootstrap.mjssrc/runner/agent-loader.tssrc/extensions/security/admin-policy.tssrc/extensions/install/source-allowlist.tssrc/config/mcp-config-routes.tssrc/runner/runner.tssrc/extensions/routes/install-extension.tssrc/extensions/cli/pi-cli.ts

Decision evidence

public snapshot
AI called this Suspicious at 84.0% confidence as Dangerous Capability with medium false-positive risk.
Evidence for warning
  • `src/extensions/routes/install-extension.ts` invokes the Pi CLI after an admin-gated HTTP install request.
  • `src/extensions/cli/pi-cli.ts` spawns the installed Pi CLI with extension-management arguments.
  • `src/config/mcp-config-routes.ts` can write `<agentDir>/mcp.json` through an explicit PUT request.
  • `src/runner/agent-loader.ts` dynamically imports a user-selected agent entry in a runner subprocess.
Evidence against
  • `package.json` has no preinstall, install, postinstall, or other lifecycle hook.
  • `runner-bootstrap.mjs` imports only the package-local runner path, not a remote or request-supplied module.
  • `src/extensions/security/admin-policy.ts` denies extension-changing operations by default.
  • `src/extensions/install/source-allowlist.ts` defaults to scoped npm/git allowlists and requires pinned versions or refs.
  • No hard-coded exfiltration endpoint, credential harvesting, eval/vm use, destructive action, or stealth persistence was found.
Behavioral surface
Source
ChildProcessCryptoDynamicRequireEnvironmentVarsFilesystemShellWebSocket
Supply chain
HighEntropyStrings
Manifest
NoLicense
scanned 203 file(s), 992 KB of source

Source & flagged code

1 flagged · loading source
runner-bootstrap.mjsView file
37async function bootstrap() { L38: const mod = await jiti.import(runnerTs); L39: const main = mod.main ?? mod.default?.main;
Medium
Dynamic Require

Package source references dynamic require/import behavior.

runner-bootstrap.mjsView on unpkg · L37

Findings

2 Medium4 Low
MediumDynamic Requirerunner-bootstrap.mjs
MediumEnvironment Vars
LowScripts Present
LowFilesystem
LowHigh Entropy Strings
LowNo License