Pin transitive NuGet dependencies via lock files with locked-mode restore (#500)#983
Merged
Conversation
…tore (#500) - packages.lock.json committed for all 17 projects; Directory.Build.props enables RestorePackagesWithLockFile and forces RestoreLockedMode when CI=true - Explicit locked-mode restore in ci.yml, release.yml, and all three production Dockerfiles (restore and publish steps) - JIM.Web pins RuntimeFrameworkVersion to the production base image runtime so the implicit Internal.Assets lock entry is deterministic; its Dockerfile cache-warming restore omits locked mode (dotnet/aspnetcore#64897), with enforcement at the publish step - New regenerate-nuget-lock-files workflow pushes signed lock-file regeneration commits to Dependabot NuGet branches (Dependabot cannot regenerate them across project references itself) - New canonical policy page engineering/DEPENDENCY_PINNING.md, cross-referenced from CLAUDE.md, DEVELOPER_GUIDE, COMPLIANCE_MAPPING, and the review-dependabot skill; two pre-existing factual slips corrected - OWASP assessment moved to engineering/plans/doing/ with remediation status Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This was referenced Jul 11, 2026
…nning # Conflicts: # engineering/plans/doing/OWASP_TOP_10_ASSESSMENT.md
…nning # Conflicts: # engineering/COMPLIANCE_MAPPING.md
…ker builds) Ubuntu published cifs-utils 2:7.0-2ubuntu0.5 (the re-enabled fix for CVE-2026-12505) to noble-security/noble-updates on 2026-07-13 and withdrew 2:7.0-2ubuntu0.4 from the archive index, so the jim.worker image build 404s at apt-get install. Bump the pin to the current release; the other three apt pins (libldap-common, libldap2, libgssapi-krb5-2) are unchanged and still available. Same failure mode as #896; the apt-pin-check bot's Sunday run predated the archive rotation by three hours, and Monday's run had not yet fired. Verified: full jim-build Docker build (jim.web, jim.worker, jim.scheduler) succeeds and the stack comes up healthy. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…cker review A Dependabot digest bump that moves the aspnet/sdk base images to a new .NET patch version needs a companion RuntimeFrameworkVersion bump and lock file regeneration in JIM.Web, and CI cannot catch the omission (locked-mode restore still passes against the old pin). DEPENDENCY_PINNING.md documents the coupling but the review skill's Docker section did not check for it; add the check so reviewers catch the silent drift at review time. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
JayVDZ
added a commit
that referenced
this pull request
Jul 14, 2026
#1014) All five remediation gaps are now merged (#1001 rate limiting, #1002 security headers/CSP, #983 NuGet lock files, #984 expression security review, #1013 security audit events), completing the assessment's remediation programme. Move the assessment document to plans/done per the plan filing convention, set its status to Done with the deferred-items note, and repoint the three engineering documents that referenced the plans/doing path. Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
JayVDZ
added a commit
that referenced
this pull request
Jul 14, 2026
….301 (runtime 10.0.9) (#1015) The devcontainer's base tag (devcontainers/dotnet:1-10.0-noble) was frozen upstream on an October 2025 RC-era image and never rebuilt after .NET 10 went GA, and the layered SDK pin (10.0.203, runtime 10.0.7) fell behind JIM.Web's RuntimeFrameworkVersion 10.0.9 when #983 introduced that pin, so native JIM.Web runs (jim-build-light, Generate-OpenApiDoc.ps1) failed at launch with "framework 10.0.9 not found" while Docker builds kept working. - Switch the base to the maintained 2.x image line, digest-pinned per the dependency pinning policy so Dependabot resumes proposing digest bumps (it cannot flag a dead tag: the digest never changes). - Bump the layered SDK pin to 10.0.301, which ships runtime 10.0.9, and document it as a sync point with RuntimeFrameworkVersion. - Drop the stale-Yarn-repo workaround (1.x-era; not present in the 2.x image) and update the PowerShell-removal rationale (the 2.x base ships stable pwsh, but setup.sh's pinned global tool remains canonical). - Add the devcontainer SDK pin to the RuntimeFrameworkVersion companion checklist in DEPENDENCY_PINNING.md and the review-dependabot skill so future .NET patch bumps carry it in the same commit. Verified: the devcontainer image builds clean on the new base, and native OpenAPI generation (the failing workflow) succeeds under a scratch install of SDK 10.0.301. A devcontainer rebuild is needed to pick this up. Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes the "NuGet transitive dependency pinning" gap from the OWASP Top 10:2025 assessment (A03/A08). Part of #500.
Direct NuGet versions, Docker base image digests, apt packages, GitHub Actions SHAs, and devcontainer features were already pinned; transitive NuGet resolution was the one remaining unpinned layer. This PR closes it and consolidates the pinning policy into a single canonical page.
Changes
packages.lock.jsoncommitted for all 17 projects;Directory.Build.propssetsRestorePackagesWithLockFileeverywhere and forcesRestoreLockedModewheneverCI=true.ci.yml(both jobs),release.yml, and all three production Dockerfiles (restore and publish steps).JIM.WebpinsRuntimeFrameworkVersionto the ASP.NET Core runtime bundled by the pinned production base image digests. Without this, the implicitMicrosoft.AspNetCore.App.Internal.Assetslock entry floats with whichever runtime patch is installed on the restoring machine (devcontainer: 10.0.7; production SDK image: 10.0.9), breaking locked-mode restore non-deterministically. This pin is a new manual sync point when base image digests are bumped; documented in the policy page.JIM.Web's Dockerfile cache-warming restore step deliberately omits locked mode due to an open upstream bug (dotnet/aspnetcore#64897): an isolated single-project locked-mode restore of aMicrosoft.NET.Sdk.Webproject inside the SDK container drops the implicit framework-reference package from its comparison and fails NU1004 regardless of lock file content. The publish step (its own implicit restore) is unaffected and enforces the lock file for JIM.Web. Worker/Scheduler are unaffected and enforce on both steps.regenerate-nuget-lock-filesworkflow: Dependabot does not reliably regenerate NuGet lock files across project references (dependabot-core#12318, dependabot-core#10863), so on pushes todependabot/nuget/**branches this workflow runsdotnet restore --force-evaluateand pushes any regenerated lock files back as a GitHub-signed commit via the GraphQLcreateCommitOnBranchmutation, using the jim-automation App token so required checks re-trigger. Expect a transient red first CI run on Dependabot NuGet PRs before the regeneration commit lands; this is documented in the workflow header, the policy page, and the review-dependabot skill.engineering/DEPENDENCY_PINNING.md: threat model, a per-layer inventory (mechanism / enforcement / update path for all nine dependency layers, including the deliberate softer pins and why), verification and provenance controls, governance, and operational runbooks. Cross-referenced from rootCLAUDE.md,engineering/DEVELOPER_GUIDE.md,engineering/COMPLIANCE_MAPPING.md, and the review-dependabot skill (plus two small pre-existing factual corrections found while consolidating: Actions are SHA-pinned not tag-pinned, and the Actions Dependabot cadence is weekly not daily).engineering/plans/doing/with status updated and this remediation marked implemented; links repointed.Validation
CI=true dotnet restore JIM.sln --locked-modepasses.dotnet build JIM.sln: 0 errors, 0 warnings.dotnet test JIM.sln: 3,356 passed, 35 skipped (category-gated), 0 failed.Docs: n/a - supply chain/CI hardening; the changelog entry is 🔒 (security posture), and the policy documentation lives in
engineering/by design.🤖 Generated with Claude Code