Skip to content

refactor(ui): make popup HTML construction injection-safe by default #105

Description

@comnam90

Spun out of code review on #103 (item #5).

Context

renderMap() in layouts/index.html builds popup HTML via template-literal string concatenation of region fields:

```js
const popupHTML = `

${region.name}

...
${edition} · ${tier}
`;
```

Today the data is YAML, Zod-validated, and controlled by maintainers, so practical XSS risk is near zero. But the trust boundary is implicit — if the schema ever loosens (free-text `edition`, scraped fields, etc.) this code becomes injectable.

Proposed fix

Add a tiny escape helper and apply it to every interpolation in the popup builder.

```js
const esc = s => String(s).replace(/[&<>"']/g, c => (
{ '&':'&','<':'<','>':'>','"':'"',"'":''' }[c]
));
```

Keep the schema as the primary defense; make the rendering layer the secondary one.

Acceptance

  • All interpolated values in the popup card go through the escape helper
  • Existing UI tests still pass
  • Comment at top of the popup builder calls out the contract

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions