Skip to content

fix: harden shell escaping, predicate interpolation, and version codegen against injection#289

Open
sebastiondev wants to merge 1 commit intogetsentry:mainfrom
sebastiondev:security/fix-shell-injection
Open

fix: harden shell escaping, predicate interpolation, and version codegen against injection#289
sebastiondev wants to merge 1 commit intogetsentry:mainfrom
sebastiondev:security/fix-shell-injection

Conversation

@sebastiondev
Copy link

Summary

This PR addresses three injection vectors found during a security review of command execution and string interpolation patterns.

1. Command injection via double-quote shell escaping (CWE-78, Medium)

File: src/utils/command.ts

When useShell=true, arguments were escaped by wrapping in double quotes with only " and \ escaped. This is insufficient because $(), backticks, and other shell expansions are still interpreted inside double quotes in /bin/sh -c.

For example, an argument like com.example$(id)app would pass the regex check, get wrapped as "com.example$(id)app", and the $(id) subshell would execute.

Fix: Replace the hand-rolled double-quote regex escaping with the projects own shellEscapeArg() from shell-escape.ts, which uses POSIX single-quote wrapping (' technique). Single-quoted strings in POSIX shell have no interpolation — this is the standard safe approach.

Callers affected: platform-detection.ts and axe-helpers.ts pass useShell=true with potentially user-influenced arguments (scheme names, project paths from MCP tool calls).

2. Predicate injection via unsanitized bundleId (CWE-78, Low-Medium)

File: src/utils/log_capture.ts

The bundleId parameter was interpolated directly into an NSPredicate string (subsystem == "${bundleId}"). A bundleId containing " could break out of the predicate string context. While the predicate is passed as an argument to spawn() (not through shell), the log commands predicate parser interprets the string, so malformed predicates could alter filtering behavior or cause errors.

Fix: Add escapePredicateString() that backslash-escapes \ and " before interpolation. Applied to all predicate construction paths including custom subsystem arrays.

3. Code injection via version string interpolation (CWE-94, Low)

File: scripts/generate-version.ts

Version fields from package.json were interpolated directly into generated TypeScript source using template literals (export const version = '${pkg.version}';). A tampered package.json (e.g., supply chain attack) could inject arbitrary code.

Fix: Use JSON.stringify() for safe string literal embedding, and validate all version fields against a version pattern before interpolation.

Testing

  • All 122 passing test suites continue to pass (11 pre-existing failures are unrelated — missing src/version.ts build artifact)
  • Pre-commit hooks pass (prettier, eslint, build)
  • Specifically verified: log_capture.test.ts, platform-detection.test.ts, launch_app_sim.test.ts, launch_app_logs_sim.test.ts, and all logging/macOS tool tests

… and sanitize predicate/version inputs

- command.ts: Replace hand-rolled double-quote regex escaping with the
  existing shellEscapeArg() helper that uses POSIX single-quote wrapping.
  The previous regex missed $(), backticks, and newlines inside double
  quotes, allowing command injection when useShell=true.

- log_capture.ts: Add escapePredicateString() to sanitize bundleId and
  custom subsystem values before interpolating them into NSPredicate
  strings, preventing predicate injection via crafted double-quotes or
  backslashes.

- generate-version.ts: Validate version fields against a version pattern
  and use JSON.stringify() instead of raw string interpolation to prevent
  code injection via a compromised package.json.
Copy link
Contributor

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

macOSTemplateVersion: string;
}

const VERSION_REGEX = /^v?[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?(\+[a-zA-Z0-9.]+)?$/;
Copy link
Contributor

Choose a reason for hiding this comment

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

Version regex rejects valid semver pre-release hyphens

Medium Severity

VERSION_REGEX uses [a-zA-Z0-9.] for pre-release and build-metadata character classes, which doesn't include -. The semver spec explicitly allows hyphens in these identifiers (e.g., 2.4.0-beta-1, 1.0.0-rc-1, 1.0.0+build-42). The validateVersion function will throw on valid semver versions containing hyphens in pre-release or build metadata, blocking releases that use common naming conventions like beta-1 or rc-2.

Fix in Cursor Fix in Web

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant