* Fix: use argv exec and single-quote escaping for the four #476 shell-injection sites
JSON.stringify and raw double-quote interpolation were used as shell quoting,
but /bin/sh still expands $(...), backticks, and ${} inside double quotes.
- is-generated.mjs / live.mjs runScript: switch execSync string commands to
execFileSync argv form, which never invokes a shell. Closes the remote path
where a source file named `$(...)` executes during the live-mode walk.
- skills.mjs hook command + hook-lib.mjs ignore-value suggestion: values that
must stay shell strings now use POSIX single-quote escaping instead of
JSON/double quotes. The doctor's hook-token parser learns the single-quoted
absolute form so it keeps verifying user-level installs.
Adds regression tests for the single-quoted absolute hook form and the
single-quoted ignore-value suggestion. Verified end to end in a browser through
a real live-mode wrap walk against a hostile-named source file.
Prepared with AI assistance (Cursor) under maintainer instruction.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Test: lock in POSIX single-quoting for a $(...) absolute install path (#476)
Follow-up from security review: prove an install path embedding $(...) is
single-quoted in the written hook manifest, not double-quoted.
Prepared with AI assistance (Cursor) under maintainer instruction.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Fix: quote ignore-command args per platform so Windows cmd.exe keeps spaces (#533)
Greptile flagged that switching quoteCommandArg to POSIX single quotes fixed
$(...) injection on /bin/sh but regressed Windows cmd.exe, where single quotes
are literal, so a --file path containing spaces was split and the ignore scope
was stored malformed.
The suggested command runs on the same machine the hook fired on, so branch on
process.platform (the pattern skills.mjs already uses): single-quote on POSIX
for the #476 fix, and keep the original double-quote escaping on Windows so
that path's behavior is unchanged. Adds a regression test asserting both forms.
Prepared with AI assistance (Cursor) under maintainer instruction.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Test: prove the POSIX hook guard is inert under /bin/sh and Windows keeps double quotes (#533)
Greptile's probe could not reach the generated manifest, leaving the hook
command contract unverified. Convert that into committed proof:
- POSIX: install with a $(touch pwned) absolute path, then actually execute the
generated guard under /bin/sh from a clean cwd and assert no marker file
appears and the guard exits 0 (single-quoted substitution stays inert).
- Windows: drive copyProviderHooks as win32 in-process and assert the command
keeps the double-quoted absolute path (usable when the install path has
spaces; $(...) is inert on cmd.exe anyway).
Test-only; source quoting is unchanged.
Prepared with AI assistance (Cursor) under maintainer instruction.
Co-authored-by: Cursor <cursoragent@cursor.com>
---------
Co-authored-by: Cursor <cursoragent@cursor.com>