You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Found while spot-checking the adversarial fixture run during review of #34. Pre-existing on main, not a regression from that PR — filing separately so it doesn't creep into its scope, same as #29 was handled for #28.
What happens
internal/render/markdown wraps several user-controlled strings in single-backtick code spans. A backtick inside the value closes the span early, and whatever follows lands in the document as live Markdown/HTML rather than as literal text.
Affected fields, all confirmed:
entities.*.attributes[].name
entities.*.attributes[].type
entities.*.actions[] (the name)
entities.*.relationships[].role
Entity, enum and glossary keys are safe — the schema constrains them to ^[A-Z][A-Za-z0-9]+$, which excludes backticks. The fields above are unconstrained strings.
Repro
kind: DomainModelversion: v1entities:
Ticket:
definition: A parking ticket.attributes:
- name: "a ` <img src=q onerror=alert(1)> `"type: string
The code span closes at the second backtick and the <img> is emitted raw. Lint passes at every severity.
Why it's worth fixing
Correctness first. A model that legitimately documents shell or Markdown syntax — an attribute type containing a backtick — renders wrong. The renderer does not faithfully represent legal input, independent of any attacker.
Mild review asymmetry. Someone with commit access could already edit the generated .md directly, so this is not a privilege boundary. What it changes is where the payload appears in a diff: a weird-looking name in a YAML file, plus a regenerated golden that reviewers habitually skim, rather than obvious HTML in a reviewed .md.
It becomes a trust boundary when vendoring lands. ADR-0010's slice 2 vendors models from repositories this one does not control and renders them into local docs. At that point the author of the string needs commit access to their repo, not yours, and your CI renders it into your site. That is the deadline: this should be fixed before vendored third-party models ship.
Not part of this issue
Prose fields pass Markdown through.definition, description and similar emit raw HTML with no backtick needed. That appears intentional — they are prose in a Markdown document and an author may want emphasis — so it is not filed here. Worth confirming it is deliberate.
The branch for #34 added a codeSpan helper that fences past backtick runs, plus linkTarget percent-encoding, to fix the same class in import paths. Applying that helper at these call sites is likely most of the fix. Expect goldens to churn.
Found while spot-checking the adversarial fixture run during review of #34. Pre-existing on
main, not a regression from that PR — filing separately so it doesn't creep into its scope, same as #29 was handled for #28.What happens
internal/render/markdownwraps several user-controlled strings in single-backtick code spans. A backtick inside the value closes the span early, and whatever follows lands in the document as live Markdown/HTML rather than as literal text.Affected fields, all confirmed:
entities.*.attributes[].nameentities.*.attributes[].typeentities.*.actions[](the name)entities.*.relationships[].roleEntity, enum and glossary keys are safe — the schema constrains them to
^[A-Z][A-Za-z0-9]+$, which excludes backticks. The fields above are unconstrained strings.Repro
The code span closes at the second backtick and the
<img>is emitted raw. Lint passes at every severity.Why it's worth fixing
Correctness first. A model that legitimately documents shell or Markdown syntax — an attribute type containing a backtick — renders wrong. The renderer does not faithfully represent legal input, independent of any attacker.
Mild review asymmetry. Someone with commit access could already edit the generated
.mddirectly, so this is not a privilege boundary. What it changes is where the payload appears in a diff: a weird-looking name in a YAML file, plus a regenerated golden that reviewers habitually skim, rather than obvious HTML in a reviewed.md.It becomes a trust boundary when vendoring lands. ADR-0010's slice 2 vendors models from repositories this one does not control and renders them into local docs. At that point the author of the string needs commit access to their repo, not yours, and your CI renders it into your site. That is the deadline: this should be fixed before vendored third-party models ship.
Not part of this issue
definition,descriptionand similar emit raw HTML with no backtick needed. That appears intentional — they are prose in a Markdown document and an author may want emphasis — so it is not filed here. Worth confirming it is deliberate.role, the backtick is stripped by mermaid'ssanitizebut<b>passes into the diagram block untouched. Sibling problem, different renderer, already tracked.Note for whoever picks this up
The branch for #34 added a
codeSpanhelper that fences past backtick runs, pluslinkTargetpercent-encoding, to fix the same class in import paths. Applying that helper at these call sites is likely most of the fix. Expect goldens to churn.🤖 Filed by Claude Code