From 9bd319198307a32cf4bf8fe21ccf242b738556f7 Mon Sep 17 00:00:00 2001 From: Widthdom Date: Sun, 26 Jul 2026 00:18:09 +0900 Subject: [PATCH] Streamline private vulnerability reporting --- CHANGELOG.md | 4 + .../CiAutomationConfigurationTests.cs | 39 +++++ README.md | 2 +- SECURITY.md | 164 +++++++++++------- doc/DEVELOPER_GUIDE.md | 2 +- 5 files changed, 151 insertions(+), 60 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9c03d311..d96fd031 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), #### Changed +- **Private vulnerability reporting and a streamlined security policy** — The repository now accepts confidential reports through GitHub private vulnerability reporting. `SECURITY.md` has one complete English section and one equivalent Japanese section covering supported versions, the direct private-reporting path, report contents, response targets, coordinated disclosure, and the preserved threat model. Regression coverage protects the reporting link, bilingual policy structure, and Japanese documentation anchors. Affected: `SECURITY.md`, `README.md`, `doc/DEVELOPER_GUIDE.md`, `FolderDiffIL4DotNet.Tests/Architecture/CiAutomationConfigurationTests.cs`, and the GitHub repository security setting. Issue: #223. + - **Release notes now use explicit dynamic comparison links** — The release workflow resolves the latest non-draft, non-prerelease stable GitHub Release by publication time, combines its tag with the current release tag to build the `Full Changelog` comparison URL, and appends the NuGet install/update commands in a consistent release-note template. Regression coverage keeps the release filtering, publication-time selection, dynamic URL, section order, and `nildiff` commands intact. Affected: `.github/workflows/release.yml`, `doc/DEVELOPER_GUIDE.md`, `FolderDiffIL4DotNet.Tests/Architecture/CiAutomationConfigurationTests.cs`. - **GitHub Actions now use immutable dependencies and least-privilege jobs** — Every third-party action is pinned to a reviewed full commit SHA with an adjacent release-version comment, while DocFX and `dotnet-ildasm` installations use exact versions. Mutation-summary comments, benchmark baseline updates, and CodeQL result uploads now run in separate write-capable jobs restricted to same-repository pull requests, `main` pushes, or other trusted events. Validation and CodeQL analysis remain read-only and continue to run for fork-originated pull requests. Dependabot continues to cover pinned GitHub Actions. Affected: `.github/workflows/dotnet.yml`, `.github/workflows/benchmark-regression.yml`, `.github/workflows/codeql.yml`, `.github/workflows/release.yml`, `FolderDiffIL4DotNet.Tests/Architecture/CiAutomationConfigurationTests.cs`. @@ -1700,6 +1702,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), #### 変更 +- **Private vulnerability reporting とセキュリティポリシーの整理** — リポジトリは GitHub private vulnerability reporting を通じて機密報告を受け付けるようになりました。`SECURITY.md` を、サポート対象バージョン、private report への直接リンク、報告内容、対応目標、協調開示、維持した脅威モデルを一読で確認できる、完全な英語節と同等の日本語節へ整理しました。報告リンク、英日ポリシー構造、日本語文書のアンカーを回帰テストで保護します。対象: `SECURITY.md`, `README.md`, `doc/DEVELOPER_GUIDE.md`, `FolderDiffIL4DotNet.Tests/Architecture/CiAutomationConfigurationTests.cs`, GitHub リポジトリのセキュリティ設定。Issue: #223. + - **リリースノートの比較リンクを明示的かつ動的に生成** — リリース workflow は公開日時を基準に、非 Draft・非 Prerelease の最新安定 GitHub Release を解決し、そのタグを今回のリリースタグと組み合わせて `Full Changelog` の比較 URL を構築し、NuGet の install/update コマンドを統一されたリリースノートテンプレートへ追加するようになりました。Release の絞り込み、公開日時による選択、動的 URL、セクション順序、`nildiff` コマンドを回帰テストで保護します。対象: `.github/workflows/release.yml`, `doc/DEVELOPER_GUIDE.md`, `FolderDiffIL4DotNet.Tests/Architecture/CiAutomationConfigurationTests.cs`。 - **GitHub Actions の依存関係を不変化し、ジョブを最小権限化** — すべての third-party Action を、隣接するリリース版コメント付きのレビュー済み完全 commit SHA に固定し、DocFX と `dotnet-ildasm` のインストールも正確なバージョンへ固定しました。mutation summary の PR コメント、benchmark baseline 更新、CodeQL 結果 upload は、同一リポジトリ由来 PR、`main` push、またはその他の信頼済みイベントに限定した write 権限付き専用ジョブへ分離しました。検証と CodeQL 解析は read-only のまま fork 由来 PR でも実行します。Dependabot は固定済み GitHub Actions を引き続き更新対象にします。対象: `.github/workflows/dotnet.yml`, `.github/workflows/benchmark-regression.yml`, `.github/workflows/codeql.yml`, `.github/workflows/release.yml`, `FolderDiffIL4DotNet.Tests/Architecture/CiAutomationConfigurationTests.cs`。 diff --git a/FolderDiffIL4DotNet.Tests/Architecture/CiAutomationConfigurationTests.cs b/FolderDiffIL4DotNet.Tests/Architecture/CiAutomationConfigurationTests.cs index 15ff23dc..4cb3e87e 100644 --- a/FolderDiffIL4DotNet.Tests/Architecture/CiAutomationConfigurationTests.cs +++ b/FolderDiffIL4DotNet.Tests/Architecture/CiAutomationConfigurationTests.cs @@ -99,6 +99,45 @@ public void UserFacingDocumentation_DoesNotAdvertiseHiddenSpinnerOptions() } } + /// + /// Verifies that the security policy directs equivalent English and Japanese guidance to the private reporting flow. + /// セキュリティポリシーの英日案内が同等で、非公開報告フローへ誘導することを検証します。 + /// + [Fact] + [Trait("Category", "Unit")] + public void SecurityPolicy_UsesPrivateReportingAndCompleteBilingualSections() + { + const string privateReportingUrl = + "https://github.com/Widthdom/FolderDiffIL4DotNet/security/advisories/new"; + var policy = File.ReadAllText(GetRepositoryFilePath("SECURITY.md")); + var readme = File.ReadAllText(GetRepositoryFilePath("README.md")); + var developerGuide = File.ReadAllText(GetRepositoryFilePath("doc", "DEVELOPER_GUIDE.md")); + + Assert.True( + Regex.Matches(policy, "^## English$", RegexOptions.Multiline).Count == 1, + "SECURITY.md must contain exactly one complete English section."); + Assert.True( + Regex.Matches(policy, "^## 日本語$", RegexOptions.Multiline).Count == 1, + "SECURITY.md must contain exactly one complete Japanese section."); + Assert.Equal(2, Regex.Matches(policy, Regex.Escape(privateReportingUrl)).Count); + Assert.Contains("### Supported Versions", policy, StringComparison.Ordinal); + Assert.Contains("### サポート対象バージョン", policy, StringComparison.Ordinal); + Assert.Contains("within 3 business days", policy, StringComparison.Ordinal); + Assert.Contains("3 営業日以内", policy, StringComparison.Ordinal); + Assert.Contains("within 7 business days", policy, StringComparison.Ordinal); + Assert.Contains("7 営業日以内", policy, StringComparison.Ordinal); + Assert.Contains("every 14 calendar days", policy, StringComparison.Ordinal); + Assert.Contains("14 暦日ごと", policy, StringComparison.Ordinal); + Assert.Contains("### Threat Model", policy, StringComparison.Ordinal); + Assert.Contains("### 脅威モデル", policy, StringComparison.Ordinal); + Assert.DoesNotContain("open a minimal public issue", policy, StringComparison.OrdinalIgnoreCase); + Assert.DoesNotContain("最小限の public issue", policy, StringComparison.Ordinal); + Assert.Contains("SECURITY.md#日本語", readme, StringComparison.Ordinal); + Assert.DoesNotContain("SECURITY.md#japanese", readme, StringComparison.Ordinal); + Assert.Contains("../SECURITY.md#日本語", developerGuide, StringComparison.Ordinal); + Assert.DoesNotContain("../SECURITY.md#セキュリティ", developerGuide, StringComparison.Ordinal); + } + /// /// Verifies that developers and CI share an exact SDK, formatting rules, and a blocking format gate. /// 開発環境と CI が同一の SDK・フォーマット規則・ブロッキング形式検証を共有することを検証します。 diff --git a/README.md b/README.md index 8bdfaa22..fce8ba32 100644 --- a/README.md +++ b/README.md @@ -236,7 +236,7 @@ CLI の詳細、HTML レビュー手順、整合性検証、セマンティッ | ランタイム設計とコントリビューター向け注意点 | [doc/DEVELOPER_GUIDE.md](doc/DEVELOPER_GUIDE.md#guide-ja-map) | | テスト方針とローカルコマンド | [doc/TESTING_GUIDE.md](doc/TESTING_GUIDE.md#testing-ja-run-tests) | | AI エージェント向け共通指示 | [AGENT_GUIDE.md](AGENT_GUIDE.md#japanese) | -| セキュリティモデルと報告先 | [SECURITY.md](SECURITY.md#japanese) | +| セキュリティモデルと報告先 | [SECURITY.md](SECURITY.md#日本語) | | 変更履歴 | [CHANGELOG.md](CHANGELOG.md#日本語) | > **レビュー責任:** このツールはレビューのノイズを減らしますが、false negative がゼロであることは保証せず、人間のリリース判断の代替にはなりません。出荷前に、関連する commit / PR diff、ソースコード、ビルド成果物と照合して最終判断してください。 diff --git a/SECURITY.md b/SECURITY.md index 4fadf28a..c2bf4bcc 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -2,28 +2,52 @@ ## English -This document describes the threat model and security considerations for FolderDiffIL4DotNet, a .NET 8 release-validation tool that compares two folders at the IL level and produces audit reports. +This document explains how to report vulnerabilities privately and describes the threat model for FolderDiffIL4DotNet, a .NET 8 release-validation tool that compares two folders at the IL level and produces audit reports. -### Reporting Security Issues +### Supported Versions -If the repository supports private vulnerability reporting, use that path first. -Otherwise, open a minimal public issue and ask for a private channel. +| Version | Supported | +|---|---| +| Latest published release | Yes | +| Current `main` branch | Yes | +| Older releases | No | -Do not include exploit details, private paths, customer reports, proprietary binaries, tokens, or other sensitive report artifacts in a public issue. +Before reporting, confirm whether the vulnerability still affects the latest published release or the current `main` branch. -### Threat Model +### Reporting a Vulnerability + +Submit suspected vulnerabilities through [GitHub private vulnerability reporting](https://github.com/Widthdom/FolderDiffIL4DotNet/security/advisories/new). +The report and follow-up discussion remain private until disclosure is coordinated. +Do not use a public GitHub Issue to report a vulnerability. + +Include the following when available: + +- the affected version, commit, or environment +- the security impact and the conditions required to trigger it +- minimal reproduction steps or a proof of concept +- relevant configuration and platform details +- a suggested mitigation or fix, if known +- your preferred contact method and credit preference -The existing threat model remains unchanged: +Do not include unrelated private paths, customer reports, proprietary binaries, tokens, credentials, or other sensitive artifacts. +If a sensitive artifact is necessary to reproduce the finding, describe it first and coordinate a safe transfer method in the private report. -- HTML diff reports and reviewed HTML may expose internal paths and code changes. -- Audit logs and IL output are sensitive artifacts. -- The HTML report must remain self-contained and must not load external resources. +### Response and Coordinated Disclosure -Refer to the rest of this file for the preserved STRIDE analysis, mitigations, and known limitations. +The maintainers aim to: -## Threat Model +- acknowledge a new report within 3 business days +- provide an initial assessment and next steps within 7 business days +- provide a status update at least every 14 calendar days while remediation is in progress -### Assets +These are response targets rather than guarantees; complex reports may require more time. +The maintainers and reporter will coordinate remediation, advisory publication, and any public disclosure. +Please keep vulnerability details private until a fix or mitigation is available and the agreed disclosure date is reached. +The advisory will credit the reporter when requested and appropriate. + +### Threat Model + +#### Assets | Asset | Description | Sensitivity | |---|---|---| @@ -33,23 +57,23 @@ Refer to the rest of this file for the preserved STRIDE analysis, mitigations, a | Reviewed HTML | Legal/compliance artifact with reviewer sign-off data, justifications, and integrity verification | High | | IL disassembly output | Decompiled .NET assembly IL code, cached during comparison | High | -### Trust Boundaries +#### Trust Boundaries 1. User input: CLI arguments, `config.json` / `config.jsonc`, and `FOLDERDIFF_*` environment variables 2. File system: old/new folder contents, report output directory, IL disassembly cache 3. External tools: `dotnet-ildasm` and `ilspycmd` 4. Browser: local HTML report rendering -### Threats & Mitigations +#### Threats and Mitigations -#### Tampering +##### Tampering - SHA256 integrity hashes are recorded in `audit_log.json` - Reviewed HTML embeds SHA256-based self-verification - Companion `.sha256` files can be generated - Report headers include generation timestamp and tool version -#### Information Disclosure +##### Information Disclosure - The HTML report uses a strict Content-Security-Policy meta tag - No network requests are made from the report @@ -57,13 +81,13 @@ Refer to the rest of this file for the preserved STRIDE analysis, mitigations, a - File paths may reveal internal directory structure - IL disassembly output may contain sensitive intellectual property -#### Injection +##### Injection - User-supplied data is HTML-encoded before insertion into HTML output - CSP restricts script execution and external sources - No form submissions or external data loading are used -#### Denial of Service +##### Denial of Service - Configurable parallelism limits unbounded thread usage - IL cache budgets limit growth @@ -71,32 +95,32 @@ Refer to the rest of this file for the preserved STRIDE analysis, mitigations, a - Disassembler timeout is configurable - Failing disassemblers can be blacklisted -#### Elevation of Privilege +##### Elevation of Privilege - The tool runs under the invoking user - Subprocess execution uses explicit paths - No privilege escalation mechanisms exist -#### Spoofing +##### Spoofing - Report headers include provenance data - Disassembler availability is reported with tool names and versions - Reviewed HTML SHA256 verification preserves the trust chain -### Subprocess Security +#### Subprocess Security - Disassembler commands are hardcoded candidates, not arbitrary user commands - External tool paths are resolved via `PATH` or configuration - Each disassembler invocation has a configurable timeout - Non-ASCII paths are handled via temporary ASCII-safe copies -### Configuration Security +#### Configuration Security - Environment overrides are scoped to `FOLDERDIFF_*` - Configuration is validated at startup - The tool does not store or require secrets -### Known Limitations +#### Known Limitations | Limitation | Rationale | |---|---| @@ -104,9 +128,54 @@ Refer to the rest of this file for the preserved STRIDE analysis, mitigations, a | File paths may reveal directory structure | Inherent to folder comparison | | IL disassembly output may contain sensitive code | Necessary for IL-level comparison | -## セキュリティ +## 日本語 + +本書は、FolderDiffIL4DotNet(2 つのフォルダを IL レベルで比較し、監査レポートを生成する .NET 8 のリリース検証ツール)の脆弱性を非公開で報告する方法と脅威モデルを説明します。 + +### サポート対象バージョン + +| バージョン | サポート | +|---|---| +| 最新の公開リリース | 対象 | +| 現在の `main` ブランチ | 対象 | +| 過去のリリース | 対象外 | + +報告前に、脆弱性が最新の公開リリースまたは現在の `main` ブランチでも再現するか確認してください。 + +### 脆弱性の報告 + +脆弱性の疑いは [GitHub private vulnerability reporting](https://github.com/Widthdom/FolderDiffIL4DotNet/security/advisories/new) から報告してください。 +報告内容とその後のやり取りは、開示を調整するまで非公開で扱われます。 +脆弱性の報告に公開 GitHub Issue を使用しないでください。 + +可能な範囲で次の情報を含めてください。 + +- 影響を受けるバージョン、コミット、または環境 +- セキュリティ上の影響と、発生に必要な条件 +- 最小限の再現手順または概念実証 +- 関連する設定とプラットフォームの詳細 +- 判明している場合は、推奨する緩和策または修正案 +- 希望する連絡方法とクレジット表記 -### 資産 +無関係な private パス、顧客レポート、プロプライエタリなバイナリ、トークン、認証情報、その他の機微な成果物は含めないでください。 +再現に機微な成果物が必要な場合は、まずその概要を記載し、private report 内で安全な受け渡し方法を調整してください。 + +### 対応と協調開示 + +メンテナーは次の対応を目標とします。 + +- 新規報告を 3 営業日以内に確認する +- 7 営業日以内に初期評価と次の対応を提示する +- 修正対応中は少なくとも 14 暦日ごとに状況を更新する + +これらは保証ではなく対応目標であり、複雑な報告では追加の時間が必要になる場合があります。 +メンテナーと報告者は、修正、advisory の公開、一般への開示時期を調整します。 +修正または緩和策が利用可能になり、合意した開示日を迎えるまで、脆弱性の詳細を非公開に保ってください。 +希望があり適切な場合は、advisory に報告者のクレジットを記載します。 + +### 脅威モデル + +#### 資産 | 資産 | 説明 | 機密性 | |---|---|---| @@ -116,23 +185,23 @@ Refer to the rest of this file for the preserved STRIDE analysis, mitigations, a | レビュー済み HTML | 承認データ、理由、整合性検証を含む監査成果物 | 高 | | IL 逆アセンブリ出力 | 比較中にキャッシュされる .NET アセンブリの IL コード | 高 | -### 信頼境界 +#### 信頼境界 1. ユーザー入力: CLI 引数、`config.json` / `config.jsonc`、`FOLDERDIFF_*` 環境変数 2. ファイルシステム: 比較対象の旧/新フォルダ、レポート出力先、IL キャッシュ 3. 外部ツール: `dotnet-ildasm` と `ilspycmd` 4. ブラウザ: ローカル HTML レポートのレンダリング -### 脅威と緩和策 +#### 脅威と緩和策 -#### 改竄 +##### 改竄 - SHA256 整合性ハッシュを `audit_log.json` に記録する - レビュー済み HTML に SHA256 ベースの自己検証を埋め込む - 付随する `.sha256` ファイルを生成できる - レポートヘッダーに生成時刻とツールバージョンを含める -#### 情報漏洩 +##### 情報漏洩 - HTML レポートは厳格な Content-Security-Policy メタタグを使う - レポートからネットワークリクエストは発生しない @@ -140,13 +209,13 @@ Refer to the rest of this file for the preserved STRIDE analysis, mitigations, a - ファイルパスは内部ディレクトリ構造を露出しうる - IL 出力には機微な知的財産が含まれうる -#### インジェクション +##### インジェクション - ユーザー提供データは HTML 出力前にエンコードする - CSP でスクリプト実行と外部ソースを制限する - フォーム送信や外部データ読み込みは使わない -#### サービス拒否 +##### サービス拒否 - 設定可能な並列度でスレッド使用を制限する - IL キャッシュ容量の上限を設定する @@ -154,56 +223,35 @@ Refer to the rest of this file for the preserved STRIDE analysis, mitigations, a - 逆アセンブラのタイムアウトを設定できる - 失敗する逆アセンブラはブラックリスト化できる -#### 権限昇格 +##### 権限昇格 - ツールは呼び出しユーザー権限で動作する - サブプロセス実行は明示的なパスを使う - 権限昇格の仕組みはない -#### なりすまし +##### なりすまし - レポートヘッダーに provenance 情報を含める - 逆アセンブラの可用性をツール名とバージョン付きで表示する - レビュー済み HTML の SHA256 検証で信頼チェーンを維持する -### サブプロセスセキュリティ +#### サブプロセスセキュリティ - 逆アセンブラ候補はハードコードされたコマンドであり、任意コマンドではない - 外部ツールパスは `PATH` または設定から解決する - 各逆アセンブラ呼び出しにはタイムアウトがある - 非 ASCII パスは一時的な ASCII セーフコピーで扱う -### 設定セキュリティ +#### 設定セキュリティ - 環境変数オーバーライドは `FOLDERDIFF_*` に限定する - 設定は起動時に検証する - ツールはシークレットを保存も要求もしない -### 既知の制限事項 +#### 既知の制限事項 | 制限 | 理由 | |---|---| | CSP に `unsafe-inline` を使う | 自己完結型 HTML を維持するため | | ファイルパスがディレクトリ構造を露出する | フォルダ比較の目的上不可避 | | IL 出力には機微なコードが含まれうる | IL レベル比較に必要 | - -## 日本語 - -本書は、FolderDiffIL4DotNet(.NET 8 のリリース検証ツール。2 つのフォルダを IL レベルで比較し、監査レポートを生成する)の脅威モデルとセキュリティ上の注意点を説明します。 - -### 脆弱性報告 - -リポジトリで private vulnerability reporting が利用できる場合は、まずそちらを使ってください。 -利用できない場合は、最小限の public issue を作成して private な連絡経路を依頼してください。 - -public issue には、攻撃手順、private なパス、顧客レポート、プロプライエタリなバイナリ、トークン、その他の機微な成果物を含めないでください。 - -### 脅威モデル - -既存の脅威モデルは維持します。 - -- HTML 差分レポートと reviewed HTML には内部パスやコード変更が含まれる可能性があります。 -- 監査ログと IL 出力は機微な成果物です。 -- HTML レポートは自己完結型を維持し、外部リソースを読み込んではいけません。 - -この後半には、既存の STRIDE 分析、緩和策、既知の制限事項をそのまま残します。 diff --git a/doc/DEVELOPER_GUIDE.md b/doc/DEVELOPER_GUIDE.md index bcde736c..77551be0 100644 --- a/doc/DEVELOPER_GUIDE.md +++ b/doc/DEVELOPER_GUIDE.md @@ -988,7 +988,7 @@ Some browsers (notably macOS Safari) ignore the `accept` attribute on `