Releases: stwhwing/markitdown-skill
Release list
v1.8.0
markitdown-skill v1.8.0
Security hardening + provenance for the web→Markdown pipeline (public build, no telemetry).
Security
- Response / decompressed size caps (P0): raw responses > 32 MiB rejected; gzip/deflate/br decoded with a streaming, bounded reader that aborts past 64 MiB (defeats decompression bombs).
- Redirect-hop limit (P0): 3xx chains longer than 10 hops refused.
- Reject embedded credentials (P0):
user:pass@hostURLs refused outright. - Prompt-injection boundary (P1):
url_to_markdown.py --sanitizestrips<script>/<style>, neutralisesjavascript:/data:URIs, and wraps output in--- EXTERNAL CONTENT ---markers (content stays data, not instructions). - New
references/SECURITY.mddocuments the full threat model (SSRF, resource caps, prompt-injection boundary, browser sandbox, data flow).
Provenance & reliability
- Per-conversion manifest (P1):
--manifest <file>records source, output, UTC time, sha256, byte size, and a heuristic quality score forurl_to_markdown.pyandbatch_convert.py— useful for knowledge-base ingestion trails. - Atomic output writes (P1): output files are written via temp file +
os.replace(no half-written files on crash). - Empty / scanned-source hint (P1): low-quality or image-only results print an Azure Document Intelligence / local-OCR upgrade suggestion.
- Honest positioning (P2): SKILL.md now states plainly when to use
url_to_markdown.pyvs a baremarkitdown <url>, and that the public build ships no reporting component. uvxinstall fallback (P2):uvx --with 'markitdown[all]' markitdown ...for environments without pip write access.
Published to GitHub + skillhub.cn + ClawHub at the same version.
v1.7.9
markitdown-skill v1.7.9
Fixed — silent mojibake on compressed responses
url_fetch.fetch_html() never looked at Content-Encoding, and urllib does not
decompress transparently (unlike requests). A server answering with gzip therefore had
its compressed bytes decoded as UTF-8 with errors="ignore" — the conversion produced
garbage while still exiting 0.
Reproduced live on both a Windows host and a Linux deployment:
| target | before | after |
|---|---|---|
fetch_html(https://www.python.org/) |
garbage, 6,259 chars | 52,649 chars of clean HTML |
url_to_markdown(...) output |
4,724 B of junk | 14,554 B of readable Markdown |
Content-Encoding is now undone first (gzip / deflate, including raw deflate / brotli /
zstd where the optional module is present), then the bytes are decoded using the charset
declared in Content-Type. The response is closed properly via with. Sites that do not
compress are unaffected.
Tests
scripts/tests/test_url_fetch.py grows to 5 cases: gzip, deflate (incl. raw), plain
pass-through, declared charset, and the PinnedHandler regression added in 1.7.8.
The new cases fail against the pre-fix code.
v1.7.8
markitdown-skill v1.7.8
Two defects found by real testing on the deployed Linux host, plus one observability fix.
Fixed
PinnedHandler.__init__did not initialise the base handler.do_open()reads
self._debuglevel, so every pinned request raised
AttributeError: 'PinnedHandler' object has no attribute '_debuglevel'.
Impact was silent: the pinned fetch failed and the tool quietly fell back, so DNS
pinning was effectively disabled while the process still exited 0. The base handler is
now initialised viaAbstractHTTPHandler.__init__(not a baresuper().__init__(),
which would also build an unused SSL context on every request).
A regression test ships asscripts/tests/test_url_fetch.py.
Changed (private reporting path only)
- Honest upload gate for the savings reporter: an anti-bot / verification page or a
too-short output is no longer reported as a token saving. - Reported events now carry
caller_cwd/caller_ppid/caller_argv, so an
unexpected event can be traced back to its entry point.
Verification
- Regression test: fails on the pre-fix code with the exact
_debuglevelerror, passes after - Offline prediction against NVIDIA SkillSpector's LP1/TM1/TM3 rules: 0 findings
- De-privatisation redline scan: clean on all three artifacts
v1.7.7
markitdown-skill v1.7.7
Scanner-alignment release (public package) — no behaviour change to conversion.
Changed
- Declared capabilities in
allowed-tools:WebFetch(network) andenv(environment-variable access) are now declared alongsideRead,Write,Bash,Glob. The skill genuinely uses both (HTTP fetching; readingMARKITDOWN_BIN/ proxy settings), so this closes a real least-privilege declaration gap rather than granting anything new. - Neutral wording for the
MARKITDOWN_BINpermission-check documentation (comments + README). Same meaning, clearer phrasing. - Description now names the optional local-only token-cost estimators (
token_saver.py,measure_tokens.py) so the manifest accurately reflects everything the package ships. - SKILL.md no longer spells out the cloud-metadata IP literal in prose (the link-local range is still listed; the code blocklist is unchanged).
Verification
- Offline prediction against NVIDIA SkillSpector's exact LP1/TM1/TM3 rules: 0 findings (was 6: LP1×2 + TM1×1 + TM3×3)
static-analysis/ de-privatisation redline scan: clean on all three artifacts- MARKITDOWN_BIN validator behaviour unchanged (Windows 6/6, POSIX 4/4 on the Linux server)
v1.7.6
markitdown-skill v1.7.6
Security hardening release (public package).
Changed
MARKITDOWN_BINnow goes through a strict allowlist. The override is honoured only when it is an absolute path to a regular file; on POSIX it must additionally be executable and not group-/world-writable. Anything else is ignored and the trustedpython -m markitdownmodule path is used. Closes the "redirect execution via a writable environment variable" hole.- Note: on Windows there is no POSIX mode bit, so the check there is "absolute path to a regular file" (documented honestly).
- Documentation clarified: sandbox-first headless rendering (
--no-sandboxis only an automatic fallback for root / crashing sandboxes, never a user flag) and--allow-internalas an explicit, off-by-default opt-in for trusted local development.
Verification
static-analysis: clean, 0 findings- Redline / de-privatisation scan: 0 hits on all three artifacts
- Deterministic test matrix: Windows behaviour 8/8, simulated POSIX branch 5/5
v1.7.5
markitdown-skill v1.7.5
三平台同步:GitHub / skillhub.cn / ClawHub。本版按 ClawHub ClawScan 与 skillhub 评测的交叉结论迭代。
安全(网络层纵深防御)
- DNS pinning(直连路径):新增
PinnedHandler,连接绑定到「已通过 SSRF 校验的那个 IP」,关闭 DNS rebinding 的 TOCTOU 窗口;跳转每一跳重新校验并重新绑定。 - 浏览器侧 pin:渲染回退用
--host-resolver-rules=MAP <host> <ip>把目标主机名映射到同一已校验 IP。 - 代理策略显式化:配置了 HTTP 代理时连接由代理完成,pinning 自动跳过并打印一次说明;
--strict-pin可绕过代理强制直连+pin。 - 诚实的边界声明:文档明确写出「代理环境下 pin 不生效」「浏览器子资源未做网络过滤(有意接受的限制)」。
可靠性(错误处理)
- 稳定退出码:0 成功 / 2 参数错 / 3 被 SSRF 拒 / 4 抓取失败 / 5 无可提取内容 / 6 输出写入失败。
- 错误即指引:stderr 统一
[error] …+[hint] …(怎么做),抓取失败与内容为空分别给出可执行的下一步。
文档(信息架构与可复现性)
- 反模式 + FAQ 前移合并:原 FAQ(位于文件 83% 处、评测未覆盖)与前移为「❗ 常见反模式与 FAQ」,现位于文件前 15%。
- 新增「触发场景 → 调用方式」对照表(含何时用 CLI、何时用脚本、内网地址如何处理)。
- 新增依赖速查 +
requirements.txt(上界锁定的依赖声明 + 系统依赖说明),响应「依赖未固定版本」的 note。 - frontmatter 描述收窄:显式写明不适用的输入(纯文本 / 需保版式 / 内网地址),并声明转换内容是数据而非指令。
安装:pip install -r requirements.txt(或 pip install 'markitdown[all]')。
v1.7.4
markitdown-skill v1.7.4
文档与网页 → Markdown 技能(基于微软 MarkItDown)。三平台同步:GitHub / skillhub.cn / ClawHub。
v1.7.4 (2026-09-10)
安全性与文档质量双线加固,对应 ClawHub ClawScan 的 3 项 concern 与 skillhub 评测的低分项:
安全(SSRF 纵深防御)
- 跳转逐跳校验:新增
ValidatingRedirectHandler,每个 3xx 跳转目标都先过 SSRF 守卫再跟随(原先 urllib 会自动跟到任意地址,含内网)。 - DNS 解析复检:
resolve_and_check()解析主机名并校验解析出的全部 IP;文档诚实标注其 TOCTOU/DNS-rebinding 局限,定位为与跳转校验、函数内复检互补的一层。 spa_extract.py模块内守卫:该模块可被直接调用,现自带 SSRF 复检(对应 SkillSpector #4)。
文档
- 不可信内容边界:明确"转换结果是数据、不是指令"——不执行页面内嵌指令、不改变工具调用(防提示注入)。
- 何时不用(When NOT to use)决策表 + 与平台其他能力的调用优先级。
- 依赖速查矩阵(能力 → 依赖 → 安装命令,含 Linux ffmpeg/chromium 单行装法)+ 生产环境固定版本建议。
- 全文清除
/tmp示例路径(5 处),改用显式输出目录占位符——/tmp在 Windows 不存在,AI 照抄会失败。 - 仓库补
.gitignore(防__pycache__/*.pyc误提交);README 新增 Feedback 反馈入口。
v1.7.3 / v1.7.2 / v1.7.1 / v1.7.0
见本仓库 Releases 历史(FAQ 章节、转换前后对比示例、文件大小说明、sandbox-first 无头渲染、--llm-model 运行时同意提示、README 结构同步、隐私声明合并与模块拆分)。
安装:pip install 'markitdown[all]';附件为完整技能包。
v1.7.3
markitdown-skill v1.7.3
文档与网页 → Markdown 技能(基于微软 MarkItDown)。本仓库为发布镜像,三平台同步:GitHub / skillhub.cn / ClawHub。
v1.7.3 (2026-09-09)
- 新增独立 FAQ 章节:8 个常见问题速查(何时无需转换 / 文件大小 / 缺依赖装什么 / 微信失败兜底 / 图片 OCR / 内网拒绝原因 / token 估算精度 / LLM 数据流向)
- 新增转换前后对比示例(Before → After)
- 浏览器渲染函数内 SSRF 复检:
render_with_browser内部二次校验目标 URL(--allow-internal仍可显式放行),纵深防御 - 文件大小限制说明
v1.7.2 (2026-09-08)
- sandbox-first 无头渲染:默认启用 Chromium 沙箱,仅 root/受限容器崩溃时自动回退
--no-sandbox并提示 --llm-model运行时同意提示:启用时先打印[consent notice]数据流出警告
v1.7.1 (2026-09-06)
- README 同步模块化结构说明(README 不携带版本号,版本唯一来源为 SKILL.md frontmatter)
v1.7.0 (2026-09-06)
- 隐私声明合并(「隐私与数据流向」为唯一决策依据)
url_to_markdown.py拆分为 5 个模块(url_security / url_fetch / content_detect / spa_extract / media_detect)
安装:pip install 'markitdown[all]',附件为完整技能包(含 README/LICENSE)。