Hi — while running an automated NL-quality audit on this repository (NLPM), the security pre-scan flagged two patterns I think are worth surfacing privately rather than as PRs. Friendly notice; both may be intentional.
Findings
| # |
Severity |
File |
Line |
Pattern |
| 1 |
Critical |
scripts/modules/prompt-manager.js |
280 |
new Function(...) evaluating template-config conditions |
| 2 |
Critical |
packages/claude-code-plugin/commands/install-taskmaster.md |
95 |
curl … | bash inside a Claude command file |
| 3 |
High |
packages/claude-code-plugin/commands/install-taskmaster.md |
79 |
sudo npm install -g in the same command file |
| 4 |
Medium |
.mcp.json |
5 |
npx -y task-master-ai — no version pin, auto-confirm |
| 5 |
Low |
package.json |
63–125 |
^ semver range on security-sensitive deps (jsonwebtoken, undici, express) |
Finding #1 — hidden eval in template-config
new Function(...Object.keys(context), `return ${condition}`)
new Function() is functionally equivalent to eval(). The condition argument flows from template configuration. If any code path lets user-controllable data reach condition (a custom prompt pack, an editable template file, a config reload from disk), this is RCE shaped exactly like a classic eval injection.
Safer shape: a small expression evaluator (e.g., expr-eval or a custom AST walker) that only permits the operators your conditions actually need. Even a hardcoded allowlist of condition strings would close the gap.
Finding #2 — curl-pipe-sh inside a Claude command
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash
Embedding curl … | bash inside a Claude command file means Claude will run it as part of /taskmaster:install-taskmaster without the user seeing what the remote URL serves at fetch time. Two problems compound:
- The pinned tag (
v0.39.0) doesn't pin the content — a tag can be moved.
- A user invoking
/taskmaster:install-taskmaster doesn't get the standard "you're about to pipe curl into bash" cognitive friction.
Safer shape: download the script, show its checksum to the user, then execute with explicit consent. Or detect nvm presence and instruct the user to install it themselves before running the rest of the workflow.
Finding #3 — sudo in a Claude command
sudo npm install -g task-master-ai
Same file as #2. Claude executing sudo inside an automated workflow asks the user to type their root password as a side effect of running a slash command — surprising, and in CI contexts won't work at all. The npm install itself should probably be done at user scope (npm install -g without sudo on a user-owned npm prefix, or pnpm/yarn with their own paths).
Findings #4 and #5
Lower priority but worth a glance: npx -y skips the prompt that would normally let a user catch a swapped package, and ^-range semver on jsonwebtoken/undici/express means a future minor version with a vulnerability flows in without a review.
About this report
Findings come from NLPM's security pattern matcher applied to executable artifacts. The matcher surfaces patterns; intent is on the maintainer to confirm. If any are intentional, please close this issue. If you'd like fix PRs for any of them, let me know which and I'll send them — keeping security issues off the public PR queue while you triage.
Hi — while running an automated NL-quality audit on this repository (NLPM), the security pre-scan flagged two patterns I think are worth surfacing privately rather than as PRs. Friendly notice; both may be intentional.
Findings
scripts/modules/prompt-manager.jsnew Function(...)evaluating template-config conditionspackages/claude-code-plugin/commands/install-taskmaster.mdcurl … | bashinside a Claude command filepackages/claude-code-plugin/commands/install-taskmaster.mdsudo npm install -gin the same command file.mcp.jsonnpx -y task-master-ai— no version pin, auto-confirmpackage.json^semver range on security-sensitive deps (jsonwebtoken,undici,express)Finding #1 — hidden eval in template-config
new Function()is functionally equivalent toeval(). Theconditionargument flows from template configuration. If any code path lets user-controllable data reachcondition(a custom prompt pack, an editable template file, a config reload from disk), this is RCE shaped exactly like a classic eval injection.Safer shape: a small expression evaluator (e.g.,
expr-evalor a custom AST walker) that only permits the operators your conditions actually need. Even a hardcoded allowlist of condition strings would close the gap.Finding #2 — curl-pipe-sh inside a Claude command
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bashEmbedding
curl … | bashinside a Claude command file means Claude will run it as part of/taskmaster:install-taskmasterwithout the user seeing what the remote URL serves at fetch time. Two problems compound:v0.39.0) doesn't pin the content — a tag can be moved./taskmaster:install-taskmasterdoesn't get the standard "you're about to pipe curl into bash" cognitive friction.Safer shape: download the script, show its checksum to the user, then execute with explicit consent. Or detect nvm presence and instruct the user to install it themselves before running the rest of the workflow.
Finding #3 — sudo in a Claude command
Same file as #2. Claude executing
sudoinside an automated workflow asks the user to type their root password as a side effect of running a slash command — surprising, and in CI contexts won't work at all. Thenpm installitself should probably be done at user scope (npm install -gwithout sudo on a user-ownednpm prefix, orpnpm/yarnwith their own paths).Findings #4 and #5
Lower priority but worth a glance:
npx -yskips the prompt that would normally let a user catch a swapped package, and^-range semver onjsonwebtoken/undici/expressmeans a future minor version with a vulnerability flows in without a review.About this report
Findings come from NLPM's security pattern matcher applied to executable artifacts. The matcher surfaces patterns; intent is on the maintainer to confirm. If any are intentional, please close this issue. If you'd like fix PRs for any of them, let me know which and I'll send them — keeping security issues off the public PR queue while you triage.