# GitHub のテーブル内 HTML 属性サニタイズ実測

GFM のテーブルはセル結合を持たないため、結合したい場合は素の `<table>` HTML を書くことになる。そのとき **どの属性が GitHub を通り、どれが消えるか** を実測したもの。`gfm-table-cheatsheet` の「GitHub が許可する HTML 属性」節の一次ソースとして使う。

## なぜ測ったか

この表は 2026-05-13 の記事公開時から 4 locale に載っていたが、**出典が 1 本も無かった**。2026-08-05 の SEO Fix セッションで内容を検証したところ 2 箇所が実際に誤っていた。

| 属性 | 記事の旧記述 | 実測 |
|---|---|---|
| `width` / `height` | 「px 値は通るが `%` は除去されがち」 | **`width="50%"` はそのまま残る**。値による除去は起きない |
| `class` | 「無視される (GitHub のスタイルシートが固定なので効かない)」 | **除去される**。属性ごと消える |
| `style` | 「無視される」 | **除去される** |

「無視される」(属性は残るが適用されない) と「除去される」(属性ごと消える) は別の機構で、記事は同じ表の中で `<script>` / `on*` にだけ「除去」を使って書き分けていた。allowlist 方式では allowlist に無い属性はすべて消えるため、この書き分けは成立しない。

## 測定対象

GitHub 本番の Markdown レンダリングエンドポイント `POST https://api.github.com/markdown` (`mode: gfm`)。README / issue / PR 本文と同じパイプラインが返す HTML をそのまま読む。

`gjtorikian/html-pipeline` の `SanitizationFilter` allowlist を読む方法もあるが、それは「GitHub が使っているであろう実装」であって GitHub 本番の証明ではない。allowlist の読み取りだけを根拠に記事へ書くのは CLAUDE.md の数値根拠ルールで言う (3) 推定に当たるため、実レスポンスを一次データとして取っている。

## 成果物

| ファイル | 内容 |
|---|---|
| `fixtures/*.json` | 検証入力 12 件。`input` (Markdown)、`probeTag` (属性を見るタグ)、`id` を持つ |
| `measure.mjs` | 再現用スクリプト (`npm run measure`) |
| `results.json` | 入力・出力 HTML・属性ごとの判定 (`kept` / `removed` / `rewritten:<新しい値>`) |

## 実測結果

| 属性 | 判定 | 備考 |
|---|---|---|
| `colspan` / `rowspan` | 保持 | セル結合に使える組 |
| `align` (td / th) | 保持 | 列単位の配置を上書きできる |
| `valign` | 保持 | 記事の表には未掲載だった |
| `width` (`50%` / `120px`) | 保持 | **`%` でも px でも残る。値は検査されない** |
| `height` (`30`) | 保持 | 同上 |
| `id` | **書き換え** | `id="anchor-me"` → `id="user-content-anchor-me"`。属性は残るが接頭辞が付くため、書いたままの値ではアンカーリンクが張れない |
| `class` | 除去 | |
| `style` | 除去 | |
| `bgcolor` | 除去 | 記事の表には未掲載だった |
| `onclick` (`on*` ハンドラ) | 除去 | XSS 対策 |

`id` の書き換えは、記事が「アンカーリンクには使えない」と結論だけ書いていた部分の機構にあたる。理由は接頭辞の付与であって、属性が消えるからではない。

## 再現手順

```bash
gh auth status                                   # 認証済みであること
cd scripts/benchmarks/github-table-attributes
npm run measure                                  # results.json を上書き
```

依存パッケージは無い。`gh` CLI の認証だけを使う。

## 測定していないこと

Markdown API は 1 つのエンドポイントで、描画文脈 (README / issue / PR / コメント) を指定する引数を持たない。**文脈ごとに CSS が違う可能性は残るが、サニタイズ結果が文脈で変わることは本測定からは言えない**。記事でも文脈別の差には触れていない。
