AI Security Review
scanned 2h ago · by lpm-firewall-aiNo install-time malicious behavior is established. A user-invoked `create-app` command builds an unquoted `zsh` command from a filesystem-derived path, enabling shell injection through a crafted directory or `--dir` value.
Static reason
High-risk behavior combination matched malicious policy.
Trigger
Run `fnd create-app` from a crafted working directory or with a crafted `--dir` value.
Impact
Arbitrary shell commands may execute with the invoking user's permissions.
Mechanism
Unquoted path interpolation into `spawn(..., { shell: 'zsh' })`.
Rationale
The package is not malicious by source inspection, but it contains a concrete user-triggered shell-injection vulnerability in `create-app`. Flag as warn until the shell invocation is removed or path arguments are safely passed without a shell.
Evidence
package.jsondist/commands/create-app.jsdist/commands/workspace/index.jsdist/lib/workspace.jsdist/lib/scaffold.jsdist/commands/token.js~/.ssh/authorized_keys./CLAUDE.md.gitignore.shopifyignore
Network endpoints4
registry.npmjs.org/${store}/admin/oauth/authorize${store}/admin/oauth/access_tokengithub.com
Decision evidence
public snapshotAI called this Suspicious at 90.0% confidence as Critical Vulnerability with low false-positive risk.
Evidence for warning
- `dist/commands/create-app.js` interpolates `targetDir` into a `zsh` shell command without quoting.
- `targetDir` derives from user `--dir` and `process.cwd()`, creating command-injection risk when `create-app` runs.
- `dist/lib/workspace.js` adds a remote key to `~/.ssh/authorized_keys` during explicit workspace setup.
- `dist/lib/scaffold.js` invokes Claude with edit and Bash tools to generate `./CLAUDE.md` on explicit scaffold commands.
Evidence against
- `package.json` has no `preinstall`, `install`, or `postinstall` lifecycle hook.
- CLI entrypoints only dispatch Oclif commands; no import-time payload execution was found.
- Workspace key changes are marker-scoped and removed in `finally` or `workspace cleanup`.
- Network use targets update checks, GitHub/Shopify operations, and user-selected SSH hosts; no covert exfiltration path was found.
- `token --write` changes only the explicit path supplied by the user.
Behavioral surface
ChildProcessCryptoEnvironmentVarsFilesystemNetworkShell
HighEntropyStrings
Source & flagged code
3 flagged · loading sourcedist/commands/create-project.jsView file
2import chalk from 'chalk';
L3: import { spawnSync } from 'node:child_process';
L4: import { existsSync, writeFileSync } from 'node:fs';
...
L11: };
L12: static description = 'Scaffold a new client project: git on branch production, ignore files, Shopify theme pull, a Claude-generated CLAUDE.md, then a private GitHub repo under the ...
L13: static examples = [
...
L25: // 1. git init on branch 'production'
L26: if (existsSync(join(process.cwd(), '.git'))) {
L27: this.log(chalk.blue('ℹ️ git repo already initialized — leaving the current branch as-is'));
...
L44: this.log(chalk.blue(`🎨 Pulling Shopify theme from store '${shop}' (via ${shopifyBin})…`));
L45: const env = { ...process.env, PATH: `${dirname(shopifyBin)}:${process.env.PATH}` };
L46: await run(shopifyBin, ['theme', 'pull', `--store=${shop}`], env);
Medium
Install Persistence
Source writes installer persistence such as shell profile or service configuration.
dist/commands/create-project.jsView on unpkg · L2dist/lib/workspace.jsView file
1import { spawn, spawnSync } from 'node:child_process';
L2: import { randomInt } from 'node:crypto';
L3: import { appendFileSync, chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
L4: import { connect } from 'node:net';
L5: import { homedir, userInfo } from 'node:os';
...
L15: };
L16: /** The authorized_keys marker comment for a given mount — used to add and later remove the key. */
L17: export const keyCommentForMount = (mount) => `fnd-workspace:${mount}`;
...
L19: export const buildContext = (opts) => {
L20: const localUser = userInfo().username;
L21: const localCwd = opts.cwd;
...
L50: ].join('\n');
Critical
Persistence Backdoor
Source writes persistence or remote-access backdoor material.
dist/lib/workspace.jsView on unpkg · L1bin/dev.cmdView file
•path = bin/dev.cmd
kind = build_helper
sizeBytes = 86
magicHex = [redacted]
Medium
Findings
1 Critical5 Medium3 Low
CriticalPersistence Backdoordist/lib/workspace.js
MediumNetwork
MediumEnvironment Vars
MediumInstall Persistencedist/commands/create-project.js
MediumShips Build Helperbin/dev.cmd
MediumStructural Risk Force Deep Review
LowScripts Present
LowFilesystem
LowHigh Entropy Strings