Skip to content

Add regression coverage for command argument injection safeguards - #53359

Merged
pelikhan merged 2 commits into
mainfrom
copilot/sighthound-security-findings-again
Aug 17, 2026
Merged

Add regression coverage for command argument injection safeguards#53359
pelikhan merged 2 commits into
mainfrom
copilot/sighthound-security-findings-again

Conversation

CopilotAI commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Sighthound flagged five dynamic exec.Command call sites as potential command injection risks. Existing validation and direct process invocation already prevent shell interpretation.

  • PyPI package validation
    • Cover shell separators, command substitution, newlines, and empty names.
  • Upgrade re-execution
    • Verify shell metacharacters are forwarded as literal arguments.
  • Triage
    • Confirm npm, Docker/Grype, and upgrade commands use validated executables and shell-free argument passing.

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
CopilotAI changed the title [WIP] Fix command injection vulnerabilities in pip validationAdd regression coverage for command argument injection safeguardsAug 17, 2026
CopilotAI requested a review from pelikhanAugust 17, 2026 12:05
@pelikhan
pelikhan marked this pull request as ready for review August 17, 2026 12:15
CopilotAI balanced review requested due to automatic review settings August 17, 2026 12:15

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds regression tests for command argument-injection safeguards.

Changes:

  • Covers malicious and empty PyPI package names.
  • Verifies upgrade arguments remain literal during re-execution.
Show a summary per file
FileDescription
pkg/workflow/argument_injection_test.goExpands PyPI validation cases.
pkg/cli/upgrade_command_test.goTests literal shell metacharacter forwarding.

Review details

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

  • Files reviewed: 2/2 changed files
  • Comments generated: 1
  • Review effort level: Balanced

})
os.Stdout = writeOutput

require.NoError(t, relaunchWithSameArgs("--skip-extension-upgrade", "/bin/echo"))
@github-actions

github-actionsBot commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Ponytail Reviewer completed successfully!

Lean already. Ship. PR adds only additional table-driven test cases and one focused regression test; no new abstractions, wrappers, or speculative complexity introduced.

Generated by Ponytail Reviewer for #53359

@github-actions

github-actionsBot commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Design Decision Gate 🏗️ completed the design decision gate check.

No ADR enforcement needed: PR #53359 does not have the 'implementation' label and has only 49 new lines of code in business logic directories (threshold: 100).

🏗️ ADR gate enforced by Design Decision Gate 🏗️

@github-actions

github-actionsBot commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

🧠 Matt Pocock Skills Reviewer has completed the skills-based review. ✅

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer

@github-actions

github-actionsBot commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Test Quality Sentinel completed test quality analysis.

Test Quality Sentinel skipped because pre-fetch PR data was unavailable: unable to fetch test file diff

🧪 Test quality analysis by Test Quality Sentinel

@github-actions

github-actionsBot commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

PR Code Quality Reviewer completed the code quality review.

Completed PR review analysis; no GitHub write issued because no new actionable review comments beyond the existing Windows portability finding were warranted.

🔎 Code quality review by PR Code Quality Reviewer

@github-actions

Copy link
Copy Markdown
Contributor

Comment Memory

reviewed_at: 2026-08-17T12:29:00Z
review_event: COMMENT
top_themes:
- existing Windows portability issue already covers the only actionable risk
- new tests otherwise match current shell-free argument handling and validation behavior
files_reviewed:
- pkg/cli/upgrade_command_test.go
- pkg/workflow/argument_injection_test.go
comment_count: 0

Note

This comment is managed by comment memory.

It stores persistent context for this thread in the code block at the top of this comment.
Edit only the text inside the backtick fences; workflow metadata and the footer are regenerated automatically.

Learn more about comment memory

🔎 Code quality review by PR Code Quality Reviewer · gpt54 · 4.25 AIC · ⌖ 5.39 AIC · ⊞ 6.9K ·
Comment /review to run again

@github-actionsgithub-actionsBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The new regression tests are well-structured and cover the right attack vectors. The existing inline comment (#3796290329) already flags the Windows portability issue with /bin/echo. No additional blocking issues found.

🧵 Reviewed using Impeccable skills by Impeccable Skills Reviewer · sonnet46 · 24.3 AIC · ⌖ 7.89 AIC · ⊞ 5.6K

@github-actionsgithub-actionsBot mentioned this pull request Aug 17, 2026

@github-actionsgithub-actionsBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Skills-Based Review 🧠

Applied /tdd and /diagnosing-bugs — one minor improvement requested, otherwise the coverage is solid.

📋 Key Themes & Highlights

Key Themes

  • Test specificity: The four new PyPI injection cases omit errContains, meaning any error message passes. Pinning the message turns the test into a real specification and protects against silent guard-deletion during refactors.
  • Windows portability: The TestRelaunchWithSameArgsPassesShellMetacharactersLiterally test uses /bin/echo, which is not valid on Windows (flagged separately as an existing inline comment).

Positive Highlights

  • ✅ Good coverage of distinct injection vectors: shell separator, command substitution, newline option injection, and empty name.
  • ✅ Clean pipe-capture pattern in the upgrade test to verify literal argument forwarding — no mocking needed.
  • ✅ PR description clearly maps each test to the Sighthound finding it addresses.

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · sonnet46 · 26.9 AIC · ⌖ 8.63 AIC · ⊞ 7.7K
Comment /matt to run again

{
name: "shell separator is rejected",
pkg: "pkg;whoami",
expectError: true,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

[/tdd] The new injection test cases omit errContains, so any error message satisfies the check — the test does not verify the rejection reason.

💡 Suggestion

Adding errContains for each case pins the behaviour and turns the test into a specification:

{
name: "shell separator is rejected",
pkg: "pkg;whoami",
expectError: true,
errContains: "PyPI names must start and end",
},

The same pattern applies to the command substitution, newline option injection, and empty name cases. Without it, a silent refactor that changes the rejection path leaves these cases green while the intended guard disappears.

@copilot please address this.

@github-actions

Copy link
Copy Markdown
Contributor

Test Quality Sentinel Report 🧪

Overview

This PR adds 2 new test cases covering command argument injection safeguards:

  1. Shell metacharacter forwarding in upgrade_command_test.go (1 new test, 29 lines)
  2. PyPI package validation edge cases in argument_injection_test.go (4 new table-driven test rows, 20 lines)

Total changes: 49 lines added. No production code modified — pure regression coverage for existing validation logic.


Test Analysis

1. TestRelaunchWithSameArgsPassesShellMetacharactersLiterally

File:pkg/cli/upgrade_command_test.go

What it tests: Verifies that shell metacharacters (;, $()) in command-line arguments are passed as literal strings to the relaunched process, not interpreted by a shell.

Quality assessment:

  • Behavioral contract: Tests core security guarantee of relaunch mechanism
  • Observable verification: Captures stdout and verifies exact argument forwarding ("upgrade ; $(whoami) --skip-extension-upgrade\n")
  • Edge cases: Uses shell metacharacters known to be dangerous
  • Clean setup/teardown: Proper os.Args and os.Stdout restoration via t.Cleanup
  • No mocks: Uses only standard library (os.Pipe, io.ReadAll)

Classification:behavioral_contract / high_value / design_test

2. TestValidatePipPackageName – New Table Rows

File:pkg/workflow/argument_injection_test.go

What was added: 4 new rows to the existing table-driven test:

  1. "shell separator is rejected""pkg;whoami" must error
  2. "command substitution is rejected""pkg$(whoami)" must error
  3. "newline option injection is rejected""pkg\n--index-url" must error
  4. "empty name is rejected""" must error

Quality assessment:

  • Behavioral contract: Each row exercises a distinct attack vector
  • Edge cases: Covers shell separators, substitution, newlines, empty input
  • Regex coverage: Tests that pypiPackageNameRE rejects all variants
  • Table-driven pattern: Reuses existing test infrastructure
  • No mocks: Pure validation logic test

Classification per row:behavioral_contract / high_value / design_test (×4)


Quality Metrics

MetricResult
Design Tests5 / 5 (100%) ✅
Edge Case Coverage5 / 5 (100%) ✅
Go Mock LibrariesNone ✅
Build TagsAll present ✅
Test Inflation RatioN/A (no prod changes) ✅

Test Quality Score

Score: 100 / 100 ✅ Excellent

Score = ((5 / 5 design_tests) × 40) +
((5 / 5 edge_cases) × 30) +
(20 - 0 duplicates) +
(10 - 0 inflation)
= 40 + 30 + 20 + 10 = 100 / 100

Key Findings

Strengths:

  • 🎯 Directly addresses the Sighthound findings for five dynamic exec.Command call sites
  • 🔒 All test scenarios target known injection attack vectors
  • 📦 Zero production changes = minimal regression risk
  • 🧩 Clean implementation without mocks or hidden complexity

No violations detected:

  • No Go mock libraries (gomock, testify/mock)
  • No forbidden JavaScript mocks
  • All build tags present
  • Strong assertions with error verification

Coverage: Comprehensive regression coverage of:

  • PyPI validation with shell metacharacters, command substitution, newlines, empty input
  • Upgrade relaunch argument forwarding via observable output

Recommendation: ✅ APPROVE — Test Quality Score meets excellent threshold. All behavioral contracts are properly tested with comprehensive edge-case coverage and zero violations.

🧪 Test quality analysis by Test Quality Sentinel · haiku45 · 23.2 AIC · ⌖ 4.51 AIC · ⊞ 7.9K ·
Comment /review to run again

@github-actionsgithub-actionsBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

✅ Test Quality Sentinel: 100/100 — Excellent

All 5 new test scenarios are behavioral contracts with comprehensive edge-case coverage:

  • 100% design tests (shell safety, injection prevention)
  • 100% edge case coverage (metacharacters, substitution, newlines, empty input)
  • Zero violations (no forbidden mocks, build tags present)
  • 0% implementation tests (all tests verify user-visible security behavior)

Recommendation: This PR is approved. Test quality exceeds all thresholds.

@pelikhan
pelikhan merged commit 5b5bb8b into mainAug 17, 2026
101 checks passed
@pelikhan
pelikhan deleted the copilot/sighthound-security-findings-again branch August 17, 2026 12:35
@github-actions

Copy link
Copy Markdown
Contributor

🎉 This pull request is included in a new release.

Release: v0.87.1

Sign up for freeto 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.

[sighthound] Security findings in github/gh-aw

3 participants

@pelikhan