function runInstaller(command, options) {
return cp.spawn(shell(), ["-c", command], options);
}
JS 1.0 · Project evidence
JS Snippet (Plugin Installer): Find Vulnerabilities
Small Express plugin installer service with shell-based package installation.
Project purpose and scale
JS Snippet (Plugin Installer): Find Vulnerabilities
Small Express plugin installer service with shell-based package installation.
- Source files
- 2
- Reference findings
- 3
- Matched signatures
- 10
- Unmatched signatures
- 18
Reference context
Deterministic reference findings
These findings define the project reference set for JS 1.0. Their presence does not establish exhaustive ground truth.
| Class | Severity | Location | Reference ID |
|---|---|---|---|
| command-injection | high | app.js:17 | jcl-command-injection-1 |
| insecure-transport | medium | app.js:43 | jcl-insecure-transport-1 |
| allocation-of-resources-without-limits-or-throttling | medium | app.js:20 | jcl-no-rate-limit-1 |
Finding evidence
Reference-matched normalized signatures
Matched means agreement with the Snyk Code reference set, not independent ground-truth adjudication.
Severity and description show the deterministic most-frequent metadata variant; the final column records how many variants were observed across repetitions.
| Configuration | Class | Representative severity | Location | Recurrence | Representative description | Metadata variants |
|---|---|---|---|---|---|---|
| Claude Opus 4.6 High | command-injection | high | app.js:17 | 5 of 5 | User-controlled plugin package data flows into child_process.spawn through a shell command. | 1 |
| Claude Opus 4.6 Medium | command-injection | high | app.js:17 | 5 of 5 | User-controlled plugin package data flows into child_process.spawn through a shell command. | 1 |
| Claude Opus 4.7 Max | allocation-of-resources-without-limits-or-throttling | medium | app.js:20 | 2 of 5 | The plugin installation endpoint performs expensive command execution without rate limiting. | 1 |
| Claude Opus 4.7 Max | command-injection | high | app.js:17 | 5 of 5 | User-controlled plugin package data flows into child_process.spawn through a shell command. | 1 |
| Claude Sonnet 4.6 High | allocation-of-resources-without-limits-or-throttling | medium | app.js:20 | 5 of 5 | The plugin installation endpoint performs expensive command execution without rate limiting. | 1 |
| Claude Sonnet 4.6 High | command-injection | high | app.js:17 | 5 of 5 | User-controlled plugin package data flows into child_process.spawn through a shell command. | 1 |
| Claude Sonnet 4.6 High | insecure-transport | medium | app.js:43 | 5 of 5 | The service is created with a plaintext HTTP server. | 1 |
| Claude Sonnet 4.6 Medium | allocation-of-resources-without-limits-or-throttling | medium | app.js:20 | 5 of 5 | The plugin installation endpoint performs expensive command execution without rate limiting. | 1 |
| Claude Sonnet 4.6 Medium | command-injection | high | app.js:17 | 5 of 5 | User-controlled plugin package data flows into child_process.spawn through a shell command. | 1 |
| Claude Sonnet 4.6 Medium | insecure-transport | medium | app.js:43 | 5 of 5 | The service is created with a plaintext HTTP server. | 1 |
Finding evidence
Unmatched normalized signatures
Unmatched reports may be false-positive-shaped, adjacent, or likely product-gap candidates.
Severity and description show the deterministic most-frequent metadata variant; the final column records how many variants were observed across repetitions.
| Configuration | Class | Representative severity | Location | Recurrence | Representative description | Metadata variants |
|---|---|---|---|---|---|---|
| Claude Opus 4.6 High | information-exposure | medium | app.js:35 | 2 of 5 | The full stdout and stderr output from the spawned shell command is returned to the client in the JSON response. This can expose internal server paths, environment details, installed package versions, and other sensitive system information, especially when command injection is also possible. | 2 |
| Claude Opus 4.7 Max | csrf | medium | app.js:20 | 1 of 5 | State-changing POST endpoint /plugins/install has no CSRF protection or origin/authentication checks, allowing cross-site requests to trigger plugin installations. | 1 |
| Claude Opus 4.7 Max | improper-type-validation | low | app.js:21 | 3 of 5 | req.body.package is used without type validation; a non-string value (object/array) could cause unexpected coercion or template interpolation behavior. | 3 |
| Claude Opus 4.7 Max | information-exposure | low | app.js:35 | 3 of 5 | Raw stdout/stderr from the npm/shell child process is returned in the HTTP response, leaking internal filesystem paths, package manager errors, and other implementation details to clients. | 3 |
| Claude Opus 4.7 Max | other | high | app.js:20 | 1 of 5 | Missing authentication/authorization: the plugin install endpoint is fully unauthenticated, allowing any remote caller to trigger installation of arbitrary npm packages, which can execute install scripts and lead to remote code execution via malicious packages. | 1 |
| Claude Sonnet 4.6 High | allocation-of-resources-without-limits-or-throttling | medium | app.js:20 | 1 of 5 | The /plugins/install endpoint has no rate limiting. An attacker can flood it with requests to spawn many parallel npm processes, exhausting CPU, memory, and network resources (denial of service). | 1 |
| Claude Sonnet 4.6 High | allocation-of-resources-without-limits-or-throttling | medium | app.js:23 | 1 of 5 | The spawned child process has no timeout configured. A hanging or deliberately slow npm install can occupy a process slot and accumulate unbounded output in the 'output' buffer indefinitely, leading to resource exhaustion. | 1 |
| Claude Sonnet 4.6 High | command-injection | critical | app.js:17 | 1 of 5 | runInstaller() passes the full command string to cp.spawn via 'sh -c', enabling shell interpretation of the entire command. This design pattern is inherently unsafe when any part of the command string derives from external input, as it is here. | 1 |
| Claude Sonnet 4.6 High | csrf | high | app.js:20 | 3 of 5 | The POST /plugins/install endpoint has no CSRF protection (no CSRF token, no Origin/Referer validation). A malicious third-party site can trigger plugin installations cross-site on behalf of a victim. | 3 |
| Claude Sonnet 4.6 High | improper-type-validation | high | app.js:21 | 1 of 5 | There is no validation that `req.body.package` is a string, matches a valid npm package-name format, or is restricted to an allowlist of permitted packages. Any value (including objects, arrays, or strings with shell metacharacters) is accepted and used directly in command construction. | 1 |
| Claude Sonnet 4.6 High | information-exposure | high | app.js:35 | 5 of 5 | The full stdout and stderr output of the spawned shell process is collected and returned verbatim in the JSON response (`output` field). This can expose sensitive server-side information such as internal file paths, system configuration, environment details leaked by npm, and error messages that aid in reconnaissance. | 5 |
| Claude Sonnet 4.6 High | other | critical | app.js:20 | 4 of 5 | The `POST /plugins/install` endpoint has no authentication or authorization checks whatsoever. Any unauthenticated caller on the network can invoke it, which — combined with the command-injection vulnerability — provides trivially unauthenticated remote code execution. | 4 |
| Claude Sonnet 4.6 High | path-traversal | high | app.js:22 | 1 of 5 | Because packageName is user-controlled and unsanitized, an attacker can supply a 'file:' protocol package reference (e.g., 'file:../../../sensitive/dir') to npm install, causing npm to read from arbitrary filesystem paths outside the intended plugins directory. | 1 |
| Claude Sonnet 4.6 Medium | allocation-of-resources-without-limits-or-throttling | medium | app.js:26 | 1 of 5 | The output variable accumulates child-process stdout/stderr chunks without any size limit. A malicious or runaway process can produce unbounded output, exhausting heap memory. | 1 |
| Claude Sonnet 4.6 Medium | csrf | low | app.js:20 | 2 of 5 | The state-changing POST /plugins/install endpoint has no CSRF token validation, allowing cross-site request forgery attacks in browser-accessible deployments. | 2 |
| Claude Sonnet 4.6 Medium | information-exposure | medium | app.js:35 | 5 of 5 | The full stdout and stderr of the npm child process is returned to the caller. This may leak sensitive data such as absolute filesystem paths, npm registry tokens, or environment variable values from lifecycle scripts. | 5 |
| Claude Sonnet 4.6 Medium | other | high | app.js:20 | 3 of 5 | The /plugins/install endpoint has no authentication or authorization. Any unauthenticated network caller can trigger package installation or exploit the command injection vulnerability. | 3 |
| Claude Sonnet 4.6 Medium | other | high | app.js:21 | 1 of 5 | No input validation is performed on the package name. It should be validated against a strict allowlist or a regex matching valid npm package names before use in a shell command. | 1 |
Model behavior
Recurrence by configuration
Stable recurrence measures repeated behavior, not independent validity.
| Configuration | Matched signatures | Matched all five | Unmatched signatures | Unmatched all five |
|---|---|---|---|---|
| Claude Opus 4.6 High | 1 | 1 | 1 | 0 |
| Claude Opus 4.6 Medium | 1 | 1 | 0 | 0 |
| Claude Opus 4.7 Max | 2 | 1 | 4 | 0 |
| Claude Sonnet 4.6 High | 3 | 3 | 8 | 1 |
| Claude Sonnet 4.6 Medium | 3 | 3 | 5 | 1 |
Inspectable source context
Reference locations
Apache-licensed fixture excerpts are shown around declared reference lines. They are evidence, not runnable examples.
});
const server = http.createServer(app);
const port = process.env.PORT || 3000;
}
app.post("/plugins/install", (req, res) => {
const packageName = req.body.package || "@warehouse/scanner-bridge";
const command = `npm install ${packageName} --prefix ${pluginRoot}`;Interpretation boundary
Inspect divergence before classifying it
Unmatched reports may be false-positive-shaped, adjacent to the release reference scope, or likely valid product-gap candidates. Missed reference findings may expose representative-versus-systematic coverage behavior.
Return to explorer evidence