Go1.25 新特性:引入go mod verify -tag,模塊管理又更安全了!
大家好,我是煎魚。
Go 模塊管理(Module)已經(jīng)發(fā)展了好幾年了。在近年來,像是供應鏈攻擊和各類安全訴求越提越多。感覺過段時間也也快到護網(wǎng)的日子了。
最近 Go1.25 新特性中,對于這一塊有了一個小點的補全,可以提高一定的安全性。分享給大家。
背景
最早在 2021 年時,@Jay Conrod 就提出過《cmd/go: go mod verify should check hashes in go.sum against GOSUMDB[1]》 的問題:
圖片
復現(xiàn)步驟
其復現(xiàn)問題的步驟是:
- 給一個模塊打版本,例如 example.com/m@v0.1.0。
- 設(shè)置 GOPROXY=direct,GOSUMDB=off。然后在另一個模塊中 go get example.com/m@v0.1.0。這樣就能在不通知 proxy.golang.org 或 sum.golang.org 的情況下將該版本下載到緩存中,并在 go.sum 中添加一個 sum 版本。
- 更改某些內(nèi)容并更新版本標簽,使其指向新的更改。
- 清除 GOPROXY 和 GOSUMDB。
- 運行 go mod verify,觀察無安全錯誤。
- 使用 go clean -modcache 清理模塊緩存。
- 運行 go list all 或其他可下載修改后版本的命令,發(fā)現(xiàn)安全錯誤。
預期和問題
實際上:在第一次執(zhí)行 go mod verify 命令時,應當報告一個安全錯誤。
也就是對于構(gòu)建列表中未被 GOPRIVATE 或 GONOSUMDB 匹配的模塊(即所有公開可用的模塊),Go 工具鏈應當:
- go mod verify 應該對比已下載模塊的哈希值與 go.sum 中記錄的哈希值
- 并將其與 GOSUMDB(Go 官方校驗和數(shù)據(jù)庫)進行驗證。
在這種場景下,由于該模塊的哈希值不在 GOSUMDB 中,工具會嘗試從原始源頭抓取 example.com/m@v0.1.0,并返回該版本的哈希值。
而由于模塊被篡改,其新哈希值將與原始 go.sum 中記錄的不一致,go mod verify 就會報告一個安全錯誤。
新提案:go mod verify -tag
在 2024 年,終于再有 “猛人出現(xiàn)”。@Esra-Al 提出了《cmd/go: add go mod verify -tag[2]》,試圖解決這個問題:
圖片
本次提案的計劃是:Go 缺乏一種 CLI 來根據(jù) Go 校驗和數(shù)據(jù)庫驗證本地軟件源。在 go mod verify 中添加一個 tag 命令參數(shù),將會根據(jù) sumdb 檢查本地 git tag,可以幫助模塊作者確保其內(nèi)容未被篡改。
這可以防止有人通過強行推送的方式訪問 GitHub、GitHub 本身,甚至 Google,在未經(jīng)授權(quán)的情況下修改模塊內(nèi)容?!?/p>
其建議添加一個 -tag 標志符,支持以下幾個參數(shù)值:
- all: 根據(jù) sumdb 檢查所有本地 git tag。
- latest: 只檢查最新的本地 git tag。
- [version]: 檢查特定版本(例如:go mod verify -tag=v1.0.0)。
未來該項提案發(fā)布后,這通常將用于 Go 應用程序發(fā)布打標簽的過程。
例如:
git tag v1.2.3
git push --tags
# Verify that our local v1.2.3 tag matches sumdb.
go mod verify -tag v1.2.3
總結(jié)
本文提及的新提案,相信大家很快就能看到。目前提案已經(jīng) Accepted。這意味著如果沒有意外,將會在 Go1.25 新特性中能夠看到:
圖片
圖片
后續(xù)我們將可以借助該新特性: go mod verify -tag vx.x.x 這一個新的命令參數(shù),其會根據(jù)根據(jù) sumdb 檢查本地 git tag,確保 Go 項目所引用的模塊的內(nèi)容未被篡改。為我們的安全進一步保駕護航。
參考資料
[1] cmd/go: go mod verify should check hashes in go.sum against GOSUMDB: https://github.com/golang/go/issues/47752
[2] cmd/go: add go mod verify -tag: https://github.com/golang/go/issues/68669