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
packages.lock.json 是什麼?
預設 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
以下情況造成 dotnet restore 結果找出不同的 Packages 集合:
- nuget.config mismatch: 不同的 OS 上有不同的 nuget.config,造成下載到不同版本的 packages。
- Intermediate versions:
- Day 1,
<PackageReference Include="My.Sample.Lib" Version="4.0.0"/>
Nuget 上有 4.1.0, 4.2.0, 4.3.0,dotnet restore 取得 4.1.0。 - Day 2,4.0.0 發佈到 Nuget。這時候執行 dotnet restore 會取得 4.0.0。
- Day 1,
- Package deletion: 如同 2. 的描述,當找不到對應的版本時,dotnet restore 會找最接近的版本,這也就導致抓到不同版本的 package。(Nuget.org 不允許刪除 package;但是 GitLab Package Registry 可以刪除)
- Floating versions:
<PackageReference Include="My.Sample.Lib" Version="4.*"/>
這會抓取 4.x 的最新版本,造成 dotnet restore 會抓取到不同版本。 - Package content mismatch: 相同的版本號,但是 Package 內容卻不同。這可能發生 Nuget.config 有 2 個以上的來源,都有相同 Package、版本號,這造成 dotnet restore 抓到不同的版本。
Reference
https://devblogs.microsoft.com/nuget/enable-repeatable-package-restores-using-a-lock-file/