Skip to content

fix(win): harden artifact.c git shell-outs against unquoted/unvalidated repo paths#886

Merged
DeusData merged 1 commit into
DeusData:mainfrom
Flipper1994:fix/artifact-git-shell-quoting
Jul 5, 2026
Merged

fix(win): harden artifact.c git shell-outs against unquoted/unvalidated repo paths#886
DeusData merged 1 commit into
DeusData:mainfrom
Flipper1994:fix/artifact-git-shell-quoting

Conversation

@Flipper1994

Copy link
Copy Markdown
Contributor

Summary

Follow-up to #881 (split out per review). Hardens the git shell-outs in pipeline/artifact.c — a different bug class from #881's CreateProcess argv-quoting: this is popen/shell command-string quoting.

The bug

artifact.c shells out to git twice via cbm_popen, interpolating the repo path with single quotes and no validation:

git -C '%s' rev-parse HEAD 2>/dev/null                 // git_head_hash
git -C '%s' config merge.ours.driver true 2>/dev/null  // ensure_gitattributes
  • cmd.exe does not honor single quotes, so on Windows a repo path containing a space breaks argument grouping — the artifact commit hash and merge-driver config silently fail for any spaced repo path.
  • An embedded quote or shell metacharacter in repo_path could break out of the intended argument.

This was the only unvalidated git shell interpolation left in the tree (every other git shell-out — git_context.c, pass_githistory.c, watcher.c, mcp.c — already validates and double-quotes).

Fix

  • Validate repo_path with cbm_artifact_repo_path_is_shell_safe() and switch to double quotes + a per-platform null device, matching git_context.c (the best-hardened git shell-out).
  • cbm_validate_shell_arg rejects quote / backslash / substitution metacharacters; on Windows we additionally reject the cmd.exe expansion metacharacters % ! ^.
  • Double quotes are honored by both POSIX sh and cmd.exe, so a legitimate spaced repo path now works — the concrete regression the single-quote form caused.

Test

New guard suite in tests/test_artifact.c for the exposed cbm_artifact_repo_path_is_shell_safe():

  • plain and spaced paths accepted (the regression),
  • quote / ; / $() / backtick / pipe injection rejected,
  • cmd.exe metacharacters % ! ^ rejected on Windows (allowed on POSIX, where they are literal inside double quotes).

Scope

Atomic to the artifact.c shell-quoting hardening. No behavior change on valid paths except that spaced paths now work on Windows.

Refs #881.

…ed repo paths

artifact.c shells out to git twice via cbm_popen with the repo path interpolated
straight into the command:

    git -C '%s' rev-parse HEAD 2>/dev/null                  (git_head_hash)
    git -C '%s' config merge.ours.driver true 2>/dev/null   (ensure_gitattributes)

Both used SINGLE quotes with NO validation of repo_path. cmd.exe does not honor
single quotes, so on Windows a repo path containing a space broke argument grouping
(the artifact commit hash and merge-driver config silently failed for any spaced repo
path), and an embedded quote or shell metacharacter could break out of the intended
argument. This was the only unvalidated git shell interpolation left in the tree.

Different bug class from the CreateProcess argv-quoting fix (which re-parses a single
command STRING back into argv); this is popen/shell command-string quoting — hence a
separate, atomic PR per review.

Fix: validate repo_path with cbm_artifact_repo_path_is_shell_safe() and switch to
double quotes + a per-platform null device, matching git_context.c (the best-hardened
git shell-out): cbm_validate_shell_arg rejects quote / backslash / substitution
metacharacters, and on Windows we also reject the cmd.exe expansion metacharacters
% ! ^. Double quotes are honored by both POSIX sh and cmd.exe, so a legitimate spaced
repo path now works — the concrete regression the single-quote form caused.

The validator is exposed (artifact.h) and guarded by a new test_artifact.c suite:
plain + spaced paths accepted; quote / ; / $() / backtick / pipe injection rejected;
the cmd.exe metacharacters % ! ^ rejected on Windows (allowed on POSIX, where they are
literal inside double quotes).

Refs: DeusData#881
Signed-off-by: Flipper <jacobphilipp@ymail.com>
@Flipper1994 Flipper1994 force-pushed the fix/artifact-git-shell-quoting branch from 6aabf39 to b0e71f0 Compare July 5, 2026 13:16
@DeusData DeusData marked this pull request as ready for review July 5, 2026 14:37
@DeusData DeusData self-requested a review as a code owner July 5, 2026 14:37
@DeusData DeusData merged commit 582c124 into DeusData:main Jul 5, 2026
15 checks passed
@DeusData

DeusData commented Jul 5, 2026

Copy link
Copy Markdown
Owner

Merged — thank you, @Flipper1994! 🙏 This is a clean, well-targeted hardening: gating both git shell-outs on cbm_artifact_repo_path_is_shell_safe, switching single→double quotes (the real cross-platform fix), the null-device redirect, and the snprintf truncation guards for parity with git_context.c. The unit tests across plain / spaced / Windows paths and the injection cases are exactly what we want to see on a shell-out path. Really appreciate the careful work here — and on the CreateProcess argv-quoting fix too.

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.

2 participants