Repository navigation
Conversation
paulbalandan
requested changes
Nov 13, 2026
michalsn
requested changes
Nov 13, 2026
Comment on lines
+560
to
+568
| if (! function_exists('_esc_attr')) { | ||
| /** | ||
| * Escapes a value for use inside a double-quoted HTML attribute. | ||
| */ | ||
| function _esc_attr(string $value): string | ||
| { | ||
| return htmlspecialchars($value, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); | ||
| } | ||
| } |
Member
There was a problem hiding this comment.
What is the reason for creating this function and not using esc($value, 'html')?
…a tags The `video()`, `audio()`, `_media()`, `source()`, `track()`, `object()`, `param()` and `embed()` helpers concatenated their arguments straight into double-quoted HTML attributes. A value containing a double quote - a `src`, `type`, `kind`, `label` or `name` that comes from a database column or a request parameter, for instance - could therefore close the attribute and inject arbitrary ones, such as `onerror`, into the generated markup. Attribute values now go through a new `_esc_attr()` helper that applies `htmlspecialchars()` with `ENT_QUOTES | ENT_SUBSTITUTE`, so both quote styles, `<`, `>` and `&` are encoded while ordinary URLs stay readable. `ENT_SUBSTITUTE` keeps invalid UTF-8 from turning the whole value into an empty string. The `$unsupportedMessage` fallback text of `video()`, `audio()` and `_media()` was emitted verbatim as well, so markup passed as the fallback message was rendered as HTML. It is now escaped with `esc($message, 'html')` and displayed as plain text. Regression tests cover each affected helper, including the alternative `ENT_SUBSTITUTE` behaviour.
gr8man
force-pushed
the
fix/html-helper-media-escaping
branch
from
November 13, 2026 20:45
675995f to
3db4058
Compare
Comment on lines
+403
to
+404
| > [!NOTE] | ||
| > Attribute values generated by media helper functions (`src`, `type`, `kind`, `srclang`, `label`, `name`, `value`, `data`) are automatically escaped. The `$unsupportedMessage` parameter in `video()` and `audio()` accepts raw HTML (such as fallback links). |
Member
There was a problem hiding this comment.
This will not render correctly on MkDocs. Please use the note admonition syntax instead set by contributing/documentation.md.
GitHub-only alert `> [!NOTE]` does not render in MkDocs; use the admonition syntax from contributing/documentation.md, and document that `$unsupportedMessage`, `$attributes`, `$tracks` and `$params` are inserted as raw HTML.
Cover `&` encoding through `video()` and through `video()` -> `source()` -> `_media()`, so a missing or a duplicated `esc()` fails the test.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
The
video(),audio(),_media(),source(),track(),object(),param()andembed()helpers concatenated their arguments directly intodouble-quoted HTML attributes. Any value containing a double quote closed
the attribute it was placed in, so caller-controlled data - a
src,type,kind,label,srclang,nameorvaluecoming from a database columnor a request parameter - could inject arbitrary attributes such as
onerrorinto the generated tag.
Attribute values now go through the existing
esc($value, 'html')helper,which applies
htmlspecialchars()withENT_QUOTES | ENT_SUBSTITUTE. Bothquote styles,
<,>and&are encoded while ordinary URLs stayreadable, and invalid UTF-8 is substituted instead of emptying the value.
Values are escaped exactly once: the array branch of
video()/audio()reaches
source(), which escapes its own arguments before_media()concatenates them.
The
$unsupportedMessage,$attributes,$tracksand$paramsparametersare intentionally left as raw HTML.
$unsupportedMessagetherefore keepssupporting fallback markup such as download links, and callers are
responsible for not passing unescaped user input in these parameters. The
user guide now documents this behaviour with a MkDocs note.
Output for input without special characters is unchanged, which the
existing tests assert. Regression tests cover every affected helper,
including single escaping of
&.Checklist: