Skip to content

fix(scripts): eliminate false positives in dependency pinning npm pattern#273

Merged
WilliamBerryiii merged 4 commits intomainfrom
fix/dependency-pinning-false-positives
Jan 25, 2026
Merged

fix(scripts): eliminate false positives in dependency pinning npm pattern#273
WilliamBerryiii merged 4 commits intomainfrom
fix/dependency-pinning-false-positives

Conversation

@WilliamBerryiii
Copy link
Copy Markdown
Member

Description

Replace regex-based pattern matching with JSON parsing for package.json validation, targeting only actual dependency sections. The previous regex approach incorrectly flagged metadata fields like name, version, description, and repository URLs as unpinned dependencies.

  • Add Get-NpmDependencyViolations function that parses package.json as structured JSON and checks only dependencies, devDependencies, peerDependencies, and optionalDependencies sections
  • Update npm pattern config to use ValidationFunc dispatcher instead of VersionPatterns regex approach
  • Add ValidationFunc dispatch logic to Get-DependencyViolation for type-specific validation functions
  • Update Test-ShellDownloadSecurity to use consistent FileInfo hashtable parameter
  • Create test fixtures for metadata-only and with-dependencies npm scenarios
  • Add Pester tests covering JSON parsing, dependency extraction, and version pattern matching

Related Issue(s)

Fixes #267

Type of Change

Select all that apply:

Code & Documentation:

  • Bug fix (non-breaking change fixing an issue)
  • New feature (non-breaking change adding functionality)
  • Breaking change (fix or feature causing existing functionality to change)
  • Documentation update

Infrastructure & Configuration:

  • GitHub Actions workflow
  • Linting configuration (markdown, PowerShell, etc.)
  • Security configuration
  • DevContainer configuration
  • Dependency update

AI Artifacts:

  • Reviewed contribution with prompt-builder agent and addressed all feedback
  • Copilot instructions (.github/instructions/*.instructions.md)
  • Copilot prompt (.github/prompts/*.prompt.md)
  • Copilot agent (.github/agents/*.agent.md)

Note for AI Artifact Contributors:

  • Agents: Research, indexing/referencing other project (using standard VS Code GitHub Copilot/MCP tools), planning, and general implementation agents likely already exist. Review .github/agents/ before creating new ones.
  • Model Versions: Only contributions targeting the latest Anthropic and OpenAI models will be accepted. Older model versions (e.g., GPT-3.5, Claude 3) will be rejected.
  • See Agents Not Accepted and Model Version Requirements.

Other:

  • Script/automation (.ps1, .sh, .py)
  • Other (please describe):

Sample Prompts (for AI Artifact Contributions)

Testing

  • PSScriptAnalyzer: All files passed with 0 issues
  • Pester: 33 tests passed (including 4 new tests for Get-NpmDependencyViolations)
  • Full dependency scan: 100% compliance, 0 violations

Checklist

Required Checks

  • Documentation is updated (if applicable)
  • Files follow existing naming conventions
  • Changes are backwards compatible (if applicable)
  • Tests added for new functionality (if applicable)

AI Artifact Contributions

Required Automated Checks

The following validation commands must pass before merging:

  • Markdown linting: npm run lint:md
  • Spell checking: npm run spell-check
  • Frontmatter validation: npm run lint:frontmatter
  • Link validation: npm run lint:md-links
  • PowerShell analysis: npm run lint:ps

Security Considerations

  • This PR does not contain any sensitive or NDA information
  • Any new dependencies have been reviewed for security issues
  • Security-related scripts follow the principle of least privilege

Additional Notes

The ValidationFunc dispatcher pattern enables type-specific validation functions without relying on regex patterns. This approach provides better accuracy for structured file formats like JSON and can be extended to other dependency types in the future.

🔧 - Generated by Copilot

…tern

Replace regex-based pattern matching with JSON parsing for package.json
validation, targeting only dependency sections.

- Add Get-NpmDependencyViolations function that parses package.json as
  structured JSON and checks only dependencies, devDependencies,
  peerDependencies, and optionalDependencies sections
- Update npm pattern config to use ValidationFunc dispatcher instead of
  VersionPatterns
- Add ValidationFunc dispatch logic to Get-DependencyViolation for
  type-specific validation functions
- Create test fixtures for metadata-only and with-dependencies npm scenarios
- Add Pester tests covering JSON parsing, dependency extraction, and
  version pattern matching

Resolves false positives from metadata fields like name, version,
description, and repository URLs being flagged as unpinned dependencies.

Fixes #267

🔧 - Generated by Copilot
@WilliamBerryiii WilliamBerryiii requested a review from a team as a code owner January 24, 2026 17:12
Copilot AI review requested due to automatic review settings January 24, 2026 17:12
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Jan 24, 2026

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Scanned Files

None

@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented Jan 24, 2026

Codecov Report

❌ Patch coverage is 74.19355% with 16 lines in your changes missing coverage. Please review.
✅ Project coverage is 29.44%. Comparing base (c52d6e2) to head (5f96c0f).

Files with missing lines Patch % Lines
scripts/security/Test-DependencyPinning.ps1 74.19% 16 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main     #273      +/-   ##
==========================================
+ Coverage   28.78%   29.44%   +0.66%     
==========================================
  Files          14       14              
  Lines        2738     2785      +47     
==========================================
+ Hits          788      820      +32     
- Misses       1950     1965      +15     
Flag Coverage Δ
pester 29.44% <74.19%> (+0.66%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
scripts/security/Test-DependencyPinning.ps1 54.70% <74.19%> (+1.80%) ⬆️

... and 1 file with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes false positives in npm dependency pinning checks by moving from regex matching to structured JSON parsing of package.json, so only actual dependency sections are validated.

Changes:

  • Added Get-NpmDependencyViolations to parse package.json and scan only dependency sections.
  • Introduced ValidationFunc dispatch in Get-DependencyViolation to support type-specific validators.
  • Updated/added Pester tests and npm JSON fixtures, and aligned Test-ShellDownloadSecurity to accept a consistent FileInfo hashtable.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.

File Description
scripts/security/Test-DependencyPinning.ps1 Adds JSON-based npm validation and ValidationFunc dispatch; updates shell download validator signature.
scripts/tests/security/Test-DependencyPinning.Tests.ps1 Updates shell-download tests to pass FileInfo; adds unit tests for npm JSON parsing/validation.
scripts/tests/Fixtures/Npm/metadata-only-package.json Fixture to ensure metadata-only package.json doesn’t produce violations.
scripts/tests/Fixtures/Npm/with-dependencies-package.json Fixture containing multiple dependency sections to validate detection logic.

- add invalid-json-package.json fixture for JSON parse error testing
- add empty-version-package.json fixture for whitespace version testing
- add test contexts for invalid JSON and empty version edge cases

🧪 - Generated by Copilot
- update Get-NpmDependencyViolations to return DependencyViolation objects
- update Test-ShellDownloadSecurity to return DependencyViolation objects
- add dispatcher validation with type checking and field normalization
- fix test path separators to forward slashes for cross-platform compatibility
- update test assertions to use Name and Metadata.Section properties

🔧 - Generated by Copilot
Copilot AI review requested due to automatic review settings January 25, 2026 00:29
@WilliamBerryiii
Copy link
Copy Markdown
Member Author

Not addressing codecov in this PR as there's a separate backlog item for improved testing of the code touched in this PR.

@WilliamBerryiii WilliamBerryiii merged commit ccbdfa3 into main Jan 25, 2026
20 checks passed
@WilliamBerryiii WilliamBerryiii deleted the fix/dependency-pinning-false-positives branch January 25, 2026 00:30
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated 6 comments.

$violation.Line = $i + 1
$violation.Type = $FileInfo.Type
$violation.Name = $line.Trim()
$violation.Severity = 'warning'
Copy link

Copilot AI Jan 25, 2026

Choose a reason for hiding this comment

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

Test-ShellDownloadSecurity sets DependencyViolation.Severity to 'warning', but the rest of the report pipeline (summary counts and SARIF level mapping) only recognizes 'High'|'Medium'|'Low'|'Info'. This will undercount these violations in the summary and downgrade SARIF results to note. Use the existing severity scheme (e.g., Medium/High) for shell-download violations (and adjust tests accordingly).

Suggested change
$violation.Severity = 'warning'
$violation.Severity = 'Medium'

Copilot uses AI. Check for mistakes.
.PARAMETER FileInfo
Hashtable with Path, Type, and RelativePath keys from Get-FilesToScan.
.OUTPUTS
Array of PSCustomObjects representing dependency violations.
Copy link

Copilot AI Jan 25, 2026

Choose a reason for hiding this comment

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

Get-NpmDependencyViolations documents returning PSCustomObjects, but it actually constructs and returns [DependencyViolation] instances. Update the comment-based help .OUTPUTS to match the real return type so callers/tests know what to expect.

Suggested change
Array of PSCustomObjects representing dependency violations.
[DependencyViolation[]] representing dependency violations.

Copilot uses AI. Check for mistakes.
if (-not $isPinned) {
$violation = [DependencyViolation]::new()
$violation.File = $relativePath
$violation.Line = 0
Copy link

Copilot AI Jan 25, 2026

Choose a reason for hiding this comment

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

NPM violations are emitted with Line = 0, which produces invalid/ambiguous locations in outputs (notably SARIF region.startLine, which is expected to be 1-based) and makes reports harder to act on. Compute a real line number for the dependency entry (or at minimum set it to 1) so downstream formats remain valid.

Suggested change
$violation.Line = 0
$violation.Line = 1

Copilot uses AI. Check for mistakes.
$violation.Type = $type
$violation.Name = $packageName
$violation.Version = $version
$violation.Severity = 'warning'
Copy link

Copilot AI Jan 25, 2026

Choose a reason for hiding this comment

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

Get-NpmDependencyViolations sets Severity to 'warning', but the report summary and SARIF export only recognize High/Medium/Low/Info. This will under-report npm violations in summaries and downgrade SARIF results to note. Align npm severity with the existing scheme (e.g., Medium).

Suggested change
$violation.Severity = 'warning'
$violation.Severity = 'Medium'

Copilot uses AI. Check for mistakes.
}

if ($v.Line -lt 1) {
$v.Line = 0
Copy link

Copilot AI Jan 25, 2026

Choose a reason for hiding this comment

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

In the validation-function path, violations with Line < 1 are normalized to 0. That propagates invalid line numbers into SARIF/markdown outputs. Prefer normalizing to 1 (or leave unset and handle formatting elsewhere) so outputs always have valid 1-based line numbers.

Suggested change
$v.Line = 0
$v.Line = 1

Copilot uses AI. Check for mistakes.
}
$result = Test-ShellDownloadSecurity -FileInfo $fileInfo
$result | Should -Not -BeNullOrEmpty
$result[0].Severity | Should -Be 'warning'
Copy link

Copilot AI Jan 25, 2026

Choose a reason for hiding this comment

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

This test asserts Severity equals 'warning', but the report/export pipeline in Test-DependencyPinning.ps1 uses High/Medium/Low/Info for summaries and SARIF levels. If shell-download violations keep 'warning', they’ll be downgraded to SARIF note and won’t be counted in High/Medium/Low summaries. Update the implementation to use the standard severities and update this assertion accordingly.

Suggested change
$result[0].Severity | Should -Be 'warning'
$result[0].Severity | Should -Be 'High'

Copilot uses AI. Check for mistakes.
WilliamBerryiii pushed a commit that referenced this pull request Jan 28, 2026
🤖 I have created a release *beep* *boop*
---


##
[2.0.0](hve-core-v1.1.0...hve-core-v2.0.0)
(2026-01-28)


### ⚠ BREAKING CHANGES

* **agents:** add Task Reviewer and expand RPI to 4-phase workflow
([#277](#277))

### ✨ Features

* **agents:** add hve-core-installer agent to extension package
([#297](#297))
([c0e48c6](c0e48c6))
* **agents:** add Task Reviewer and expand RPI to 4-phase workflow
([#277](#277))
([ae76cab](ae76cab))
* **build:** add code coverage reporting to Pester workflow
([#230](#230))
([a34822a](a34822a))
* **docs:** add GOVERNANCE.md for OSSF Silver Badge compliance
([#235](#235))
([b0e752c](b0e752c))
* **docs:** add ROADMAP.md for OSSF Silver badge compliance
([#238](#238))
([4a41c16](4a41c16))
* **mcp:** add MCP server configuration guidance and installer
enhancements ([#225](#225))
([0bce418](0bce418))
* **scripts:** add YAML linting with actionlint
([#234](#234))
([d9301f9](d9301f9))
* **security:** add OpenSSF Scorecard workflow and badge
([#271](#271))
([7c6d788](7c6d788))
* **skills:** add video-to-gif conversion skill with FFmpeg two-pass
optimization ([#247](#247))
([8d65c42](8d65c42))
* **tests:** add Pester tests for LintingHelpers and
Validate-MarkdownFrontmatter
([#197](#197),
[#198](#198))
([#205](#205))
([51ae563](51ae563))


### 🐛 Bug Fixes

* **build:** detect table formatting changes via git diff
([#261](#261))
([985eee0](985eee0))
* **build:** disable MD024 lint rule in CHANGELOG for release-please
([#220](#220))
([971df94](971df94))
* **build:** quote shell variables and group redirects in workflow files
([#299](#299))
([3372509](3372509))
* **build:** resolve scorecard badge and workflow security issues
([#301](#301))
([aeaed13](aeaed13))
* **extension:** remove frontmatter from README and exclude from
markdown linting
([#223](#223))
([4272529](4272529))
* **instructions:** quote applyTo glob pattern for YAML compatibility
([#216](#216))
([085199c](085199c))
* **scripts:** add FooterExcludePaths parameter to frontmatter
validation ([#334](#334))
([64db98d](64db98d))
* **scripts:** add GHSA word and logs/ exclusion to cspell config
([#214](#214))
([5c99b3f](5c99b3f))
* **scripts:** correct type assertions in Invoke-YamlLint.Tests.ps1
([#332](#332))
([af7050d](af7050d))
* **scripts:** eliminate false positives in dependency pinning npm
pattern ([#273](#273))
([ccbdfa3](ccbdfa3))
* **security:** add artifact attestation for signed releases
([#257](#257))
([c52d6e2](c52d6e2))
* standardize markdown footers and complete frontmatter
([#217](#217))
([b4e7556](b4e7556))


### 📚 Documentation

* add OpenSSF Best Practices Passing badge to README
([#239](#239))
([91bc529](91bc529))
* **architecture:** add architecture documentation and value proposition
([#252](#252))
([0e4b02f](0e4b02f))
* **contributing:** add testing requirements for OSSF compliance
([#254](#254))
([4db1a18](4db1a18))
* **docs:** add enterprise status badges to README header
([#270](#270))
([ccb68a4](ccb68a4))
* **security:** add security assurance case and threat model for OSSF
Silver ([#259](#259))
([a390e26](a390e26))


### ♻️ Refactoring

* **application:** wrap execution with try blocks, ensure proper …
([#296](#296))
([35c4417](35c4417))
* **scripts:** extract frontmatter validation to testable module
([#293](#293))
([4e8707e](4e8707e))
* **scripts:** extract pure functions for Pester testability
([#221](#221))
([d40e742](d40e742))


### 🔧 Maintenance

* **deps-dev:** bump cspell from 9.4.0 to 9.6.0 in the npm-dependencies
group ([#208](#208))
([855914b](855914b))
* **deps-dev:** bump cspell from 9.6.0 to 9.6.1 in the npm-dependencies
group ([#294](#294))
([1e45ad6](1e45ad6))
* **deps:** bump actions/setup-node from 6.1.0 to 6.2.0 in the
github-actions group
([#209](#209))
([c4c69e2](c4c69e2))
* **deps:** bump the github-actions group with 4 updates
([#295](#295))
([d8337b8](d8337b8))
* remove step-security/harden-runner from workflows
([#246](#246))
([c5708d8](c5708d8))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: hve-core-release-please[bot] <254602402+hve-core-release-please[bot]@users.noreply.github.com>
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.

fix(security): dependency-pinning script reports false positives on package.json metadata

4 participants