# gosentry
[](https://github.com/trailofbits/gosentry/actions/workflows/go.yml)
gosentry は、Go コードベースに対する最先端のファジングキャンペーンのための多数の機能を統合した、Go ツールチェーンのセキュリティ重視のフォークです。以前 `go test -fuzz` を使用していたなら、gosentry をその代替として使用してください。
Go ツールチェーンにはネイティブに存在しないさまざまなファジング改善とバグ検出器が含まれています。以下の TLDR を参照してください。関連するブログ記事は [こちら](https://blog.trailofbits.com/2026/05/12/go-fuzzing-was-missing-half-the-toolkit.-we-forked-the-toolchain-to-fix-it./) から読むこともできます。
**TLDR(機能とオプション)**:
- `struct` 入力を直接ファジングします(カスタムパーサーは不要)。`f.Add(Input{N: 7, S: "hi"})` でシードを追加し、`f.Fuzz(func(t *testing.T, in Input) { ... })` を実行します。
- 整数オーバーフローでパニックを発生させ、算術問題を検出します
- LibAFL による最先端のファジング技術(経路制約の解決など)でファジングします
- 文法から入力を生成/変異させ、無駄な変異を回避します。変異によって有効な数式が生成されます。`X + Y - Z` は `X / U + Z - 14` になり得ますが、`X + Yè - Z` にはなりません
- 選択した関数(重大なエラーロガーなど)でパニックを発生させ、呼び出されたときにクラッシュさせます
- 最近変更された行と新しいカバレッジにファザーを集中させ、主に新しいコミットを対象にします
- ファジング時にデータ競合を検出します
- ファジング時に Go リークを検出します
- ファジング時にタイムアウトで実行の停滞を検出します
- 1 つの CLI でファジングキャンペーンのコーパスから HTML カバレッジレポートを生成します
## Table of Contents
- [ビルド](#build)
- [機能1: 構造体対応ファジング(struct を入力としてファジング)](#feature-1-struct-aware-fuzzing-fuzz-structs-as-inputs)
- [機能2: 整数オーバーフローおよび切り詰め問題の検出](#feature-2-integer-overflow-and-truncation-issues-detection)
- [機能3: 選択した関数でのパニック](#feature-3-panic-on-selected-functions)
- [機能4: LibAFL による最先端ファジング](#feature-4-libafl-state-of-the-art-fuzzing)
- [機能5: Git-blame 指向ファジング(実験的)](#feature-5-git-blame-oriented-fuzzing-experimental)
- [機能6: ファジング時の競合状態、goroutine リーク、ハングの検出](#feature-6-detect-race-conditions-goroutine-leaks-and-hangs-at-fuzz-time)
- [機能7: 文法ベースのファジング(Nautilus)](#feature-7-grammar-based-fuzzing-nautilus)
- [機能8: キャンペーンからのファジングカバレッジレポート生成](#feature-8-generate-go-coverage-reports-from-fuzzing-campaign)
- [トロフィー](#trophies)
- [クレジット](#credits)
## ビルド```bash
cd src && ./make.bash # Produces `../bin/go`. See `GOFLAGS` below.
```
> [!TIP]
> コントリビューター向けドキュメント: コードマップ、推奨される開発ループ、CI エントリポイント、ベンチマークスクリプトについては、`docs/gosentry/index.md` をお読みください。
> このフォークは Pull GitHub App を使用して、`golang/go:master` から `master` への PR を開き自動マージすることで、Go ツールチェーンの最新アップデートから遅れないようにしています。
## 機能 1: 構造体を意識したファジング(構造体を入力としてファズ)
#### 概要
Go のネイティブなファジング (`go test -fuzz=...`) は、ファズパラメータとして少数のスカラー型 (`[]byte`, `string`, 数値, ...) のみをサポートしています。gosentry では、それらのスカラーから構築された**複合型**(構造体、配列、スライス、ポインタ)もファズできます。
これは、コードが自然に構造化入力を受け取り、コーパスをシードしてミューテーションするためだけに独自のエンコーダ/デコーダを構築したくない場合に便利です。
例については、`test/gosentry/examples/multiargs` と `test/gosentry/examples/composite` を参照してください。
#### 簡単な例```go
type Input struct {
Data []byte
S string
N int
OK bool
}
func FuzzStructInput(f *testing.F) {
// Seed the initial corpus with a Go struct (gosentry feature).
f.Add(Input{Data: []byte("A"), S: "B", N: 7, OK: true})
f.Fuzz(func(t *testing.T, in Input) {
if in.OK && in.N == 1337 && in.S == "BOOMMOOB" && bytes.Equal(in.Data, []byte("A")) {
t.Fatalf("boom")
}
})
}
```
<details>
<summary><strong>構造体シード(<code>f.Add</code>)と構造体ファジングの仕組み(作られた接着層)</strong></summary>
Go標準のファザーは<code>struct</code>値を直接ファズできません(スカラー型の小さなリストしか変異できないため)。gosentryは小さな接着層を追加します。ファズターゲットが(<code>Input</code>のような)複合型を使う場合、gosentryは舞台裏で単一の<code>[]byte</code>をファズします。実行のたびに、そのバイト列をあなたの構造体へ**デコード**し(フィールド単位で、スライス/配列/ポインタは再帰的に処理)、デコードされた値をあなたの<code>f.Fuzz</code>コールバックへ渡します。シードにも同じ**エンコーディング**が使われるため、<code>f.Add(Input{...})</code>はエンコードされた<code>[]byte</code>コーパスエントリになり、ファザーは他のシードと同様に再利用・変異できます。
ファザー(LibAFLを含む)は生のバイト列を変異させるため、**どんな**バイト列でも「何らかの」構造体値に変換し、処理を続行できるデコーダが必要です。JSON/<code>gob</code>はほとんどのランダム入力を拒否するため(カバレッジに悪影響)、また未エクスポートフィールドを設定しないため、ファジングでは不変条件を破る方が有益なことがよくあります。このカスタム形式は、小さく、高速で、決定的で、不正なデータに対して寛容です。
内部では、gosentry独自の単純なバイナリ形式(<code>gob</code>でもJSONでもない)を使用しています。コードは<code>src/testing/libafl.go</code>にあります:
- エンコード:<code>libaflMarshalInputs</code> / <code>libaflAppendValue</code>
- デコード:<code>libaflUnmarshalArgs</code> / <code>libaflDecodeValue</code>
エンコード規則(概要):
- <code>bool</code>:1バイト(<code>0</code>または<code>1</code>)
- 整数:リトルエンディアンのバイト列(<code>int</code>/<code>uint</code>は8バイト)
- 浮動小数点数:IEEE-754ビットをリトルエンディアンで表現(<code>float32</code> = 4バイト、<code>float64</code> = 8バイト)
- <code>string</code>:<code>uvarint(len)</code>に続けて生の文字列バイト列
- <code>[]byte</code>:<code>uvarint(len)</code>に続けて生のバイト列
- その他のスライス:<code>uvarint(len)</code>に続けて各要素をエンコード
- 構造体:フィールドを宣言順にエンコード
- ポインタ:1バイト(<code>0</code> = nil、<code>1</code> = 存在する)に続けてポインタ先の値をエンコード
</details>
## 機能2:整数オーバーフローおよび切り詰め問題の検出
#### 概要
この作業は、以前開発された [go-panikint](https://github.com/trailofbits/go-panikint) から着想を得ています。整数演算のオーバーフロー/アンダーフロー検出と、(オプションで)整数変換時の型切り詰め検出を追加します。オーバーフローまたは切り詰めが検出されると、詳細なエラーメッセージを含むパニックが発生し、関与する特定の演算種別と整数型が示されます。
_算術演算_:符号付きおよび符号なし整数型の加算 <code>+</code>、減算 <code>-</code>、乗算 <code>*</code>、除算 <code>/</code> を処理します。符号付き整数では <code>int8</code>、<code>int16</code>、<code>int32</code> を対象とします。符号なし整数では <code>uint8</code>、<code>uint16</code>、<code>uint32</code>、<code>uint64</code> を対象とします。除算のケースでは、符号付き整数の <code>MIN_INT / -1</code> オーバーフロー条件を特に検出します。<code>int64</code> と <code>uintptr</code> は算術演算のチェック対象外です。
_型切り詰め検出_:情報を失う可能性のある整数型変換を検出します。すべての整数型(<code>int8</code>、<code>int16</code>、<code>int32</code>、<code>int64</code>、<code>uint8</code>、<code>uint16</code>、<code>uint32</code>、<code>uint64</code>)を対象とします。<code>uintptr</code> はプラットフォーム依存の使用法のため除外されます。これはデフォルトでは無効です。
オーバーフロー検出はデフォルトで有効です。無効にするには、<code>./make.bash</code> の前に <code>GOFLAGS='-gcflags=-overflowdetect=false'</code> を追加してください。切り詰め問題チェッカーを有効にするには、<code>-gcflags=-truncationdetect=true</code> を使用できます。
#### 仕組み
この機能はコンパイラのSSA生成をパッチし、整数演算と整数変換に追加のランタイムチェックを挿入します。バグが検出されると、詳細なエラーメッセージ付きのパニックを発生させるランタイム関数を呼び出します。チェックはソースコード位置に基づくフィルタリングで適用されるため、ユーザーコードだけが計測され、標準ライブラリファイルや依存関係(モジュールキャッシュおよび<code>vendor/</code>)はスキップされます。
関連するブログ記事は [**こちら**](https://blog.trailofbits.com/2025/12/31/detect-gos-silent-arithmetic-bugs-with-go-panikint/) で読めます。
#### 誤検知の抑制
該当する操作と同じ行、またはその直上の行にマーカーを追加すると、特定のレポートを抑制できます:
- オーバーフロー/アンダーフロー:<code>overflow_false_positive</code>
- 切り詰め:<code>truncation_false_positive</code>
例:```go
// overflow_false_positive
intentionalOverflow := a + b
// truncation_false_positive
x := uint8(big)
sum2 := a + b // overflow_false_positive
x2 := uint8(big) // truncation_false_positive
```
これが機能しない場合がありますが、それはGoが関数をインライン化しているためです。`// overflow_false_positive` で不十分な場合は、関数シグネチャの前に `//go:noinline` を追加してください。
## Feature 3: Panic on selected functions
ファジングの対象を調査する際、特定の関数が呼び出されたときにパニックを発生させたい場合があります。例えば、一部のソフトウェアはパニックを起こさずに `log.error` メッセージを出力する場合がありますが、そのような状況は、セキュリティ研究者がファジング中に検出したい状態を示していることがよくあります。
しかし、これらのエラーは通常、内部的に処理されるため(再試行や一時停止のメカニズム、またはログへのメッセージ出力など)、ファザーからはほぼ見えません。この機能の目的は、この問題に対処することです。
#### 使い方
gosentry をコンパイルし、`--panic-on` フラグを使用します。```bash
./bin/go test -fuzz=FuzzHarness --use-libafl --focus-on-new-code=false --catch-races=false --catch-leaks=false --panic-on="test_go_panicon.(*Logger).Warning,test_go_panicon.(*Logger).Error"
```
上記の例では、`(*Logger).Warning` または `(*Logger).Error` のいずれかが呼び出されるとパニックが発生します(カンマ区切りのリスト)。
<details>
<summary><strong>選択した関数でパニックを発生させる機能の仕組み</strong></summary>```text
┌───────────────────────────────────────────────────────────────────────────┐
│ 1) gosentry `go test` │
│ - parses + validates `-panic-on=...` against packages being built │
│ - forwards patterns to the compiler via `-panic-on-call=...` │
└───────────────┬───────────────────────────────────────────────────────────┘
v
┌───────────────────────────────────────────────────────────────────────────┐
│ 2) `cmd/compile` │
│ - prevents inlining of matching calls so the call stays visible │
│ - SSA pass inserts a call to `runtime.panicOnCall(...)` │
└───────────────┬───────────────────────────────────────────────────────────┘
v
┌───────────────────────────────────────────────────────────────────────────┐
│ 3) `runtime.panicOnCall` │
│ - panics with: "panic-on-call: func-name" │
└───────────────────────────────────────────────────────────────────────────┘
```
実際には、これにより、一致した呼び出しサイトはファザーにとってクラッシュ/パニックのように動作します(注:静的呼び出しサイトのみがトラップ可能です)。
</details>
## 機能4: LibAFL の最先端ファジング
LibAFL は従来の Go ファザーよりも *はるかに* 優れたパフォーマンスを発揮します。ファジング実行時(`go test -fuzz=...`)、gosentry は**デフォルトで** [LibAFL](https://github.com/AFLplusplus/LibAFL) を使用します(ランナーは `golibafl/` にあります)。
安定性に関する注意: LibAFL モードでは、gosentry は `GODEBUG=updatemaxprocs=0` を強制し(ランタイムの GOMAXPROCS 自動更新を無効化)、断続的に発生する Linux CI のクラッシュ("sync: inconsistent mutex state")を回避します。詳細は `misc/gosentry/USE_LIBAFL.md` にあります。
LibAFL(デフォルト)を使用する場合、git 対応スケジューリングを有効にするかどうかを明示的に選択する必要があります: `--focus-on-new-code=true|false`。詳細なドキュメントは[このMarkdownファイル](https://github.com/trailofbits/gosentry/blob/master/misc/gosentry/USE_LIBAFL.md)にあります。
また、LibAFL 用のオプションの JSONC 設定ファイル(文法ファジングオプションを含む)を渡すこともできます。参照は[こちら](https://github.com/trailofbits/gosentry/blob/master/misc/gosentry/libafl.config.jsonc)です。
`"stop_all_fuzzers_on_panic": false` の場合、LibAFL は各クラッシュを保存し、ファジングを継続するためにクライアントを再起動します。```bash
./bin/go test -fuzz=FuzzHarness --focus-on-new-code=false --catch-races=false --catch-leaks=false --libafl-config=path/to/libafl.jsonc # optional --libafl-config
```
`-fuzztime=1m` を使用すると、LibAFL キャンペーンを 1 分後に停止できます。
LibAFL キャンペーンのコーパスからのカバレッジレポート生成については、[機能 8](#feature-8-generate-go-coverage-reports-from-fuzzing-campaign) に記載されています。
文法ベースのファジング (Nautilus) については、[機能 7](#feature-7-grammar-based-fuzzing-nautilus) に記載されています。
<details>
<summary><strong>Go + LibAFL の連携方法</strong></summary>```text
┌───────────────────────────────────────────────────────────────────────────┐
│ 1) gosentry `go test` │
│ - captures `testing.F.Fuzz(...)` callback │
│ - generates extra source file: `_libaflmain.go` │
└───────────────┬───────────────────────────────────────────────────────────┘
v
┌───────────────────────────────────────────────────────────────────────────┐
│ 2) Generated bridge: `_libaflmain.go` │
│ - provides libFuzzer-style C ABI entrypoints: │
│ LLVMFuzzerInitialize │
│ LLVMFuzzerTestOneInput │
│ - adapts bytes -> Go types -> calls the captured fuzz callback │
└───────────────┬───────────────────────────────────────────────────────────┘
v
┌───────────────────────────────────────────────────────────────────────────┐
│ 3) `libharness.a` (static archive on disk) contains: │
│ - compiled objects for all test package (+ dependencies) │
│ - generated `_testmain.go` + `_libaflmain.go` │
│ - LLVMFuzzerInitialize │
│ - LLVMFuzzerTestOneInput │
└───────────────┬───────────────────────────────────────────────────────────┘
v
┌───────────────────────────────────────────────────────────────────────────┐
│ 4) `golibafl/` (Rust + LibAFL) │
│ env: HARNESS_LIB=/path/to/libharness.a │
│ fuzz loop: mutate input -> LLVMFuzzerTestOneInput(data) -> observe │
└───────────────────────────────────────────────────────────────────────────┘
```
In `--use-libafl` モードでは、gosentry が `libharness.a` をビルドし、Rust 製の `golibafl` ランナーが libFuzzer エントリポイントを介してそれをプロセス内で駆動します。注: `HARNESS_LIB` は任意のハーネスアーカイブ名を指すことができます(たとえば `--catch-races` で使用される `libharness_race.a` など)。
</details>
<details>
<summary><strong>カバレッジ計装の仕組み(LibAFL + Go ターゲット)</strong></summary>
`--use-libafl` モードでは、gosentry はカバレッジ計装を有効にして Go ハーネスをコンパイルします。これにより、プログラムのさまざまな部分が実行されたときに変化する小さなカウンタがコードに追加されます。ハーネスが `golibafl` 内で開始されると、Go ランタイムはこれらのカウンタを LibAFL に公開します。LibAFL は各入力後にそれらを読み取ってどのコードが実行されたかを確認し、そのカバレッジを次のミューテーションの指針として使用します。
</details>
##### 制限事項
LibAFL を使用する動機について説明します。`go test -fuzz` によるファジングは、最先端のファジング技術よりも _はるかに_ 遅れています。その良い例が AFL++ の CMPLOG/Redqueen です。これらの機能により、ファザーは特定の制約を解決できます。次のスニペットを想定しましょう。```go
if input == "IMARANDOMSTRINGJUSTCMPLOGMEMAN" {
panic("this string is illegal")
}
```
SOTAファザー(AFL++やLibAFLなど)は、その場合パニックを即座に検出するでしょう。しかし、Goネイティブファザーはそうではありません。これは、カバレッジ探索を**大幅に**制限する大きなギャップです。
以下のベンチマークは、これらの限界を示しています。これらのベンチマークは、[gosentry-bench-libafl リポジトリ](https://github.com/kevin-valerio/gosentry-bench-libafl/tree/main)で**再現**および改善できることに注意してください。
##### ベンチマーク1:
下のチャートは、LibAFLとGoネイティブファザーを使用してGoogleの[UUID](https://github.com/google/uuid)をファジングした際にカバーされた行数の推移です。

##### ベンチマーク2:
下のチャートは、LibAFLとGoネイティブファザーを使用して[go-ethereum](https://github.com/ethereum/go-ethereum)をファジングした際にカバーされた行数の推移です。

#### 例
`test/gosentry/examples/` にあるいくつかのファジングハーネスでテストできます。```bash
cd test/gosentry/examples/reverse
../../../../bin/go test -fuzz=FuzzReverse --focus-on-new-code=false --catch-races=false --catch-leaks=false
```
Ctrl+C でファズキャンペーンを停止してください。
##### LibAFL 出力ディレクトリ(キャンペーン ID / コーパスの再利用)
gosentry は、LibAFL のキャンペーン状態(コーパス、クラッシュなど)を、Go のファズキャッシュルート(おおよそ `$(go env GOCACHE)/fuzz`)の下にある、**同じパッケージ + 同じファズターゲット**(および同じプロジェクトルート)から導出される決定論的なディレクトリに保存します。
つまり、同じファズキャンペーンを停止(Ctrl+C)して再開すると、デフォルトでは前回の LibAFL `queue/` コーパスから継続されます。
パスは実行の最後に出力されます。```text
libafl output dir: /full/path/to/.../fuzz/<pkg import path>/libafl/<project>/<harness>
```
Notes:
- `<harness>` は、`-fuzz` が `FuzzXxx`(または `^FuzzXxx$`)のような単純な識別子である場合のファズターゲット名です。それ以外の場合は `pattern-<hash>` です。
- カバレッジ生成(`--generate-coverage`)は、正しい `queue/` コーパスを見つけるために同じルールを使用するため、同じパッケージから同じ `-fuzz=...` で実行する必要があります。
## 機能5: Git-blame指向ファジング(実験的)
#### 概要
カバレッジ誘導ファジングは新しいパスを探索するのに優れていますが、カバーされたすべてのコードを同等に興味深いものとして扱います。大規模なコードベースをファジングする際には、リグレッションやバグが発生しやすい最近変更されたコードにファザーを偏らせたい場合があります。LibAFLモードでは、gosentryは`git blame`を使用して、最近変更された行を実行する入力を優先できます(カバレッジガイダンスを主要なシグナルとして維持しつつ)。
この作業は、[LibAFL-git-aware](https://github.com/kevin-valerio/LibAFL-git-aware) の以前の作業に基づいています。技術的な詳細はすべてそこに文書化されています。
#### 使用方法
`--focus-on-new-code=true` でgit対応スケジューリングを有効にします:```bash
./bin/go test -fuzz=FuzzHarness --use-libafl --focus-on-new-code=true --catch-races=false --catch-leaks=false
```
このモードでは、`git`(`git blame` の実行用)と `go tool addr2line`(カバレッジカウンタをソースの `file:line` にマッピングし直すため)が必要です。
<details>
<summary><strong>git-blame指向ファジングの仕組み</strong></summary>```text
┌───────────────────────────────────────────────────────────────────────────┐
│ 1) gosentry `go test -fuzz` │
│ - builds `libharness.a` (contains `go.o` + `.go.fuzzcntrs`) │
│ - runs `golibafl` with `GOLIBAFL_FOCUS_ON_NEW_CODE=1` │
└───────────────┬───────────────────────────────────────────────────────────┘
v
┌───────────────────────────────────────────────────────────────────────────┐
│ 2) `golibafl` generates a cached "git recency map" │
│ - maps coverage counters -> (file:line) via `go tool addr2line` │
│ - runs `git blame` to get a timestamp per line │
│ - stores timestamps in `git_recency_map.bin` │
└───────────────┬───────────────────────────────────────────────────────────┘
v
┌───────────────────────────────────────────────────────────────────────────┐
│ 3) LibAFL scheduler uses the recency map │
│ - coverage decides what enters the corpus │
│ - among the corpus, prioritize inputs that hit newer lines │
└───────────────────────────────────────────────────────────────────────────┘
```
</details>
<details>
<summary><strong>gosentry が <code>git_recency_map.bin</code> をビルドする方法</strong></summary>
`.go.fuzzcntrs` は、Go の libFuzzer スタイルの **8ビットカバレッジカウンタ** を保持するリンカセクションです (`-gcflags=all=-d=libfuzzer` で有効化)。各バイトは「この計測ポイントが何回ヒットしたか」を表します。`--focus-on-new-code=true` の場合、`golibafl` は以下の手順で `git_recency_map.bin` を生成します:
1. `libharness.a` から `go.o` を抽出する。
2. `.go.fuzzcntrs` セクションのサイズを読み取り、カウンタ数 `N` を取得する。
3. `.text` 内で `.go.fuzzcntrs` シンボルを参照する再配置情報をスキャンし、各カウンタインデックスのアドレスを復元する。
4. `go tool addr2line` を使用して、各アドレスを `file:line` に解決する。
5. `git blame --line-porcelain` を実行して、行ごとの `committer-time` を取得する。
6. `git_recency_map.bin` を `u64 head_time` + `u64 N` + `N * u64 timestamps` (リトルエンディアン) として書き込む。未マッピングのエントリはタイムスタンプ `0` を使用する。
</details>
<details>
<summary><strong>ベンチマーク 1 (go-ethereum / geth): ベースライン vs git対応版</strong></summary>
`misc/gosentry/bench_focus_on_new_code_geth.sh --trials 5 --warmup 600 --timeout 200` で実行。
</details>```text
gitaware_5: crash (7122ms)
baseline results:
trial 1: crash (107747ms)
trial 2: crash (146415ms)
trial 3: crash (37902ms)
trial 4: crash (154034ms)
trial 5: timeout (200000ms)
baseline crashes: 4/5 (timeouts=1, errors=0)
baseline median (capped to timeout): 146.415s
git-aware results:
trial 1: timeout (200000ms)
trial 2: crash (87432ms)
trial 3: crash (61733ms)
trial 4: crash (157540ms)
trial 5: crash (7122ms)
git-aware crashes: 4/5 (timeouts=1, errors=0)
git-aware median (capped to timeout): 87.432s
```
</details>
## 機能 6: ファズ時に競合状態、goroutine リーク、ハング(タイムアウト)を検出する
##### 確認済みハングの捕捉(LibAFL タイムアウト)
LibAFL でファジングを行うと、ハーネスの実行が **タイムアウト** することがあります(例: デッドロック、待機中にスタックした goroutine、または非常に遅いパス)。
誤検知を減らすため、gosentry はタイムアウトをハングの候補として扱い、タイムアウトした入力をより大きなタイムアウトで数回リプレイして確認します。ハングが確認された場合、gosentry は入力を `<libafl output dir>/hangs/` に書き込み、ファズキャンペーンを停止します(バグ/クラッシュとして扱います)。
終了前に、`golibafl` はクラッシュ/ハングする入力を最小化しようとします(ベストエフォート。ハングは合計で最大約60秒に制限されます)。
注: ハング確認は初期コーパスのインポート/生成中にも実行されるため、すべての入力でタイムアウトするターゲットでも決定的に検出できます。
これは `--libafl-config` で設定します:
- `catch_hangs` (デフォルト: `true`)
- `hang_timeout_ms` (デフォルト: `10000`)
- `hang_confirm_runs` (デフォルト: `3`)
##### データ競合の捕捉(`--catch-races`)
gosentry は、LibAFL の `queue/` ディレクトリを監視し、`GORACE=halt_on_error=1` を設定して新たに発見されたシードをリプレイする、独立した `-race` リプレイループを実行できます。
```
---
[Read more](https://github.com/trailofbits/gosentry)