Skip to content

セキュリティ方針

このページでは、本ライブラリが どうやって 安全性を保とうとしているかと、同じくらい大事な どんな保証は与えていないか を整理します。

期待値の合わせ方

go-oidc-provider は個人開発者が空き時間で維持している OSS ライブラリです。第三者による独立監査、有償ペネトレーションテスト、OpenID Foundation の公式認証 — いずれも受けていません。下記の性質はコードベースが能動的に防いでいるものを書き出したものであって、第三者監査レポートと同等のものではありません。

5 つの独立した性質

「これは安全か?」と問われたとき、誠実に答えるには次の 5 つに分けて回答する必要があります。

#性質このプロジェクトで示せる根拠
1適合性 — 仕様を実装しているOFCS 緑(適合状況: OFCS
2正しさ — どんな入力でも壊れないtest/ 配下のユニット / シナリオ / fuzz テスト
3セキュリティ — 能動的な攻撃に耐える後述の構造的防御 + 設計判断
4サプライチェーン — 依存が安全であるCI で govulncheck、depguard、サードパーティ目録
5運用 — 時間が経っても安全であるSECURITY.md による報告経路、GitHub Security Advisories

適合性 ≠ セキュリティ です。OFCS が緑でも、攻撃が可能なケース(alg 混同、PKCE ダウングレード、redirect_uri 部分一致、シークレット比較のタイミング攻撃など)は存在し得ます。次のセクションでは、それぞれのクラスを if 文ではなく構造的に閉じている理由を説明します。

構造的防御(コードの形そのもので強制している箇所)

「実装ミスがないか毎回検査する」のではなく、不安全な経路がそもそも存在しないように型 / パッケージ境界で設計しています。

1. コンストラクタはゼロ値起動を拒否する

op.New(...)error を返します — 必須 4 オプション(WithIssuerWithStoreWithKeysetWithCookieKey)のいずれかが欠けるとビルド時にエラー。利用可能なゼロ値の Provider は存在しません。

なぜ重要か

多くの「デフォルト ON」型のフレームワークは設定不足でも気付かれずに起動します。本ライブラリの設計では「OP が立ち上がったが署名鍵がない / 推測可能な cookie 鍵 / 誤った issuer」といったクラスのバグを、最初の 1 リクエストが届く前に閉じます。詳細は op.WithIssuer / op.WithKeyset / op.WithCookieKey / op.WithStore の不在時に出るビルド時エラーを参照してください。

2. JOSE の alg リストは閉じた型

internal/jose.AlgorithmRS256PS256ES256EdDSA の 4 値のみを列挙しています。noneHS256/384/512、その他の文字列は IsAllowed() で false を返します。ParseAlgorithm は不明値に対してフォールバックせず、ok=false を返します。コードベース内のすべての署名 / 検証経路は internal/jose を経由するので、alg 混同攻撃(RFC 7519 §6 / RFC 8725 §2.1)は構造的に到達できません

想定リスク緩和策
JWT ライブラリが alg=none を受理Algorithm(s) は不明値・空文字を拒否
公開鍵経路で HS256 を受理HS* は型に存在しない
配置ごとの alg「フィーチャーフラグ」depguard が internal/jose/ 外からの JOSE ライブラリ直接 import を禁止

3. crypto/rand のみ — math/rand 禁止

リポジトリ全体ルールで math/rand を禁止しています。lint も同様に強制。すべての nonce、コード、リフレッシュトークン、認可コード、DPoP server-nonce は crypto/rand を使います。

4. time.Now()internal/timex/ 経由のみ

time.Now() の直接呼び出しは禁止です。Clock 抽象により、時刻注入を境界で明示し、テスト時に時刻がずれて replay 検証窓のテストが偶然通ってしまう事故を防いでいます。

5. エラーは型付きカタログ経由のみ

fmt.Errorf で API 可視のエラーを作ることはできません。通信路に出るエラーはすべて op.Error / カタログ値から組み立てます。これにより error code、status code、WWW-Authenticate の形が一貫し、情報漏えいもカタログ範囲に収まります。

6. internal/ 境界は不可侵

外部から internal/ を import することはできません。公開すべきものは op/op/profile/op/feature/op/grant/op/store/op/storeadapter/ の安定した公開面に出ています。「JAR verifier だけ差し替えたい」といった抜け道は Go のパッケージ可視性ルールで閉じられています。

7. ORM を持ち込まない設計

ライブラリは ORM(GORM、ent、xo など)を埋め込みません。ストレージは小さな store.*Store interface を介します。呼び出し側は使い慣れたものを実装するだけです。副作用として「気付かぬうちに DB がマイグレーションされる」事態が起きません。

デフォルトで有効な防御機能

防御ソース仕様
__Host- cookie、AES-256-GCM、double-submit CSRF、Origin/Referer チェックinternal/cookieinternal/csrfOWASP ASVS L1 / RFC 6265bis
authorization_code grant に PKCE 必須、plain は拒否internal/pkceRFC 7636
リフレッシュトークンのローテーション + 再利用検知(chain revoke)internal/grants/refreshRFC 9700 §4.14
送信者制約付きトークン(DPoP cnf.jkt、mTLS cnf.x5t#S256internal/dpopinternal/mtlsinternal/tokensRFC 9449、RFC 8705
認可応答に iss を付与internal/authorizeRFC 9207
redirect_uri 完全一致(既定で完全一致)internal/authorizeOAuth 2.1、RFC 8252
ループバック redirect の制約強化internal/registrationendpointinternal/authorizeRFC 8252
Back-Channel Logout の SSRF 防御(RFC 1918 拒否リスト)internal/backchannelOIDC Back-Channel Logout 1.0
OP 側の request_object replay 対策(jtiinternal/jarRFC 9101 §10.8
各検証経路でのアルゴリズム allow-listinternal/joseRFC 8725
Issuer 正規化(末尾スラッシュなどの揺れを防ぐ)op/op.goRFC 9207

ツールチェーン

階層ツール場所
Lintgolangci-lint v2(errcheck、govet、staticcheck、unused、gosec、errorlint、revive、depguard など).golangci.yaml
脆弱性スキャンgovulncheckscripts/govulncheck.sh
FuzzGo 標準 Fuzz*make fuzz / scripts/fuzz.sh 30sinternal/joseinternal/jarinternal/dpopinternal/pkceinternal/jwks などにターゲット
ライセンスgo-licensesscripts/licenses.sh
適合性make conformance-baselinetools/conformance/conformance/
シナリオカタログ駆動の Spec Scenario Suitetest/scenarios/

ここに 無い もの

このプロジェクトの限界をはっきり書きます。採用前に必ず目を通してください。

採用前に必ず確認

  • 第三者によるセキュリティ監査は受けていません。
  • 有償ペネトレーションテストも未実施です。
  • OpenID Foundation の公式認証は取得していません。OFCS 適合状況 参照)
  • パッチ適用 SLA は提供していません。 SECURITY.md には 目安 として「3 営業日以内に受領、確認済み問題は 14 日以内に緩和方針」を書いていますが、契約上の保証ではありません。
  • 24/7 のインシデント対応窓口はありません。 報告経路は GitHub Security Advisories または Maintainer プロフィールです。
  • CVE データベース上のエントリは現時点でゼロです脆弱性報告ガイド)。pre-v1.0 期間中、適格な脆弱性報告がまだ届いていないので公開すべきものがない、というのが文字通りの状況です。「真面目にやっていない」わけではありません。

これらのいずれかが採用要件に含まれているなら、本ライブラリは選ばないでください — 少なくとも v1.0 と公式監査が出るまでは。誠実なお断りは何も損ないませんし、誤用を防げます。

採用判断のヒント

状況判断
自社プロダクトの内部 OP を作る適合します。タグで pin し、自社 CI で govulncheck、GHSA を購読してください
公衆向け、価値の高いフロー(銀行グレード FAPI)このライブラリは出発点として使い、第三者監査を入れて findings を還元する形を推奨
コンプライアンス上の都合で認証取得済み IdP を置換する推奨しません — v1.0 と引用可能な監査結果が揃うまでは控えてください
実 OP のコードベースで OIDC の仕組みを学ぶ最適。構造的防御自体が学習コンテンツになります

続きはこちら

  • 設計判断 — RFC 同士の衝突をどう解釈したか(PAR vs request_uri 再利用、リフレッシュローテーション vs RFC 9700 grace、alg リスト vs OIDC Core …)。
  • 脆弱性報告 — 脆弱性報告、サポート対象バージョン、CVE 取り扱い。
  • OFCS 適合状況 — 適合性が証明できること / できないこと。