When attribute text contains a single quote, like "It's a nice day" that single quote when rendered is escaped to "It's a nice day". Why is that happening and can it be prevented? Is twig doing that escaping?


it says:

"The attribute keys and values are automatically escaped for output with Html::escape()."

and also:

"The attribute values are considered plain text and are treated as such. If a safe HTML string is detected, it is converted to plain text with PlainTextOutput::renderFromHtml() before being escaped."

Neither of those should do that conversion.

  • *Why is that happening and can it be prevented? * Because it takes only 2 seconds to see the massive security issue: <a class="It's a nice day"... vs. <a class='It's no longer a nice day but a security issue by onclick='evilCode()'... Do NOT prevent that.
    – Hudri
    Aug 20, 2021 at 14:49
  • 6
    Basically in 99 of 100 cases the answer to Why is it escaped? is Because someone found a security issue ;-)
    – Hudri
    Aug 20, 2021 at 14:55
  • 1
    I want a t-shirt with that on @Hudri, great phrase!
    – Clive
    Aug 20, 2021 at 15:05

1 Answer 1


Attributes built via the Attribute class are escaped.

The Attribute::__toString() code is the following one.

$return = '';

/** @var \Drupal\Core\Template\AttributeValueBase $value */
foreach ($this->storage as $name => $value) {
  $rendered = $value->render();
  if ($rendered) {
    $return .= ' ' . $rendered;
return $return;

In a class that extend AttributeValueBase, for example AttributeString, render() contains the following code.

value = (string) $this;
if (isset($this->value) && static::RENDER_EMPTY_ATTRIBUTE || !empty($value)) {
  return Html::escape($this->name) . '="' . $value . '"';

AttributeString::__toString() contains the following code.

return Html::escape($this->value);

Html::escape() is called for the attribute name and its value. That's why an attribute built using code similar to the following one single quotes inside the attribute name and value are escaped.

$attributes = new Attribute(array());
$attributes['id'] = 'socks';
$attributes['style'] = 'background-color:white';
echo '<cat ' . $attributes . '>';

AttributeArray::__toString() uses the following code.

// Filter out any empty values before printing.
$this->value = array_unique(array_filter($this->value));
return Html::escape(implode(' ', $this->value));

This means that for an attribute built using code similar to the following one, the attribute value is escaped.

$attributes = new Attribute();
$attributes['class'] = array();
$attributes['class'][] = 'cat';

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.