-
Notifications
You must be signed in to change notification settings - Fork 125
Description
Summary
Extend Test-DependencyPinning.ps1 with a new workflow-npm-commands dependency type that scans GitHub Actions workflow run: steps for unpinned npm commands.
Problem
OpenSSF Scorecard's Pinned-Dependencies check flags npm install commands in workflow run: steps that don't use npm ci or git-URL-with-SHA syntax. The local security scanner (scripts/security/Test-DependencyPinning.ps1) has no equivalent check — its existing npm type only validates package.json dependency sections. Workflow run: step npm commands like npm install -g <package> bypass the lockfile entirely and are invisible to current scanning.
The four Scorecard alerts in #457 originated from workflow run: steps, not from package.json. Without this scanner type, similar regressions can reach main undetected.
Scorecard Context
The Scorecard check (isNpmUnpinnedDownload() in shell_download_validate.go) is syntactic:
npm ci→ pinned (reads integrity hashes frompackage-lock.json)npm installwith git URL + 40-char SHA → pinned- Everything else → unpinned (including
@versiontags)
Implementation
1. Add dependency type to $DependencyPatterns
In scripts/security/Test-DependencyPinning.ps1, add a new entry to the $DependencyPatterns hashtable:
'workflow-npm-commands' = @{
FilePatterns = @('**/.github/workflows/*.yml', '**/.github/workflows/*.yaml')
ValidationFunc = 'Get-WorkflowNpmCommandViolations'
Description = 'npm commands in workflow run steps must use npm ci or npx'
}2. Implement Get-WorkflowNpmCommandViolations
Create a validation function that:
- Parses each workflow YAML file
- Extracts all
run:block content from job steps - Matches lines containing
npm install,npm i,npm update, ornpm install-test(including-g/--globalvariants) - Flags any match that is not
npm ci - Allows
npxcommands (these use the localnode_modulesresolved bynpm ci) - Returns
[DependencyViolation]objects with file path, line number, and violation description
3. Follow existing scanner patterns
Reference the existing validation functions in Test-DependencyPinning.ps1 for the return type, error handling, and output format conventions.
Acceptance Criteria
-
workflow-npm-commandstype added to$DependencyPatternshashtable -
Get-WorkflowNpmCommandViolationsfunction implemented - Function detects
npm install/npm i/npm update/npm install-testcommands in workflowrun:steps -
npm cicommands are NOT flagged as violations -
npxcommands are NOT flagged as violations - Function returns proper
[DependencyViolation]objects matching existing scanner output format - Existing tests pass (
npm run test:ps)
Verification
- Run the scanner with the new type:
./scripts/security/Test-DependencyPinning.ps1 -IncludeTypes 'workflow-npm-commands'
- After fix(build): resolve Pinned-Dependencies alerts for vsce npm commands in extension workflows #457 remediation lands, this should report 0 violations
- Temporarily add
npm install -g some-packageto a workflow file — should report 1 violation (then revert) - Run existing tests:
npm run test:ps
Dependencies
- Prerequisite: fix(build): resolve Pinned-Dependencies alerts for vsce npm commands in extension workflows #457 must merge first (eliminates existing violations before enforcement activates)
How to Build This
This is a PowerShell feature implementation task using the task-implementor workflow.
Workflow: /task-research → /task-plan → /task-implement → /task-review
Tip
Between each phase, type /clear or start a new chat to reset context.
Phase 1: Research
Source Material
- This issue body
#file:scripts/security/Test-DependencyPinning.ps1(script to extend)#file:scripts/security/Test-ActionVersionPinning.ps1(scanning pattern reference)#file:.github/workflows/main.yml(example workflow with run steps)#file:.github/workflows/pr-validation.yml(example workflow with npm/pip commands)#file:PSScriptAnalyzer.psd1(linting rules)
Steps
- Type
/clearto start a fresh context. - Attach or open the files listed above.
- Copy and run this prompt:
/task-research topic="npm command scanning in GitHub Actions workflow run steps"
Research how to extend Test-DependencyPinning.ps1 to scan workflow YAML `run:` steps
for unpinned npm commands. Investigate:
1. How Test-DependencyPinning.ps1 currently parses workflow YAML files (regex patterns,
AST parsing, or line-by-line analysis)
2. The different forms of npm install commands in workflow run steps (npm install -g,
npm ci, npx, pip install, pip3 install)
3. What constitutes a "pinned" vs "unpinned" command in a run step context
4. How SARIF findings should be structured for run-step violations (file path, line number,
rule ID, message)
5. How existing Pester tests are structured for the security scripts
6. Edge cases: multi-line run blocks, shell selection (bash vs pwsh), conditional steps
Output: Research document at .copilot-tracking/research/{{YYYY-MM-DD}}-npm-command-scanning-research.md
Phase 2: Plan
Source Material
- Research document from Phase 1
Steps
- Type
/clearto start a fresh context. - Open the research document from Phase 1.
- Copy and run this prompt:
/task-plan
Create an implementation plan for adding npm/pip command scanning to
Test-DependencyPinning.ps1. The plan should cover new functions or code blocks,
SARIF finding format, Pester test cases, and integration with the existing
script structure.
Output: Plan at .copilot-tracking/plans/ and details at .copilot-tracking/details/
Phase 3: Implement
Source Material
- Plan from Phase 2
Steps
- Type
/clearto start a fresh context. - Open the plan document from Phase 2.
- Copy and run this prompt:
/task-implement
Implement the npm command scanning feature in Test-DependencyPinning.ps1 following
the plan. Extend the existing script to detect unpinned npm, pip, and package manager
commands in workflow run steps and report them as SARIF findings.
Output: Modified script and test files, changes log at .copilot-tracking/changes/
Phase 4: Review
Source Material
- Plan from Phase 2
- Changes log from Phase 3
Steps
- Type
/clearto start a fresh context. - Open the plan and changes log.
- Copy and run this prompt:
/task-review
Review the npm command scanning implementation. Run these validation commands:
- npm run lint:ps (PSScriptAnalyzer validation)
- npm run test:ps (Pester tests including new test cases)
Verify that scanning correctly identifies unpinned commands across all 25 workflow files
and that SARIF output format matches existing findings.
Output: Review log at .copilot-tracking/reviews/
After Review
- Pass: All criteria met. Create a PR referencing this issue.
- Iterate: Review found issues. Run
/clear, return to Phase 3 with the review feedback. - Escalate: Fundamental design issue discovered. Run
/clear, return to Phase 1 to research the gap.
Authoring Standards
- PowerShell scripts follow PSScriptAnalyzer rules from
PSScriptAnalyzer.psd1 - Include comment-based help for new functions
- Pester tests follow existing patterns in
scripts/tests/ - SARIF output matches the schema used by existing findings in the script
Success Criteria
-
run:steps in workflow files are scanned for unpinned package manager commands - SARIF findings include file path, line number, rule ID, and descriptive message
- Pester tests cover npm install, pip install, and edge cases
-
npm run lint:pspasses -
npm run test:pspasses - No false positives on
npm ci(lockfile-backed) commands