セキュリティ保証ケース¶
この文書は httptap のセキュリティ保証ケースです。それらのセキュリティ特性が**何であるか**だけでなく、プロジェクトがそれらのセキュリティ特性が成立すると考える**理由**を説明します。OpenSSF Best Practices の silver レベルの assurance_case 基準に従って構成されています。
最終レビュー: 2026-10-05。
保証ケースは生きた文書です。すべてのメジャーリリース時、および脅威の状況や機能セットに重大な変化があるたびにレビューされます。修正の提案はこのファイルに対するプルリクエストとして受け付けます。
httptap とは¶
httptap はコマンドラインの診断ツールです。開発者は単一の URL(およびオプションでヘッダー、ボディ、プロキシ、CA バンドルなど)を指定し、httptap は 1 回の HTTP リクエスト(または短いリダイレクトチェーン)を実行して、フェーズごとのタイミングと TLS 情報を表示します。以下は**行いません**:
- 信頼できないピアからネットワーク入力を受け付ける(サーバーではありません);
- ユーザーアカウント、セッション、または長期間有効な認証情報を管理する;
- リモートコードを実行したり、サーバーから提供されたスクリプトを評価したりする;
- オプションの
--jsonレポート、--harアーカイブ、--prometheusテキストファイルを超えてシークレットやユーザーデータを永続化する; - ユーザーがオプションの
--otlpで指定した OTLP コレクター以外に計測結果を送信する。
セキュリティ要件¶
プロジェクトは以下の観測可能なセキュリティ特性にコミットします。それぞれは以下のセクションの裏付けとなる論拠にマッピングされています。
| # | 要件 | 根拠 |
|---|---|---|
| SR-1 | TLS 証明書の検証は、すべての HTTPS ターゲットに対してデフォルトで有効。 | デフォルトで受動的および能動的な MITM を防止する。 |
| SR-2 | 平文 HTTP、弱められた TLS、またはカスタム CA バンドルには、明示的なユーザーのオプトインが必要。 | 安全でない設定が常に意図的であることを保証する。 |
| SR-3 | ユーザーが指定した認証情報(Authorization、Cookie、Proxy-Authorization ヘッダー)は、オリジン(スキーム、ホスト、ポート)が異なるリダイレクトターゲットには送信されず、メソッドを GET に切り替えるリダイレクトの後はリクエストボディも再送されない。 | オープンリダイレクトを介した認証情報の窃取を防止する。 |
| SR-4 | ツールはリモートホストが提供するコンテンツを実行しない。 | サーバーからのコード実行プリミティブが存在しない。 |
| SR-5 | リリース成果物(PyPI wheel/sdist、コンテナイメージ、git タグおよびリリースコミット)は署名され、そのビルドプロベナンスは検証可能。 | 改ざんされた配布物からユーザーを保護する。 |
| SR-6 | すべての CI ワークフロートークンは最小権限に従い、SHA でピン留めされている。 | ビルドパイプラインの攻撃対象領域を削減する。 |
| SR-7 | サプライチェーン(依存関係、GitHub Actions、Docker イメージ)は既知の脆弱性について監視されている。 | 上流の脆弱性への迅速なパッチ適用。 |
信頼境界¶
┌─────────────────────┐
│ CLI user │ trusted
│ (argv, stdin, env) │
└──────────┬──────────┘
│
▼
┌─────────────────────┐ --json, --har, --prometheus ┌─────────────────────┐
│ httptap process │ ────────────────────────────► │ Local files, stdout │ trusted
│ (Python 3.11+) │ └─────────────────────┘
│ │ --otlp (OTLP/HTTP) ┌─────────────────────┐
│ │ ────────────────────────────► │ OTLP collector │ user-chosen
└──────────┬──────────┘ └─────────────────────┘
│ TLS/HTTP ◄─── untrusted: network, proxy, remote host
▼
┌─────────────────────┐
│ Remote HTTP server │ untrusted
└─────────────────────┘
- ユーザー → httptap は信頼できる: ユーザーは任意のリクエストを発行する正当な理由を持っていると想定される。入力検証は、オペレーターのミスを防ぐために、不正な形式の URL、メソッド、タイムアウトなどを依然として拒否する。
- httptap → ネットワーク → リモートサーバー は信頼できない。この境界を越えるすべてのデータは攻撃者に制御されているものとして扱われる: レスポンスヘッダー、ステータスコード、
Locationの値、TLS 証明書、コンテンツボディ。 - httptap → ローカル出力 は信頼できる:
--jsonはレポートを、--harは HAR 1.2 アーカイブをファイルまたは stdout に書き込み、--harと--prometheusはファイルをアトミックに書き込む(同じディレクトリ内の一時ファイルに書き込んでからリネームする)。Prometheus のラベルにはホスト名とリダイレクトのステップ番号のみが含まれ、パスやクエリ文字列が含まれることはない。ファイルはユーザーが指定した場所に作成され、その場所を読み取れる者なら誰でも読み取れる。 - httptap → OTLP コレクター は、ユーザーが
--otlp(オプションのhttptap[otel]extra)で指定したエンドポイントへ、指定どおりhttp://またはhttps://でネットワークを越える。各リクエストステップはフェーズごとの子スパンを持つ 1 つのスパンとなり、メソッド、ステータスコード、ボディサイズ、ホスト名、ピア IP、HTTP と TLS のバージョン、失敗したステップのエラーメッセージを運ぶ。スパンに完全な URL(パス、クエリ文字列、認証情報)やヘッダーが含まれることはない。送信の失敗は警告として報告され、終了コードは変わらない。 - ビルドパイプライン → PyPI / GitHub Releases は、GitHub OIDC(長期間有効な鍵なし)、Sigstore 署名、および SHA でピン留めされたアクションによって保護された別の信頼境界。
脅威モデル¶
脅威は、診断用 HTTP クライアントに適用される STRIDE カテゴリを用いて列挙します。クライアントの範囲外の脅威(例: サーバー側の DoS)は、非目標として明示的に除外します。
| STRIDE | 脅威 | 緩和策 |
|---|---|---|
| Spoofing | 攻撃者が意図された HTTPS サーバーになりすます。 | TLS 証明書の検証がデフォルトで有効(SR-1); --ignore-ssl はオプトインであり、安全でないものとして文書化されている(SR-2)。 |
| Spoofing | 悪意のある PyPI ミラーが改ざんされた wheel を提供する。 | PyPI は TLS を使用する; リリースは SLSA v1.0 プロベナンスとともに Sigstore で署名されている(SR-5); ユーザーは gh attestation verify で検証できる。 |
| Tampering | GitHub Releases 上の改変された成果物。 | 上記と同じ — ビルドプロベナンスの証明書により独立した検証が可能。 |
| Tampering | 侵害されたサードパーティアクションを介して CI パイプラインが汚染される。 | すべてのアクションは SHA でピン留めされている(Scorecard Pinned-Dependencies 10/10 と zizmor pedantic により強制); Dependabot がピンを更新する PR を作成する(SR-6、SR-7)。 |
| Repudiation | — | 範囲外; httptap はマルチユーザーシステムではない。 |
| Information disclosure | -H Authorization の認証情報が、異なるホスト上のリダイレクトターゲットに漏洩する。 | httptap はリダイレクトを自身で処理し(httpx では follow_redirects=False)、スキーム・ホスト・ポートが変わるリダイレクトでは Authorization、Cookie、Proxy-Authorization を削除する; 303、および POST 後の 301/302 はボディなしの GET に切り替える(SR-3)。 |
| Information disclosure | --json または --har のエクスポートがディスク上に認証ヘッダーやプロキシの認証情報を含む。 | Authorization、Proxy-Authorization、Cookie、Set-Cookie、API キーのヘッダーは出力とエクスポートでマスクされ、URL の認証情報は、ターゲットとプロキシの URL、Location/Content-Location ヘッダーとリダイレクト先、エクスポートの警告に表示される --otlp エンドポイントで伏せられる; それでも共有前にエクスポートを確認するよう、SECURITY.md および docs/troubleshooting.md で助言される。 |
| Information disclosure | テレメトリのエクスポートによって、テキストファイルを読む者やコレクターを運用する者にリクエストの詳細が明らかになる。 | Prometheus のラベルはホスト名とステップに限定される; OTLP スパンは完全な URL とヘッダーを含まない。OTLP エクスポートはオプトインであり、--otlp で指定されたエンドポイントにのみ送信される; リモートのコレクターには https:// が推奨される。 |
| Information disclosure | 安全でないプロキシ上での MITM。 | プロキシ URL は検証される(スキーム、ホスト、ポート); 機密性の高いターゲットには socks5h:// / https:// が推奨される; プロキシのソースは監査のために出力および JSON で報告される。 |
| Denial of service | 悪意のあるサーバーが無制限のボディをストリーミングする。 | -m/--timeout(デフォルト 20 秒)はチェーン全体に対する厳密な期限であり、期限が来るとウォッチドッグが接続を遮断するため、応答を止めたりバイトを少しずつ送り続けたりするサーバーが実行を引き延ばすことはできない。 |
| Denial of service | 悪意のあるサーバーが zip 爆弾や巨大なボディをストリーミングする。 | httptap は、タイミングメトリクスのためにバイト数をカウントする以外にボディをデコードしたり永続化したりしないため、メモリコストは線形でありタイムアウトによって制限される。 |
| Elevation of privilege | 悪意のあるレスポンスボディがパーサーの RCE を引き起こす。 | ボディはコンテンツとして解析されることはなく、長さのみが読み取られる。HTML、JS、または埋め込みスクリプトの解釈は行われない(SR-4)。 |
| Elevation of privilege | 悪意のある CLI 引数が下流の呼び出しでシェルインジェクションを引き起こす。 | 引数は argparse によって解析され(シェルなし)、list[str] として httpx に転送される(シェルなし); リクエストパスにシェルの呼び出しは存在しない。 |
範囲外の脅威¶
- 開発者のマシン上でローカルコード実行を行う敵対者。 範囲外 — その敵対者はすでにプロセスを掌握している。
- ユーザーのターミナル / TTY を制御する敵対者。 範囲外。
- TLS 自体に対する暗号解析攻撃。 OpenSSL に委譲されている; 緩和策はシステムの Python ビルドから継承される。
- ポスト量子の脅威。 上流(OpenSSL / Python)で追跡されている; httptap 自体としては範囲外。
適用されたセキュア設計原則¶
Saltzer & Schroeder (1975) に現代的な追加を加えたものにマッピングしています。
| 原則 | httptap における適用 |
|---|---|
| メカニズムの経済性 | 小さなコードベース(約 6 kLoC)、単一の目的、プラグインローダーなし、ランタイム設定ファイルなし。 |
| フェイルセーフなデフォルト | TLS 検証は有効、健全なデフォルトタイムアウト、HTTP/2 を優先、デフォルトではリダイレクトを追跡しない。 |
| 完全な仲介 | すべての送信 HTTP リクエストは HTTPClientRequestExecutor を経由してルーティングされる; レガシーなコードパスは存在しない。唯一の二次的なパスは、同じホストとポートへの HTTP リクエストを伴わない TLS のみのプローブである: ライブ接続から TLS データが得られない場合のフォールバックプローブと、検証失敗後に証明書を報告する検証なしの診断プローブ(リクエスト自体は失敗のまま)。どちらもプロキシ使用時はスキップされ、リクエストの期限内に制限される。 |
| オープンな設計 | コードベース全体が GitHub 上で Apache-2.0 である; 隠蔽によるセキュリティはない。 |
| 権限の分離 | リリースパイプラインは開発環境から分離されている; PyPI への公開は OIDC によってゲートされた GitHub Environment を使用する。 |
| 最小権限 | すべての CI ジョブは明示的な最小限の permissions: を宣言する; write-all を持つワークフローはない。Token-Permissions Scorecard チェックは 10/10 のスコアを獲得している。 |
| 最小共通メカニズム | 実行間で共有される状態がない(単一リクエストのツール); キャッシュやバックグラウンドデーモンがない。 |
| 心理的な受容性 | curl 互換のフラグエイリアス(-X、-L、-k、-x、-H)がメンタルモデルを馴染みのあるものに保つ。 |
| ワークファクター | 開発者のローカルな curl 呼び出しに対する攻撃者の利得は本質的にゼロである — httptap は curl 以上のものを公開しない。 |
| 侵害の記録 | JSON エクスポートは完全なリクエスト/レスポンスのメタデータとプロキシのソースを捕捉するため、事後のフォレンジックは容易である。 |
| 多層防御 | 入力検証 + TLS 検証 + ピン留めされたビルド依存関係 + SAST + シークレットスキャン + Dependabot + 署名されたリリース。 |
対策された一般的な実装上の脆弱性¶
CWE Top 25 (2023) および OWASP ASVS 4.0 から導出されています。列挙されていない項目は、HTTP クライアントに該当しないか、上流で処理されるかのいずれかです。
| CWE | 脆弱性 | 対策 |
|---|---|---|
| CWE-20 | 不適切な入力検証 | argparse の enum/type 強制変換; URL/メソッド/タイムアウト/プロキシは明示的にチェックされる(プロキシのスキーム、ホスト、ポート。不正な場合は終了コード 64); -H の名前は RFC 9110 のトークン、値は印字可能な ASCII でなければならない; リダイレクト先は追跡する前に検証される。 |
| CWE-22 | パストラバーサル(@file データローダー内) | パスはユーザーからそのまま取得される; サーバーが提供したパスがファイルを開くために使用されることは決してない。 |
| CWE-78 | OS コマンドインジェクション | リクエストパスにおいて、ユーザー制御のデータに対する subprocess/os.system の呼び出しがない。 |
| CWE-79 | XSS | HTML のレンダリングなし; サーバーが制御する値(URL、Server、Location、証明書フィールド、エラーメッセージ)は Rich でレンダリングする前に rich.markup.escape でエスケープされ、1 行モードはマークアップなしで出力される。 |
| CWE-89 | SQL インジェクション | データベースなし。 |
| CWE-94 | コードインジェクション | eval/exec は使用されない; レスポンスボディが解析されることは決してない。 |
| CWE-113 | HTTP リクエスト分割(ヘッダー内の CRLF) | CR、LF その他の制御文字を含む -H の値は、リクエストを送信する前に拒否される。 |
| CWE-116 | 不適切な出力エンコーディング | サーバーが制御する文字列は Rich のマークアップレンダリング前にエスケープされる; JSON エクスポートは厳格なエスケープを伴う json.dumps を使用する。 |
| CWE-200 | 機密情報の漏洩 | 機密ヘッダーは出力と JSON エクスポートでマスクされ、URL の認証情報(ターゲット、プロキシ、Location/Content-Location、--otlp エンドポイント)は出力、警告、JSON エクスポートで伏せられる; Prometheus と OTLP のエクスポートには URL のパス、クエリ文字列、ヘッダーが含まれない; リダイレクト時に認証ヘッダーは別のオリジンに転送されない(SR-3); SECURITY.md とドキュメントは共有前にエクスポートを確認するよう助言する。 |
| CWE-295 | 不適切な証明書検証 | TLS 検証はデフォルトで有効; --ignore-ssl はオプトインのみであり、明示的に文書化されている。 |
| CWE-319 | 平文送信 | HTTPS を優先; 平文 HTTP には明示的な http:// URL が必要; プロキシのソースが報告される。 |
| CWE-327 | 壊れた暗号 | stdlib の ssl に委譲されている; 弱いアルゴリズムはリモートサーバーを診断するときにのみ表面化する。 |
| CWE-330 | 不十分なランダム性 | TLS 用の OpenSSL 提供の CSPRNG を超える RNG の使用はない。 |
| CWE-352 | CSRF | 該当なし — httptap はサーバーではなくクライアントである。 |
| CWE-400 | 制御されないリソース消費 | チェーン全体に対する合計期限(読み取りが止まった場合にも適用); 制限されたリダイレクトチェーン(最大 10)。 |
| CWE-502 | 安全でないデシリアライゼーション | json.loads のみ; pickle、yaml.load、marshal はない。 |
| CWE-601 | オープンリダイレクト(認証情報の漏洩) | httptap は明示的なオリジンチェック付きでリダイレクトを処理する — クロスオリジンのホップでは Authorization、Cookie、Proxy-Authorization を削除する。 |
| CWE-918 | SSRF | httptap はクライアントである; 他のシステムに代わってリクエストをプロキシすることはない。 |
サプライチェーンの保証¶
リリースの完全性特性(SR-5)を裏付けるもの:
- 公開: GitHub OIDC Trusted Publishing を介した PyPI(および事前本番のスモークテストとしての TestPyPI)— 長期間有効な PyPI トークンはどこにも存在しない。PEP 740 の証明書は PyPI 上で「Verified publisher」として表示される。
- コンテナイメージ: マルチアーキテクチャ(linux/amd64、linux/arm64)のイメージが Buildx でビルドされ、GHCR にプッシュされ、cosign で鍵なしで署名され、レジストリに添付された SLSA ビルドプロベナンスを伴う。
- Git 署名: リリースコミットと注釈付きタグは、リリースワークフローの OIDC アイデンティティを使用して gitsign(Fulcio による x.509 + Rekor 透明性ログ)で鍵なしで署名される。
- 署名:
actions/attest-build-provenanceと cosign を通じた Sigstore の鍵なし署名。署名鍵は短命であり、実行ごとに Fulcio によって発行され、Rekor 透明性ログを介して検証可能である。 - プロベナンス: SLSA v1.0 の証明書がすべての wheel、sdist、およびコンテナイメージのダイジェストに付随する。
- Dockerfile のリンティング:
hadolintがすべての PR で警告レベルの失敗しきい値とともに実行される。 - ピン留め: すべてのワークフローのすべての GitHub Action は SHA でピン留めされる; Scorecard Pinned-Dependencies と zizmor pedantic によってすべての PR で強制される。
- 依存関係の追跡: CycloneDX および SPDX 形式の SBOM がリリース中に生成され、GitHub Release のアセットとして添付される。
- 悪用可能性の開示: OpenVEX 文書(
httptap-X.Y.Z.openvex.json)が SBOM とともに配布され、各依存関係の CVE についてhttptapが実際に影響を受けるかどうかを宣言する。信頼できる情報源は.vex/httptap.openvex.jsonにバージョン管理されている; VEX を利用するスキャナー(Grype、Trivy、Snyk)はこれを使用して、到達不可能な脆弱なコードパスに対する誤検知アラートを抑制する。
ユーザーはダウンロードした成果物を独立して検証できます:
既知の残存リスク¶
これらは緩和されるのではなく文書化されています。それらは、見落としではなく明示的なトレードオフを表しています。
- 単独のメンテナー。 バス係数は 1 である(GOVERNANCE.md で追跡)。継続性計画は運用における単一障害点を緩和するが、コードレビューについては緩和しない: 単一のレビュアーが第二の目なしに変更をマージできる。pre-commit、CI ゲート、および公開監査証跡が部分的に補償する。
- ランタイムのサンドボックス化なし。 httptap はユーザーの完全な権限で実行される。これは開発者の診断ツールとしては適切であるが、
httptap自体のバグがユーザーの権限で実行されることを意味する。 - OS から継承された TLS トラストアンカー。 OS のトラストストアが侵害された場合(例: 企業の MITM プロキシが private CA をインストールする)、httptap はこれを検出できない。JSON エクスポートの
network.tls_custom_caおよびproxy_sourceフィールドは、カスタム CA バンドルまたはプロキシが使用されていたかどうかを記録する。
変更履歴¶
| 日付 | 備考 |
|---|---|
| 2026-04-12 | httptap 0.4.7 の初期保証ケース(silver 提出)。 |
| 2026-04-13 | 0.5.0 に向けた OSS のハードニング: gitsign で署名されたリリースコミット/タグ、TestPyPI の事前チェック、SLSA プロベナンスを伴う署名済み GHCR コンテナイメージ、CI での hadolint、man ページの成果物。 |
| 2026-09-17 | 0.6.2 のセキュリティ修正(GHSA-pgxm-hj3g-p7wv): リダイレクト時の明示的なオリジンチェックで SR-3 を担保、サーバーが制御する値を Rich のレンダリング前にエスケープ(CWE-79/116)、プロキシの認証情報を伏せる(CWE-200); OpenVEX でアドバイザリーの状態を記録。 |
| 2026-10-05 | --prometheus テキストファイルと --otlp トレースの出力を、信頼境界、脅威モデル、CWE-200 の対策に追加。完全な仲介の項に TLS のフォールバックプローブと診断プローブを記載。-x/--proxy と -H の入力検証(CWE-20、CWE-113)、Location ヘッダーと --otlp エンドポイントにおける URL 認証情報の秘匿(CWE-200)、厳密な合計期限(CWE-400)を追加。 |
参考文献¶
- SECURITY.md — 脆弱性報告のプロセスとサポートされるバージョン。
- GOVERNANCE.md — プロジェクトの役割、決定、および継続性計画。
- ROADMAP.md — 範囲、非目標、および廃止ポリシー。
- トラブルシューティング & FAQ — 運用上のガイダンス。
- CWE Top 25 および OWASP ASVS 4.0 — 実装上の脆弱性のリファレンスカタログ。