microsoft/hve-core

Public

mirrored fromhttps://github.com/microsoft/hve-coreAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
3ed441c3d4a92f1fa944a2121273ba46fdab8a8d

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

docs/security/dependency-pinning.md

208lines · modecode

1---
2title: Dependency Pinning
3description: How HVE Core enforces dependency pinning across GitHub Actions, npm, pip, and shell downloads with automated CI validation
4sidebar_position: 3
5author: Microsoft
6ms.date: 2026-03-02
7ms.topic: concept
8keywords:
9 - dependency pinning
10 - supply chain security
11 - npm
12 - pip
13 - github actions
14estimated_reading_time: 8
15---
16
17## Overview
18
19HVE Core enforces dependency pinning to mitigate supply chain attacks. Every dependency reference in the repository must resolve to a specific, immutable version. The `Test-DependencyPinning.ps1` scanner validates all dependency types during CI and produces SARIF reports for GitHub code scanning integration.
20
21| Dependency Type | Pinning Strategy | Example |
22|-----------------------|------------------------------|-------------------------------------------------------------|
23| GitHub Actions | Full 40-character commit SHA | `actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29` |
24| npm | Exact version (no ranges) | `"eslint": "9.18.0"` |
25| pip | Exact version with `==` | `requests==2.31.0` |
26| Workflow npm commands | `npm ci` enforcement | `npm ci` instead of `npm install` |
27| Shell downloads | Checksum verification | `sha256sum --check` after download |
28
29## npm: Exact-Version Enforcement
30
31> [!NOTE]
32> npm dependencies use **exact-version enforcement** rather than SHA-pinning. Unlike GitHub Actions (where commit SHAs identify immutable source snapshots), npm packages are published as immutable registry artifacts. An exact version string like `9.18.0` is already a unique, deterministic reference.
33
34### What Is Validated
35
36The scanner rejects any version string that contains range operators or wildcards:
37
38```json
39{
40 "dependencies": {
41 "valid": "9.18.0",
42 "invalid-caret": "^9.18.0",
43 "invalid-tilde": "~9.18.0",
44 "invalid-wildcard": "9.*",
45 "invalid-range": ">=9.0.0 <10.0.0"
46 }
47}
48```
49
50### Validation Regex
51
52```text
53^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?(\+[a-zA-Z0-9.]+)?$
54```
55
56This permits standard semver (`1.2.3`), pre-release tags (`1.2.3-beta.1`), and build metadata (`1.2.3+build.42`), while rejecting all range operators.
57
58### Why Not SHA-Pinning for npm
59
60| Criterion | SHA-Pinning (GitHub Actions) | Exact-Version (npm) |
61|----------------------|------------------------------------------------|----------------------------------------------|
62| Registry model | Git repositories with mutable tags | Immutable package tarballs |
63| Mutability risk | Tags can be force-pushed to different commits | Published versions are permanently immutable |
64| Audit tooling | `npm audit` cross-references semver, not SHAs | Full compatibility with `npm audit` |
65| Lockfile integration | N/A | `package-lock.json` records integrity hashes |
66| Human readability | 40-char hex strings obscure the actual version | Version is self-documenting |
67
68## GitHub Actions: SHA Pinning
69
70GitHub Actions references must use full 40-character commit SHAs because action tags (like `v4`) are mutable Git references that can be retargeted to arbitrary commits.
71
72```yaml
73# Rejected: mutable tag reference
74- uses: actions/checkout@v4
75
76# Accepted: immutable SHA reference
77- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.2.2
78```
79
80The scanner validates that the SHA is a real 40-character hexadecimal string and optionally checks staleness against the GitHub API.
81
82## pip: Exact-Version Pinning
83
84Python dependencies must use the `==` operator for exact version pinning. The scanner excludes virtual environment directories (`.venv`, `venv`, `.tox`, `.nox`, `__pypackages__`) to avoid false positives from installed package metadata.
85
86```text
87# Accepted
88requests==2.31.0
89flask==3.0.0
90
91# Rejected
92requests>=2.31.0
93flask~=3.0
94```
95
96## Workflow npm Commands: npm ci Enforcement
97
98CI workflow YAML files are scanned for npm commands that modify the dependency tree at install time. These commands resolve version ranges against the registry, producing non-deterministic installs that can pull in compromised packages.
99
100### Detected Commands
101
102The scanner inspects `run:` blocks in workflow YAML with indentation-aware parsing and flags these commands:
103
104| Flagged | Reason |
105|--------------------|--------------------------------------------------------|
106| `npm install` | Resolves ranges from `package.json`, ignoring lockfile |
107| `npm i` | Alias for `npm install` |
108| `npm update` | Upgrades to latest versions within semver ranges |
109| `npm install-test` | Combines install and test in a non-deterministic way |
110
111### Safe Commands
112
113These npm commands are not flagged because they do not modify the dependency tree:
114
115* `npm ci`: Installs exactly from the lockfile, removing `node_modules` first
116* `npm run`: Executes a script defined in `package.json`
117* `npm test`: Alias for `npm run test`
118* `npm audit`: Reports known vulnerabilities without installing
119* `npx`: Runs a package binary without modifying dependencies
120
121### Remediation
122
123Replace flagged commands with `npm ci` for deterministic, lockfile-based installs:
124
125```yaml
126# Rejected: resolves version ranges from the registry
127- run: npm install
128
129# Accepted: installs exactly what the lockfile specifies
130- run: npm ci
131```
132
133### File Scope
134
135The scanner processes files matching `.github/workflows/*.yml` and `.github/workflows/*.yaml`.
136
137## Shell Downloads: Checksum Verification
138
139Shell scripts that download files from the internet must verify checksums to prevent tampered or corrupted binaries from entering the build environment.
140
141### Detection
142
143The scanner identifies download commands matching `curl` or `wget` with an HTTP/HTTPS URL. It then checks the next five lines for a checksum verification command. If no verification is found, the download is flagged.
144
145### Accepted Verification Commands
146
147Any of these patterns within five lines of the download satisfies the check:
148
149* `sha256sum`: GNU coreutils checksum
150* `shasum`: macOS/BSD checksum utility
151* `Get-FileHash`: PowerShell checksum cmdlet
152* `openssl dgst -sha256`: OpenSSL digest
153* `sha256sum -c`: Checksum file verification
154
155### Examples
156
157```bash
158# Accepted — checksum verified immediately after download
159curl -Lo tool.tar.gz https://example.com/tool-v1.0.tar.gz
160echo "abc123... tool.tar.gz" | sha256sum --check
161
162# Rejected — no checksum verification after download
163wget https://example.com/tool-v1.0.tar.gz
164tar xzf tool-v1.0.tar.gz
165```
166
167### Scanned Files
168
169The scanner processes files matching `.devcontainer/scripts/*.sh` and `scripts/*.sh`, excluding fixture directories used in tests.
170
171## CI Integration
172
173The dependency pinning scanner runs in CI as part of the security validation workflow. It produces SARIF 2.1.0 output that integrates with GitHub code scanning.
174
175```mermaid
176flowchart LR
177 A[CI Trigger] --> B[Test-DependencyPinning.ps1]
178 B --> C{Violations?}
179 C -->|None| D[✅ Pass]
180 C -->|Found| E[SARIF Report]
181 E --> F[GitHub Code Scanning]
182```
183
184### Severity Mapping
185
186| Scanner Severity | SARIF Level | Trigger |
187|------------------|-------------|--------------------------------------------|
188| High | `error` | Unpinned or mutable dependency reference |
189| Medium | `warning` | Stale pinned version with available update |
190| Low | `note` | Informational findings |
191
192### Running Locally
193
194```powershell
195# Full scan with SARIF output
196./scripts/security/Test-DependencyPinning.ps1
197
198# Results appear in logs/dependency-pinning-results.json
199```
200
201## Related Resources
202
203* [Threat Model](threat-model.md): Supply chain threats S-1, S-2, SC-1, SC-4, and SC-6
204* [Branch Protection](../contributing/branch-protection.md): Required status checks including dependency pinning
205
206---
207
208🤖 *Crafted with precision by ✨Copilot following brilliant human instruction, then carefully refined by our team of discerning human reviewers.*
209