1

1. esc_attr()

Based on the official documentation, this is correct:

echo '<div id="', esc_attr( $prefix . '-box' . $id ), '">';

This is incorrect:

echo '<div id="', esc_attr( $prefix ), '-box', esc_attr( $id ), '">';

Why is the second way incorrect, I do not understand the potential risk?

Source: https://developer.wordpress.org/apis/security/escaping/#escaping-arbitrary-variable-within-html-attribute

A small example: What needs to be inside $dangerousString1 and/or $dangerousString2 to break something?

<?php 
$dangerousString1 = 'abc';
$dangerousString2 = 'xyz';

echo '<div id="', esc_attr( $dangerousString1 ), '-box', esc_attr( $dangerousString2 ), '">TEST</div>';
?>

2. esc_html()

Is this approach correct? I specifically meant this part: ... esc_html__('Setup and Help', 'my-plugin') . ' <i ...

add_submenu_page( 'xyz_settings', esc_html__('Setup and Help', 'my-plugin'), esc_html__('Setup and Help', 'my-plugin') . ' <i class="fa fa-info-circle" aria-hidden="true"></i>', 'manage_options', 'xyz_help', 'xyz_help_page' );

2 Answers 2

2

Escaping is all about eliminating the need for trust or "it should be an XYZ" and instead guaranteeing it by force that "it will always be an XYZ". It's like a cookie cutter, everything will be that shape at the end even if it's not cookie dough.

esc_attr

The official docs contain the answer:

When a variable is used as part of an attribute or url, it is always better to escape the whole string as that way a potential escape character just before the variable will be correctly escaped.

Escaping is all about context, so by concealing context from esc_attr you're reducing its effectiveness. Don't escape portions of an attribute, escape the entire attribute, and do it at the moment of output.

esc_attr is for escaping an attribute, the entire attribute. You can't use it to partially escape sub-sections of an attribute because that's not what it's intended for, and it would be a misuse.

This is for the same reason you cannot use esc_url on sub-sections of a URL, esc_url always outputs a full URL. Without the context of the full URL it's not possible to correctly escape it without potentially dangerous things leaking through, or malformed URLs that could be dangerous leaking out.

esc_html

esc_html guarantees that a string will not contain HTML tags, and it does this by escaping them so that they are printed out to the user rather than processed and executed by the browser.

Is this approach correct? I specifically meant this part: ... esc_html__('Setup and Help', 'my-plugin') . ' <i ...

Yes! You may find some people consider escaping language strings unnecessary or overzealous, but language files and filters can be used as an attack vector and you're protecting yourself by doing this.

If you know that string should never contain HTML, then escaping can provide some guarantees of that.

In General

Escaping is all about enforcing expectations. esc_html and esc_attr are intended for different purposes. Escaping isn't a magic thing you apply to stuff universally, it's ultra specific to the context and use, that's why we don't have a general escape function but instead have specific functions such as esc_html/esc_textarea/esc_attr/esc_url/wp_kses_post/strip_tags etc

"This variable contains a URL, and now that I've used esc_url it will be a URL even if you put something in there that isn't. The result might be garbled junk but that junk is a URL."

So don't pick and choose or apply partially. If you want to escape a string, escape the entire string. Partially escaping might seem prudent but it's a mistake and a way for things to leak through.

  • escape once

    double escaping is bad and carefully crafted content can use that to break through and expose malicious data. Be clear about which code is responsible for escaping, and make sure that code is also the code that prints it out

  • escape late

    Don't assign escaped values to variables, those variables can be modified and made unsafe after escaping, and it encourages accidental double escaping.

  • escape often

    Escape all the things that you can, and do it in full. Even if you thought that the partial escaping should be fine, why trust that? Guarantee and say with 100% certainty that it will be fine by escaping the entire thing as one unit.

    • also does it really make sense to litter your code with lots of tiny esc_attr calls in every attribute when 1 will do the job?
7
  • Ad esc_attr(): What does this mean "as that way a potential escape character just before the variable will be correctly escaped."? Can you please give an example? esc_html(): In my example I also escape partially, the <i> element is not escaped instead it is concatenated. Why is this partial escape ok?
    – JShinigami
    Nov 16, 2023 at 5:35
  • the usage with the <i> element is not using esc_attr, they are not equivalent. As for escape characters, this is a string that contains a quote: " \"\"", the slashes escape the " so that when you print it out it prints as "". But if you only escape parts of an attribute esc_attr does not know if there are slashes or not, so it can't do its job. Remember, esc_attr is for escaping an attribute, not parts or sub-sections of an attribute, it outputs a value that is safe to use as an attribute in a HTML tag. esc_html outputs a value that has no HTML, it's usage/purpose is different.
    – Tom J Nowell
    Nov 16, 2023 at 10:54
  • think of it this way, would a cookie cutter that only cut parts of the shape out guarantee the end result? Also consider this: <a href="https://<?php echo esc_url( $domain ); ?>/test">, that code would result in a broken URL. esc_attr does not make content safe to put in an attribute, it makes a whole attribute safe for output, the attribute in its entirety is what it's escaping, not sub-sections or portions, that is its purpose. esc_html is for ensuring that all HTML in a string is escaped and doesn't show up as tags. The two functions have different functions and usages
    – Tom J Nowell
    Nov 16, 2023 at 10:58
  • Thank you for your answers. I still do not understand how the second esc_attr() example can be broken? What needs to be inside $dangerousString1 and/or $dangerousString2 to break something? I have edited the original question and added an example.
    – JShinigami
    Nov 17, 2023 at 9:39
  • if you need to use escape characters to print values such as & requires &amp; then what if you put the escape character at the end of the variable so that it changes the meaning of something outside the variable? Now escaping has broken. The value would have to be specially crafted for the specific piece of code to be usable maliciously, but that's not too difficult to do. Likewise you can take something dangerous and split it apart, put one piece in the first variable and the second in the next so that neither parts are suspect enough to be escaped but when combined cause problems.
    – Tom J Nowell
    Nov 17, 2023 at 12:30
0

Based on ChatGPT: So, in summary, while both versions are secure in terms of preventing XSS attacks, the WordPress documentation recommends the second version for better maintainability and to reduce the chance of missing necessary escaping for each part of the string.

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.