# 網站留言區的 Markdown 連結，預設設定居然會留下 javascript？CommonMark 實測

- 網址：https://blog.valenvan.uk/posts/thephpleague-commonmark.html
- 發布日期：2026-11-02
- 測試設備：Mac mini M4 Pro（12 核、64GB）
- 專案：thephpleague/commonmark（https://github.com/thephpleague/commonmark），BSD-3-Clause 授權
- 測試版本：原始碼 3164fa3d（2.10.x-dev）
- 實測影片：https://www.youtube.com/watch?v=PnxYQ78WYaI

## 重點摘要

- CommonMark 預設的 GFM 轉換器，會把留言裡的 javascript: 連結原樣留在輸出的 HTML 裡（實測 1 個連結留著）。
- 同一份留言裡的 script 標籤，預設就被轉成純文字，不會原樣保留。
- 設定 html_input=strip 與 allow_unsafe_links=false 後，連結只剩文字、script 整個移除，4 個表格格子與 2 個勾選框照常輸出。
- 它是 PHP 套件，需要會寫程式；本次只測一份自製留言，不代表整個網站安全。
- **結論：** 網站讓人輸入 Markdown 時，這兩個選項值得打開。
- **適合：** 自己架網站、會寫 PHP、開放訪客用 Markdown 留言或投稿的人
- **不適合：** 不會寫程式的人，或想要一鍵就保證整站安全的人

| 實測項目 | 結果 |
|---|---|
| 安裝（含 7 個相依） | 約 14 秒 |
| 預設：javascript 連結 | 留著 |
| 預設：script 標籤 | 轉成純文字 |
| 安全設定：javascript 連結 | 只剩文字 |
| 安全設定：script 標籤 | 移除 |
| 安全設定：表格格子／勾選框 | 4 個／2 個 |

假設你自己架了一個小網站，開放訪客用 Markdown 留言。某天有人留了一個「領取優惠」的連結，看起來沒什麼問題。但這個連結的網址不是 https，而是 `javascript:alert(1)`——訪客一點，那段程式就在你的網站頁面上執行。

這種事要怎麼在「把 Markdown 轉成網頁」這一步就擋掉？我拿 PHP 套件 [CommonMark](https://github.com/thephpleague/commonmark) 實際測了一次。測試設備：Mac mini M4 Pro（12 核、64GB），Linux arm64、PHP 8.2.35。

## 下載

CommonMark 是 PHP 套件，用 Composer 安裝（官方套件名 `league/commonmark`）。本次測的是原始碼 `3164fa3d`（BSD-3-Clause）。我在乾淨環境裝好 php-cli、php-mbstring、composer，再以路徑載入原始碼，相依套件共 7 個，整個安裝約 14 秒。

```bash
apt-get install -y php-cli php-mbstring composer
composer require league/commonmark
```

## 測試檔

自製一份留言 `comment.md`：標題、兩列表格、兩個勾選框、一個 javascript 連結、一個 script 標籤。

```markdown
# 本週工作

| 工作 | 狀態 |
| --- | --- |
| 寫報告 | 完成 |
| 整理照片 | 進行中 |

- [x] 寄出報告
- [ ] 整理照片

[領取優惠](javascript:alert(1))

<script>alert('demo')</script>
```

## 跑起來

轉換程式只差一行設定：預設，或是加上兩個選項。

```php
use League\CommonMark\GithubFlavoredMarkdownConverter;

// 預設
$c = new GithubFlavoredMarkdownConverter();
// 安全設定
$c = new GithubFlavoredMarkdownConverter([
    'html_input' => 'strip',
    'allow_unsafe_links' => false,
]);
echo $c->convert(file_get_contents('comment.md'));
```

| 項目 | 預設 | 安全設定 |
| --- | --- | --- |
| javascript 連結 | `<a href="javascript:alert(1)">領取優惠</a>`（留著） | `<a>領取優惠</a>`（只剩文字） |
| script 標籤 | 轉成純文字 `&lt;script>` | 整個移除 |
| 表格格子 | — | 4 個 |
| 勾選框 | — | 2 個 |

![預設設定的輸出](https://blog.valenvan.uk/img/thephpleague-commonmark-article_1.png)

![安全設定的輸出](https://blog.valenvan.uk/img/thephpleague-commonmark-article_2.png)

## 常見問題

- **預設會原樣保留 script 嗎？** 不會。GFM 轉換器預設就把 script 轉成純文字；真正留下的是 javascript 連結。
- **直接 `composer install` 失敗？** 我在乾淨環境對原始碼庫直接安裝時，因為開發相依要求 `ext-curl` 而失敗；改成在另一個目錄以路徑載入核心，只裝 7 個執行期相依就成功。
- **這樣網站就安全了嗎？** 不能這樣說。我只測了這一份自製留言，沒測其他危險網址格式、其他標籤或完整網站防護。

## 結論

只要網站讓別人輸入 Markdown，這兩個選項就值得打開；表格與勾選框不受影響。但它是 PHP 套件，需要會寫程式才能用，不是給一般人按按鈕的工具。

- 專案：https://github.com/thephpleague/commonmark
- 授權：BSD-3-Clause
