Skip to content

Conversation

@colinrotherham
Copy link
Contributor

This PR closes #4940 and fixes safe and escape filtered values in govukAttributes()

The previous fix in #4938 missed that JSON.stringify() in renderMacro() is what breaks instanceof checks

<div {{- govukAttributes({
  'data-text': 'Testing',
  'data-unsafe-text': 'Testing & more',
  'data-safe-text': 'Testing &amp; more' | safe,
  'data-escaped-text': 'Testing & more' | escape
}) }}>

We can now use the Nunjucks is escaped test instead of only is mapping

@colinrotherham
Copy link
Contributor Author

Worth a mention, some JavaScript-only syntax is creeping in to your Nunjucks

I've limited changes in this PR to only govuk/macros/attributes.njk but watch out for:

  • Strict equals, === versus is sameas(true)
  • Defined checks !== undefined versus is not undefined
  • Array methods [x, y, z].includes() versus in [x, y, z]

Depends how strict Nunjucks v4 ends up being

@colinrotherham colinrotherham changed the title Preserve already escaped attributes values to prevent double escaping Preserve already escaped attribute values to prevent double escaping Oct 23, 2025
@colinrotherham
Copy link
Contributor Author

The macro also didn't handle being called directly with a string made safe

{{- govukAttributes(' data-attribute="Testing &amp; more"' | safe) -}}

Sadly it passes the is mapping check but lacked is not escaped to prevent this:

    Expected: " data-attribute=\"Testing &amp; more\""
    Received: "  =\"\" d=\"\" a=\"\" t=\"\" a=\"\" -=\"\" a=\"\" t=\"\" t=\"\" r=\"\" i=\"\" b=\"\" u=\"\" t=\"\" e=\"\" ==\"\" &quot;=\"\" T=\"\" e=\"\" s=\"\" t=\"\" i=\"\" n=\"\" g=\"\"  =\"\" &amp;=\"\" a=\"\" m=\"\" p=\"\" ;=\"\"  =\"\" m=\"\" o=\"\" r=\"\" e=\"\" &quot;=\"\""

That's all fixed now too and tests updated

@owenatgov
Copy link
Contributor

@colinrotherham Would you be willing to change the target of this to support/5.x? If it's a hassle I'm happy for this to go through normal review and then backport it myself.

@colinrotherham colinrotherham changed the base branch from main to support/5.x November 12, 2025 10:40
@colinrotherham colinrotherham requested a review from a team as a code owner November 12, 2025 10:40
@colinrotherham colinrotherham force-pushed the attributes-double-escape branch from 28720bb to 5588006 Compare November 12, 2025 10:40
@colinrotherham
Copy link
Contributor Author

@owenatgov Done

Copy link
Contributor

@owenatgov owenatgov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code looks grand 👍🏻 Thanks for this @colinrotherham

One pithy thing is that this needs a fix changelog entry. After that I'll approve.

Finally this just needs a second review. I'll ping the other devs as reviewers on ths.

@colinrotherham colinrotherham changed the title Preserve already escaped attribute values to prevent double escaping Preserve already escaped attributes values to prevent double escaping Nov 12, 2025
@colinrotherham
Copy link
Contributor Author

Good job I know you, thanks @owenatgov

Changelog entry pushed

Copy link
Contributor

@domoscargin domoscargin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good to me!

@owenatgov owenatgov merged commit bd4d9b9 into alphagov:support/5.x Nov 13, 2025
45 checks passed
@domoscargin domoscargin added this to the v5.14 milestone Dec 3, 2025
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.

attributes values are encoded even if passed with the safe filter

3 participants