Considering to use so did review using https://gist.github.com/2a491f29bf662d3e04fe1713b1757729.git and some concerns look legit, e.g. it is a constant battle against hardcoded /tmp paths in debian packages ;)
Vibecoder Security Review: DRYwall
Date: 2026-04-07
Summary
Found 1 medium-priority issue and 4 low-priority/informational issues in this Node.js MCP server plugin. The codebase is small (~230 lines of source), has no web-facing attack surface (no auth, no HTTP server, no user data), and uses execFile correctly to avoid shell injection. Overall security posture is reasonable for a CLI tool.
Findings
[MEDIUM] Arbitrary npm Package Execution via jscpdVersion Config
Location: src/lib.js:60-61
Issue: The jscpdVersion value from .drywallrc.json is interpolated into the npx package specifier without validation:
const fullArgs = [`jscpd@${version}`, ...args];
execFile("npx", fullArgs, ...);
A malicious .drywallrc.json could set jscpdVersion to a completely different package name (e.g., "jscpdVersion": "../../malicious-pkg"), though execFile mitigates the shell injection vector. The realistic risk is low since the attacker would need write access to the project's config file, but it violates the principle of validating external input before passing it to process execution.
Impact: If an attacker controls .drywallrc.json (e.g., via a malicious PR or compromised dependency that writes config), they could cause npx to execute an arbitrary npm package.
Suggested fix: Validate that jscpdVersion matches a semver pattern:
const VERSION_RE = /^\d+\.\d+\.\d+(-[\w.]+)?$/;
if (version && !VERSION_RE.test(version)) {
throw new Error(`Invalid jscpdVersion: ${version}`);
}
[LOW] Predictable Temp Directory Path
Location: src/lib.js:7
Issue: Report output uses a fixed path /tmp/drywall-report:
export const REPORT_DIR = "/tmp/drywall-report";
Impact: On shared systems, another user could create a symlink at /tmp/drywall-report pointing elsewhere (symlink/TOCTOU attack). Practical risk is low since this is a developer CLI tool typically run on single-user machines, and jscpd writes a JSON file (not executable content).
Suggested fix: Use os.tmpdir() with a unique suffix (e.g., mkdtemp) if multi-user environments are a concern.
[LOW] Unrestricted Path Scanning
Location: src/jscpd.js:70
Issue: The path parameter from MCP tool input is passed directly to jscpd without path validation:
const targetPath = scanPath || config.path || ".";
args.push(targetPath);
Impact: An MCP client could request scanning of any directory readable by the process (e.g., /etc, ~/.ssh). The scan only detects duplication (no file contents are exfiltrated in full), but code fragments are returned in the response. This is by-design for an MCP tool (the LLM host already has file access), so this is informational.
[LOW] 4 High-Severity npm Audit Vulnerabilities (Transitive)
Issue: npm audit reports 4 high-severity vulnerabilities in transitive dependencies:
hono <=4.12.6 -- cookie injection, SSE injection, file access, prototype pollution
@hono/node-server <1.19.10 -- auth bypass in static paths
express-rate-limit 8.2.0-8.2.1 -- IPv4-mapped IPv6 bypass
path-to-regexp 8.0.0-8.3.0 -- ReDoS
Impact: These are transitive deps pulled by @modelcontextprotocol/sdk. DRYwall doesn't use Hono/Express directly -- it only uses the MCP SDK's stdio transport, so these vulnerabilities are not exploitable in this context. The server has no HTTP listener.
Suggested fix: npm audit fix to update, or document as accepted risk.
[INFO] Minimal .gitignore
Location: .gitignore
Issue: Only ignores node_modules/. Missing common patterns like .env, *.log, .DS_Store. Not a real risk since this is a plugin with no secrets, but worth noting for hygiene.
Not Applicable
The following checks found no issues (as expected for a non-web MCP server plugin):
- Secrets & Keys -- No hardcoded credentials, API keys, or tokens found anywhere in source
- Auth & Accounts -- No authentication system (MCP stdio transport, no HTTP)
- User Data & Privacy -- No user data storage or retrieval
- Test vs Production -- No debug backdoors, no test credentials
- File Uploads -- No upload handling
- XSS / SQL Injection -- No HTML rendering, no database
- CORS / Security Headers -- No HTTP server
- Prompt Injection -- No LLM integration in the server itself
Quick Wins
- Validate
jscpdVersion against a semver regex before passing to npx
- Run
npm audit fix to clear transitive vulnerability warnings
Considering to use so did review using https://gist.github.com/2a491f29bf662d3e04fe1713b1757729.git and some concerns look legit, e.g. it is a constant battle against hardcoded /tmp paths in debian packages ;)
Vibecoder Security Review: DRYwall
Date: 2026-04-07
Summary
Found 1 medium-priority issue and 4 low-priority/informational issues in this Node.js MCP server plugin. The codebase is small (~230 lines of source), has no web-facing attack surface (no auth, no HTTP server, no user data), and uses
execFilecorrectly to avoid shell injection. Overall security posture is reasonable for a CLI tool.Findings
[MEDIUM] Arbitrary npm Package Execution via
jscpdVersionConfigLocation:
src/lib.js:60-61Issue: The
jscpdVersionvalue from.drywallrc.jsonis interpolated into the npx package specifier without validation:A malicious
.drywallrc.jsoncould setjscpdVersionto a completely different package name (e.g.,"jscpdVersion": "../../malicious-pkg"), thoughexecFilemitigates the shell injection vector. The realistic risk is low since the attacker would need write access to the project's config file, but it violates the principle of validating external input before passing it to process execution.Impact: If an attacker controls
.drywallrc.json(e.g., via a malicious PR or compromised dependency that writes config), they could causenpxto execute an arbitrary npm package.Suggested fix: Validate that
jscpdVersionmatches a semver pattern:[LOW] Predictable Temp Directory Path
Location:
src/lib.js:7Issue: Report output uses a fixed path
/tmp/drywall-report:Impact: On shared systems, another user could create a symlink at
/tmp/drywall-reportpointing elsewhere (symlink/TOCTOU attack). Practical risk is low since this is a developer CLI tool typically run on single-user machines, and jscpd writes a JSON file (not executable content).Suggested fix: Use
os.tmpdir()with a unique suffix (e.g.,mkdtemp) if multi-user environments are a concern.[LOW] Unrestricted Path Scanning
Location:
src/jscpd.js:70Issue: The
pathparameter from MCP tool input is passed directly to jscpd without path validation:Impact: An MCP client could request scanning of any directory readable by the process (e.g.,
/etc,~/.ssh). The scan only detects duplication (no file contents are exfiltrated in full), but code fragments are returned in the response. This is by-design for an MCP tool (the LLM host already has file access), so this is informational.[LOW] 4 High-Severity npm Audit Vulnerabilities (Transitive)
Issue:
npm auditreports 4 high-severity vulnerabilities in transitive dependencies:hono<=4.12.6 -- cookie injection, SSE injection, file access, prototype pollution@hono/node-server<1.19.10 -- auth bypass in static pathsexpress-rate-limit8.2.0-8.2.1 -- IPv4-mapped IPv6 bypasspath-to-regexp8.0.0-8.3.0 -- ReDoSImpact: These are transitive deps pulled by
@modelcontextprotocol/sdk. DRYwall doesn't use Hono/Express directly -- it only uses the MCP SDK's stdio transport, so these vulnerabilities are not exploitable in this context. The server has no HTTP listener.Suggested fix:
npm audit fixto update, or document as accepted risk.[INFO] Minimal
.gitignoreLocation:
.gitignoreIssue: Only ignores
node_modules/. Missing common patterns like.env,*.log,.DS_Store. Not a real risk since this is a plugin with no secrets, but worth noting for hygiene.Not Applicable
The following checks found no issues (as expected for a non-web MCP server plugin):
Quick Wins
jscpdVersionagainst a semver regex before passing tonpxnpm audit fixto clear transitive vulnerability warnings