Semgrep Supply Chain 掃描 C# 需要 packages.lock.json。但是預設的專案並不會有此檔案,可以用以下方式建立:
dotnet restore -p:RestorePackagesWithLockFile=True
或是在 OS 設定環境變數(RestorePackagesWithLockFile = True),然後執行 dotnet restore。
在 GitLab Pipeline 可以這樣寫:
stages:
- PreTest
- Test
lockFile:
image: mcr.microsoft.com/dotnet/sdk:8.0.201-jammy
stage: PreTest
script:
- dotnet restore -p:RestorePackagesWithLockFile=True
artifacts:
paths:
- ./**/packages.lock.json
expire_in: 1 week
semgrep:
image: returntocorp/semgrep
stage: Test
dependencies:
- lockFile
script: semgrep ci
rules:
- if: $CI_PIPELINE_SOURCE == "web" # allow triggering a scan manually from the gitlab UI
- if: $CI_MERGE_REQUEST_IID
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
variables:
SEMGREP_APP_TOKEN: $SEMGREP_APP_TOKEN
# To configure MR comments on gitlab.com, see <https://semgrep.dev/docs/semgrep-cloud-platform/gitlab-mr-comments/#enabling-gitlab-merge-request-comments>
GITLAB_TOKEN: $PAT
預設 C# Project 使用的 Package 都是寫在 .csproj,用 [PackageReference] 描述,參考如下:
...
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="Serilog" Version="3.1.1" />
</ItemGroup>
...
每次建制(Build)專案的時候會執行 dotnet restore,會根據 PackageReference 找出 Project 需要的 Packages。注意上述的說明,是每次 Build Project 的時候,重新找出全部的 Packages。所以這「可能」發生相同的程式,一年前執行和現在執行取到不同的 Package,造成得到不同的結果。
packages.lock.json 就是要解決這個問題,確保每一次都一定抓到相同的 Packages。
以下情況造成 dotnet restore 結果找出不同的 Packages 集合:
<PackageReference Include="My.Sample.Lib" Version="4.0.0"/>
Nuget 上有 4.1.0, 4.2.0, 4.3.0,dotnet restore 取得 4.1.0。<PackageReference Include="My.Sample.Lib" Version="4.*"/>
這會抓取 4.x 的最新版本,造成 dotnet restore 會抓取到不同版本。https://devblogs.microsoft.com/nuget/enable-repeatable-package-restores-using-a-lock-file/