Cover HTML renderer inserts raw document metadata as markup
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 4k
- Forks
- 453
- Avg merge
- 12h 30m
- Merged PRs (30d)
- 46
Description
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-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.
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
--subtitlecan 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.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in skills/minimax-pdf/scripts/cover.py, especially the subtitle block at lines 83-89, the listed title interpolations, and render(tokens). Reproduce the issue with the provided script, then inspect every cover pattern for text-valued metadata. Done means title and subtitle markup-like text is escaped in all patterns, CSS-related tokens remain separately validated, and regression tests cover titles, subtitles, ampersands, and every pattern.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- security
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 72/100