Summary
skills/minimax-pdf/scripts/cover.py interpolates user-controlled document tokens directly into generated cover HTML. Values such as title, subtitle, and similar metadata are inserted without HTML escaping, so plain text containing markup is rendered as real HTML instead of text. This can break generated covers and can execute active markup if the HTML is opened in a browser or converted by an HTML renderer that honors scripts/events.
Code path
skills/minimax-pdf/scripts/cover.py:83-89 builds the optional subtitle block with raw t['subtitle'].
skills/minimax-pdf/scripts/cover.py:142, 219, 353, 459, 567, 669, 822, 961, 1063, 1165, 1332, and 1494 insert raw t['title'] across cover patterns.
skills/minimax-pdf/scripts/cover.py:1532-1536 dispatches the selected pattern from render(tokens).
skills/minimax-pdf/scripts/cover.py:1548-1562 reads tokens.json and optional --subtitle before rendering the HTML file.
Steps to reproduce
Validation level: dynamic reproduction plus source-control-flow inspection.
import importlib.util
from pathlib import Path
def load_module(rel_path):
path = Path(rel_path)
spec = importlib.util.spec_from_file_location(path.stem, path)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
return module
palette = load_module("skills/minimax-pdf/scripts/palette.py")
cover = load_module("skills/minimax-pdf/scripts/cover.py")
payload = "<script>alert(1)</script>"
tokens = palette.build_tokens(title=payload, doc_type="academic", author=payload)
tokens["subtitle"] = payload
html = cover.render(tokens)
print(payload in html)
print(html[html.find(payload) - 60 : html.find(payload) + len(payload) + 60])
Observed output:
True
<div class="first-word"><script>alert(1)</script></div>
Expected behavior
Document metadata should be treated as text by default. If a title, subtitle, or author contains characters such as <, >, or &, the generated cover should contain escaped text such as <script>...</script>, not executable HTML.
Actual behavior
The generated cover HTML contains the raw payload. This turns text metadata into markup and may execute active content when the cover HTML is viewed or processed by an HTML renderer.
Existing coverage
I searched current issues and PRs for cover.py, cover.render, _pattern_*, title, subtitle, script, html escape, XSS, and minimax-pdf. I did not find an existing issue or PR that covers this root cause.
Suggested fix
Escape text-valued tokens before interpolation into HTML, for example with html.escape(..., quote=True). Keep CSS/color/font tokens validated separately instead of blindly escaping every token, because those values are used inside CSS declarations.
A small helper such as text_token(t, key) could make the pattern templates consistent and avoid missing one cover pattern.
Suggested tests
- Add a regression test that renders every cover pattern with a title like
<script>alert(1)</script> and asserts the raw payload is absent while the escaped text is present.
- Add a subtitle-specific test, because
--subtitle can override the token value at the CLI layer.
- Add a test for ordinary text containing
& and <2026> to ensure non-malicious markup-like titles are displayed literally.
Submitted with Codex.
Summary
skills/minimax-pdf/scripts/cover.pyinterpolates user-controlled document tokens directly into generated cover HTML. Values such astitle,subtitle, and similar metadata are inserted without HTML escaping, so plain text containing markup is rendered as real HTML instead of text. This can break generated covers and can execute active markup if the HTML is opened in a browser or converted by an HTML renderer that honors scripts/events.Code path
skills/minimax-pdf/scripts/cover.py:83-89builds the optional subtitle block with rawt['subtitle'].skills/minimax-pdf/scripts/cover.py:142,219,353,459,567,669,822,961,1063,1165,1332, and1494insert rawt['title']across cover patterns.skills/minimax-pdf/scripts/cover.py:1532-1536dispatches the selected pattern fromrender(tokens).skills/minimax-pdf/scripts/cover.py:1548-1562readstokens.jsonand optional--subtitlebefore rendering the HTML file.Steps to reproduce
Validation level: dynamic reproduction plus source-control-flow inspection.
Observed output:
Expected behavior
Document metadata should be treated as text by default. If a title, subtitle, or author contains characters such as
<,>, or&, the generated cover should contain escaped text such as<script>...</script>, not executable HTML.Actual behavior
The generated cover HTML contains the raw payload. This turns text metadata into markup and may execute active content when the cover HTML is viewed or processed by an HTML renderer.
Existing coverage
I searched current issues and PRs for
cover.py,cover.render,_pattern_*,title,subtitle,script,html escape,XSS, andminimax-pdf. I did not find an existing issue or PR that covers this root cause.Suggested fix
Escape text-valued tokens before interpolation into HTML, for example with
html.escape(..., quote=True). Keep CSS/color/font tokens validated separately instead of blindly escaping every token, because those values are used inside CSS declarations.A small helper such as
text_token(t, key)could make the pattern templates consistent and avoid missing one cover pattern.Suggested tests
<script>alert(1)</script>and asserts the raw payload is absent while the escaped text is present.--subtitlecan override the token value at the CLI layer.&and<2026>to ensure non-malicious markup-like titles are displayed literally.Submitted with Codex.