Skip to content

[high] fix: 7,650+ doc links (13.9%) point at anchors the renderer never creates - #1273

Open
elhoim wants to merge 1 commit into
MISP:mainfrom
elhoim:fix/mkdocs-anchor-slugify
Open

elhoim wants to merge 1 commit into
MISP:mainfrom
elhoim:fix/mkdocs-anchor-slugify

Conversation

@elhoim

@elhoim elhoim commented Aug 30, 2026

Copy link
Copy Markdown
Member

BLUF — 13.9% of galaxy doc links point at heading anchors the Markdown renderer never creates.

  • Problem — Documentation links clusters by an anchor built from a hand-rolled slugifier duplicated in tools/mkdocs/utils/helper.pyname_to_section() at line 12 and inline in cluster_transform_to_link() at line 50 — which strips only slashes and colons, while Python-Markdown's toc extension that actually assigns the heading ids strips all non-word characters.
  • Fix — Delegate both sites to markdown.extensions.toc.slugify, the same function that mints the ids, so links and headings cannot disagree.
  • Effect — The 7,788 of 56,131 values (13.9%) whose anchors do not exist today resolve to their real headings.

Problem

Every cluster renders as a ## {value} heading, and the documentation links to it with an anchor built by a hand-rolled slugifier — duplicated in two places, name_to_section() at helper.py:12 and inline in cluster_transform_to_link() at helper.py:50:

name.lower()
    .replace(" - ", placeholder)
    .replace(" ", "-")
    .replace("/", "")
    .replace(":", "")
    .replace(placeholder, "-")

Python-Markdown's toc extension — which is what actually assigns the heading ids — strips all non-word characters, not just / and :. So any value containing a comma, a period, a parenthesis, an ampersand and so on gets a link pointing at an anchor that does not exist on the page.

Measured across all 56,131 cluster values:

values: 56131 | mismatching anchors: 7788 (13.9%)

  punctuation the hand-rolled version does not strip     7058
  non-ASCII in the name                                   569
  other (whitespace/separator handling)                   161

The bulk of it is plain ASCII punctuation, nothing exotic:

'SKILL.md Prompt Injection - ATR-2026-00120'
    hand-rolled -> 'skill.md-prompt-injection-atr-2026-00120'
    rendered    -> 'skillmd-prompt-injection-atr-2026-00120'

'Skill Squatting / Typosquatting - ATR-2026-00124'
    hand-rolled -> 'skill-squatting--typosquatting-atr-2026-00124'
    rendered    -> 'skill-squatting-typosquatting-atr-2026-00124'

'Remote Code Execution via eval() and Dynamic Code Injection - ATR-2026-00110'
    hand-rolled -> '...-via-eval()-and-dynamic-code-injection-...'
    rendered    -> '...-via-eval-and-dynamic-code-injection-...'

Fix

Delegate to Python-Markdown's own markdown.extensions.toc.slugify — the function that generates the heading ids — so a link can never point at an anchor the renderer did not create. cluster_transform_to_link() now calls name_to_section() instead of carrying a second copy of the logic.

Markdown==3.8.1 is already pinned in tools/mkdocs/requirements.txt (mkdocs depends on it), so this adds no new dependency.

Verification

Against the real Markdown 3.8.1, over every cluster value:

values checked: 56131
anchors that do not match the rendered heading id: 0

Note

For non-ASCII names the shared function now produces what the renderer produces — e.g. 海莲花 - APT-C-00-apt-c-00. That is a correct link where there was a broken one, but it is not a readable anchor. If you would prefer CJK and Cyrillic names to keep their characters, adding a unicode slugify to mkdocs.yml:

markdown_extensions:
  - toc:
      slugify: !!python/object/apply:pymdownx.slugs.slugify {kwds: {case: lower}}

would fix that — and because both sides now share one function, the links would follow automatically. That changes existing URLs, so I have left it out of this PR.

🤖 Generated with Claude Code

Clusters render as "## {value}" headings and are linked with an anchor built
by a hand-rolled slugifier, duplicated in name_to_section() and inline in
cluster_transform_to_link(). It strips only "/" and ":", while
Python-Markdown's toc extension -- which actually assigns the heading ids --
strips every non-word character.

Across all 56,131 cluster values, 7,788 links (13.9%) target an anchor the
renderer never emits:

  punctuation the hand-rolled version does not strip   7058
  non-ASCII in the name                                 569
  other (whitespace/separator handling)                 161

e.g. 'SKILL.md Prompt Injection - ATR-2026-00120' was linked as
'skill.md-prompt-injection-...' but renders as 'skillmd-prompt-injection-...'.

Delegate to markdown.extensions.toc.slugify and have
cluster_transform_to_link() call name_to_section() rather than keep a second
copy. Markdown==3.8.1 is already pinned in requirements.txt, so no new
dependency.

Verified against Markdown 3.8.1: 0 of 56,131 anchors now mismatch.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HZGwPoa8MMfkhCw47rDLA4
@elhoim elhoim changed the title fix: 7,650+ doc links (13.9%) point at anchors the renderer never creates [high] fix: 7,650+ doc links (13.9%) point at anchors the renderer never creates Sep 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant