Skip to content

General: Prevent percent signs in tooltip button markup from being parsed by sprintf() - #13199

Closed
ekamran wants to merge 6 commits into
WordPress:trunkfrom
ekamran:fix/65914-tooltip-button-format-string
Closed

ekamran wants to merge 6 commits into
WordPress:trunkfrom
ekamran:fix/65914-tooltip-button-format-string

Conversation

@ekamran

@ekamran ekamran commented Aug 20, 2026

Copy link
Copy Markdown

Trac ticket: https://core.trac.wordpress.org/ticket/65914

This PR fixes a regression in wp_get_tooltip() and wp_get_toggletip() where custom button markup passed via the button argument is concatenated into a sprintf() format string.

Because of that, literal percent signs in valid button or anchor markup can be treated as format specifiers. This can cause fatal errors or silently corrupt output, for example percent-encoded URLs or button text like 100% done.

The fix resolves the tooltip-supported placeholders in the button markup first, then passes the resulting button HTML to sprintf() as a value instead of as part of the format string.

Testing:

  • npm run test:php -- --group tooltip
  • composer lint:errors -- src/wp-includes/general-template.php tests/phpunit/tests/general/wpGetTooltip.php

Results:

  • Tooltip tests passed: 16 tests, 45 assertions.
  • PHPCS errors check passed for both touched files.

@github-actions

github-actions Bot commented Aug 20, 2026 •

Copy link
Copy Markdown

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

Core Committers: Use this line as a base for the props when committing in SVN:

Props ekamran, joedolson.

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

@github-actions

Copy link
Copy Markdown

Test using WordPress Playground

The changes in this pull request can previewed and tested using a WordPress Playground instance.

WordPress Playground is an experimental project that creates a full WordPress instance entirely within the browser.

Some things to be aware of

  • All changes will be lost when closing a tab with a Playground instance.
  • All changes will be lost when refreshing the page.
  • A fresh instance is created each time the link below is clicked.
  • Every time this pull request is updated, a new ZIP file containing all changes is created. If changes are not reflected in the Playground instance,
    it's possible that the most recent build failed, or has not completed. Check the list of workflow runs to be sure.

For more details about these limitations and more, check out the Limitations page in the WordPress Playground documentation.

Test this pull request with WordPress Playground.

@ekamran
ekamran force-pushed the fix/65914-tooltip-button-format-string branch from 7a4779c to 7735a48 Compare August 20, 2026 14:26
`wp_get_tooltip()` and `wp_get_toggletip()` concatenated caller-supplied
button markup into a `sprintf()` format string, so literal percent signs
in valid markup were read as conversion specifications.

This caused fatal errors or silently corrupted output, including
percent-encoded URLs.

Build the generated button with its final label, icon, and popover
target rather than with placeholders, then pass the button markup to
`sprintf()` as a value. Caller-supplied button markup is no longer
scanned or substituted.

See #65914.

@joedolson joedolson left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

A couple changes to how I think this can be best handled.

Comment thread src/wp-includes/general-template.php Outdated
Comment thread tests/phpunit/tests/general/wpGetTooltip.php Outdated
@adamsilverstein
adamsilverstein self-requested a review September 4, 2026 14:22
ekamran and others added 4 commits September 9, 2026 20:01
The generated default button is now a plain skeleton, and every dynamic
attribute is added in the single tag processor pass that already sets
the ARIA attributes: the accessible name is only added when the markup
does not already carry one, the toggle class and popover wiring are
applied to every accepted button, and the dashicon span is only filled
in for the generated button. This removes the string concatenation and
lets the processor handle all attribute escaping.

Also renames a test ID so it does not point at a specific plugin, and
adds a test pinning that a custom button without an accessible name
gains one while a caller supplied aria-label is never overwritten.

@joedolson joedolson left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

With these changes and a couple additional comment changes, I think this is good to go.

@ekamran

ekamran commented Sep 9, 2026

Copy link
Copy Markdown
Author

Thank you for the approval and the doc cleanup. While reading your doc commit I noticed the same wording also sits in the wp_get_tooltip() and wp_get_toggletip() docblocks, both still say "Default standard button HTML". Since the default is now an empty string, should I push the same small fix to both? Happy to do it right away if you think it is worth it, or leave it to you.

@joedolson

Copy link
Copy Markdown
Contributor

Good catch! Yes, please do update those, as well.

@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown

A commit was made that fixes the Trac ticket referenced in the description of this pull request.

SVN changeset: 63566
GitHub commit: 126a9ea

This PR will be closed, but please confirm the accuracy of this and reopen if there is more work to be done.

@github-actions github-actions Bot closed this Sep 9, 2026
@ekamran
ekamran deleted the fix/65914-tooltip-button-format-string branch October 6, 2026 15:47
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.

2 participants