Skip to content

fix: single-quote-escape remote paths in files.mjs shell commands - #17

Merged
Shinrai merged 2 commits into
nextfrom
fix/quote-remote-paths
Sep 3, 2026
Merged

Shinrai merged 2 commits into
nextfrom
fix/quote-remote-paths

Conversation

@cldmv-bot

@cldmv-bot cldmv-bot Bot commented Sep 2, 2026 •

Copy link
Copy Markdown
Contributor

🚀 What's Changed

💥 Breaking Changes

No breaking changes

✨ Features

No new features

🐛 Bug Fixes

📦 Dependencies

No dependency updates

🔧 Other Changes

No other changes

👥 Contributors

files.mjs's shell-based file operations (listShell, stat, mkdir, remove,
move, copy, chmod, diskUsage, find) interpolated caller-supplied paths
into double-quoted shell commands with no escaping, letting $, backticks,
or an embedded double-quote break out of the command. Adds
utils.quoteShellArg() (the standard POSIX '\'' single-quote technique)
and applies it at all nine call sites.

Closes #13.
@cldmv-bot cldmv-bot Bot added area: core Touches core library / runtime source code area: tests Touches test files, fixtures, or test infrastructure labels Sep 2, 2026
@Shinrai
Shinrai requested a lite review from Copilot September 2, 2026 23:54

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Several non-path parameters (e.g., mode, maxDepth, type) are still interpolated into shell commands without validation/coercion, leaving command-injection risk despite the improved path quoting.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR hardens the file-operations API’s shell-command construction by switching remote path/pattern interpolation in src/api/files.mjs from double-quoted strings to single-quoted, safely-escaped shell arguments, reducing the risk of shell metacharacter injection when interacting with devices via ADB.

Changes:

  • Added quoteShellArg() utility for POSIX-safe single-quote argument quoting.
  • Updated files.mjs shell commands (e.g., mkdir, rm, mv, find, stat, ls) to use quoteShellArg() for remote paths/patterns.
  • Expanded Vitest coverage to assert correct quoting behavior, including embedded single quotes and metacharacters.
File summaries
File Description
tests/utils.test.vitest.mjs Adds unit tests for the new quoteShellArg() helper.
tests/files.test.vitest.mjs Updates expectations to single-quoted commands and adds injection-oriented test cases.
src/api/utils.mjs Introduces quoteShellArg() for safe shell argument quoting.
src/api/files.mjs Migrates shell command construction to use quoteShellArg() for remote paths/patterns.
Review details

Suppressed comments (1)

src/api/files.mjs:472

  • chmod interpolates mode directly into a shell command via mode.toString(8) with no validation/coercion. If a caller passes a non-number value, this can lead to unexpected output or shell injection. Coerce mode to a number and validate it is an integer in a safe range before building the command.
export async function chmod(socket, streamManager, remotePath, mode, recursive = false) {
	const flag = recursive ? "-R" : "";
	const command = `chmod ${flag} ${mode.toString(8)} ${quoteShellArg(remotePath)}`;
	return await self.shell.execute(socket, streamManager, command);
}
  • Files reviewed: 4/4 changed files
  • Comments generated: 3
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/api/files.mjs
Comment thread src/api/files.mjs
Comment thread src/api/utils.mjs Outdated
Copilot review on PR #17 flagged that mkdir/chmod's mode and find's
maxDepth/type were still interpolated into shell commands unvalidated -
mode.toString(8) silently skips the octal conversion for a non-number,
letting unvalidated input reach the shell. Adds assertValidMode() and
inline validation for maxDepth/type, rejecting anything outside a safe
range/whitelist instead of interpolating it. Also fixes maxDepth's
truthy check, which dropped a valid maxDepth: 0, and corrects
quoteShellArg's JSDoc type to match its actual String() coercion.
@Shinrai

Shinrai commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Re: the suppressed finding on chmod's mode.toString(8) (review #5096427090) — addressed in c2efece together with the same issue on mkdir, via the new assertValidMode() helper (see the reply on the mkdir thread).

Resolves #13 — closed when this ships to the default branch.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The changes consistently apply safe quoting and input validation across all shell-interpolated arguments in files.mjs, and the added tests cover both security-sensitive edge cases and validation failures.

Review details
  • Files reviewed: 4/4 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

@Shinrai
Shinrai merged commit 9d13de7 into next Sep 3, 2026
25 checks passed
@cldmv-bot
cldmv-bot Bot deleted the fix/quote-remote-paths branch September 3, 2026 01:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: core Touches core library / runtime source code area: tests Touches test files, fixtures, or test infrastructure

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants