From cc1022e0b4f1d0872db5e56c12d4e6f02d0ee952 Mon Sep 17 00:00:00 2001 From: jrfnl Date: Tue, 20 Apr 2021 15:21:46 +0200 Subject: [PATCH 1/7] ProperEscapingFunction: fix overreach As part of the changes made in 624, the `T_COMMA` token was added to the list of tokens to skip over to allow for `echo` statements with multiple arguments passed as a coma-delimited list. As a side-effect, this caused the sniff to also examine `[s]printf()`-like function calls where the first parameter is a text string, while the second is often a variable within a call to one of the escaping functions. The current change fixes this by only adding the `T_COMMA` token to the "ignore when looking for the previous token"-list when in an `echo` statement. Includes unit test. Fixes 667 Additional notes: * I've run the sniff over WP Core to verify the fix and have verified that all 23 violations being throw up are correctly detected violations. * If it would be considered a good idea to also examine, `[s]printf()`-like function calls for this sniff for proper escaping, I suggest opening a separate, new feature request as that change would need significantly different and quite complex logic and does not fall within the scope of this bug fix. --- .../Sniffs/Security/ProperEscapingFunctionSniff.php | 9 +++++++-- .../Tests/Security/ProperEscapingFunctionUnitTest.inc | 3 +++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/WordPressVIPMinimum/Sniffs/Security/ProperEscapingFunctionSniff.php b/WordPressVIPMinimum/Sniffs/Security/ProperEscapingFunctionSniff.php index 9db2983e..7c2db497 100644 --- a/WordPressVIPMinimum/Sniffs/Security/ProperEscapingFunctionSniff.php +++ b/WordPressVIPMinimum/Sniffs/Security/ProperEscapingFunctionSniff.php @@ -46,7 +46,6 @@ class ProperEscapingFunctionSniff extends Sniff { T_OPEN_TAG => T_OPEN_TAG, T_OPEN_TAG_WITH_ECHO => T_OPEN_TAG_WITH_ECHO, T_STRING_CONCAT => T_STRING_CONCAT, - T_COMMA => T_COMMA, T_NS_SEPARATOR => T_NS_SEPARATOR, ]; @@ -107,7 +106,13 @@ public function process_token( $stackPtr ) { return; } - $html = $this->phpcsFile->findPrevious( $this->echo_or_concat_tokens, $stackPtr - 1, null, true ); + $ignore = $this->echo_or_concat_tokens; + $start_of_statement = $this->phpcsFile->findStartOfStatement( $stackPtr, T_COMMA ); + if ( $this->tokens[ $start_of_statement ]['code'] === T_ECHO ) { + $ignore[ T_COMMA ] = T_COMMA; + } + + $html = $this->phpcsFile->findPrevious( $ignore, $stackPtr - 1, null, true ); // Use $textStringTokens b/c heredoc and nowdoc tokens will never be encountered in this context anyways.. if ( $html === false || isset( Tokens::$textStringTokens[ $this->tokens[ $html ]['code'] ] ) === false ) { diff --git a/WordPressVIPMinimum/Tests/Security/ProperEscapingFunctionUnitTest.inc b/WordPressVIPMinimum/Tests/Security/ProperEscapingFunctionUnitTest.inc index a0ff39cc..bd5523d7 100644 --- a/WordPressVIPMinimum/Tests/Security/ProperEscapingFunctionUnitTest.inc +++ b/WordPressVIPMinimum/Tests/Security/ProperEscapingFunctionUnitTest.inc @@ -82,3 +82,6 @@ echo ''; // Error. echo ''; // Error. echo 'data-param-url="' . Esc_HTML::static_method( $share_url ) . '"'; // OK. + +// Not a target for this sniff (yet). +printf( '', esc_attr( $content ) ); // OK. From 208dda6afe4d638a99d9c681160d97b4a66c581d Mon Sep 17 00:00:00 2001 From: Rebecca Hum <16962021+rebeccahum@users.noreply.github.com> Date: Wed, 21 Apr 2021 14:56:03 -0600 Subject: [PATCH 2/7] Docs: Add version compare for bugs to checklist --- .github/ISSUE_TEMPLATE/release-template.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/release-template.md b/.github/ISSUE_TEMPLATE/release-template.md index 563f2d2e..026b6704 100644 --- a/.github/ISSUE_TEMPLATE/release-template.md +++ b/.github/ISSUE_TEMPLATE/release-template.md @@ -1,7 +1,7 @@ --- name: Release template about: Internally used for new releases -title: Release 2.x.y +title: Release x.y.z labels: 'Type: Maintenance' assignees: GaryJones, rebeccahum @@ -13,6 +13,7 @@ assignees: GaryJones, rebeccahum PR for tracking changes for the X.Y.Z release. Target release date: DOW DD MMMM YYYY. +- [ ] Scan WordPress (or just wp-admin folder) with prior version and compare results against new release for potential new bugs. - [ ] Add change log for this release: PR #XXX - [ ] Double-check whether any dependencies need bumping. - [ ] Merge this PR. From 7f77f90030c8e52b7345d342b03fa062e255b547 Mon Sep 17 00:00:00 2001 From: jrfnl Date: Tue, 20 Apr 2021 18:38:45 +0200 Subject: [PATCH 3/7] ProperEscapingFunction: improve "action" match precision In VIPCS 2.2.0, checking for the use of `esc_url()` for "action" HTML attributes was introduced in PR 575 in response to issue 554. As it is not inconceivable that "action" is used as a suffix for custom HTML attributes - like "data-action"- for which the value does not necessarily has to be a URL, the check for the "action" HTML attribute should make sure it is the complete attribute name and not used as a suffix for a custom attribute name. This change contains a minor refactor of the code which examines the content of the previous text string. Instead of looping over the various lists and doing a `substr()` on the same content 25 times, it will now use a regular expression to gather the necessary information to throw the right errors in one go. Includes unit tests. Fixes 669 Note: This PR removes two `private` properties which were introduced in 624/VIPCS 2.3.0 and two `public` methods. The removal of the properties is safe. The removal of the `public` methods could be considered a BC-break as these methods were `public`, though they never should have been. If so preferred, the `public` methods could be deprecated instead and remain in the code base as dead code/emptied out methods until the next major release upon which they could be removed. --- .../Security/ProperEscapingFunctionSniff.php | 78 ++++--------------- .../ProperEscapingFunctionUnitTest.inc | 6 +- 2 files changed, 16 insertions(+), 68 deletions(-) diff --git a/WordPressVIPMinimum/Sniffs/Security/ProperEscapingFunctionSniff.php b/WordPressVIPMinimum/Sniffs/Security/ProperEscapingFunctionSniff.php index 7c2db497..ae1d6725 100644 --- a/WordPressVIPMinimum/Sniffs/Security/ProperEscapingFunctionSniff.php +++ b/WordPressVIPMinimum/Sniffs/Security/ProperEscapingFunctionSniff.php @@ -18,6 +18,13 @@ */ class ProperEscapingFunctionSniff extends Sniff { + /** + * Regular expression to match the end of HTML attributes. + * + * @var string + */ + const ATTR_END_REGEX = '`(?href|src|url|\s+action)?=(?:(?:\\\\)?["\'])?$`i'; + /** * List of escaping functions which are being tested. * @@ -49,31 +56,6 @@ class ProperEscapingFunctionSniff extends Sniff { T_NS_SEPARATOR => T_NS_SEPARATOR, ]; - /** - * List of attributes associated with url outputs. - * - * @var array - */ - private $url_attrs = [ - 'href', - 'src', - 'url', - 'action', - ]; - - /** - * List of syntaxes for inside attribute detection. - * - * @var array - */ - private $attr_endings = [ - '=', - '="', - "='", - "=\\'", - '=\\"', - ]; - /** * Returns an array of tokens this test wants to listen for. * @@ -134,57 +116,23 @@ public function process_token( $stackPtr ) { return; } - if ( $escaping_type !== 'url' && $this->attr_expects_url( $content ) ) { + if ( preg_match( self::ATTR_END_REGEX, $content, $matches ) !== 1 ) { + return; + } + + if ( $escaping_type !== 'url' && empty( $matches['attrname'] ) === false ) { $message = 'Wrong escaping function. href, src, and action attributes should be escaped by `esc_url()`, not by `%s()`.'; $this->phpcsFile->addError( $message, $stackPtr, 'hrefSrcEscUrl', $data ); return; } - if ( $escaping_type === 'html' && $this->is_html_attr( $content ) ) { + if ( $escaping_type === 'html' ) { $message = 'Wrong escaping function. HTML attributes should be escaped by `esc_attr()`, not by `%s()`.'; $this->phpcsFile->addError( $message, $stackPtr, 'htmlAttrNotByEscHTML', $data ); return; } } - /** - * Tests whether provided string ends with open attribute which expects a URL value. - * - * @param string $content Haystack in which we look for an open attribute which exects a URL value. - * - * @return bool True if string ends with open attribute which expects a URL value. - */ - public function attr_expects_url( $content ) { - $attr_expects_url = false; - foreach ( $this->url_attrs as $attr ) { - foreach ( $this->attr_endings as $ending ) { - if ( $this->endswith( $content, $attr . $ending ) === true ) { - $attr_expects_url = true; - break; - } - } - } - return $attr_expects_url; - } - - /** - * Tests whether provided string ends with open HMTL attribute. - * - * @param string $content Haystack in which we look for open HTML attribute. - * - * @return bool True if string ends with open HTML attribute. - */ - public function is_html_attr( $content ) { - $is_html_attr = false; - foreach ( $this->attr_endings as $ending ) { - if ( $this->endswith( $content, $ending ) === true ) { - $is_html_attr = true; - break; - } - } - return $is_html_attr; - } - /** * Tests whether an attribute escaping function is being used outside of an HTML tag. * diff --git a/WordPressVIPMinimum/Tests/Security/ProperEscapingFunctionUnitTest.inc b/WordPressVIPMinimum/Tests/Security/ProperEscapingFunctionUnitTest.inc index bd5523d7..e477c716 100644 --- a/WordPressVIPMinimum/Tests/Security/ProperEscapingFunctionUnitTest.inc +++ b/WordPressVIPMinimum/Tests/Security/ProperEscapingFunctionUnitTest.inc @@ -38,9 +38,9 @@ echo 'data-param-url="' . Esc_HTML( $share_url ) . '"'; // Error. ?> -
- - + + +link From 1401543a67f01b078923f323b1aa77917f6289e1 Mon Sep 17 00:00:00 2001 From: jrfnl Date: Thu, 22 Apr 2021 07:05:38 +0200 Subject: [PATCH 4/7] ProperEscapingFunction: fine-tune attribute regex This adds test cases with: * No space before "action" as it is at the start of the line in a multi-line text string. * A tab before "action". ... and makes minor adjustments to the regex to safeguard handling these cases correctly. --- .../Sniffs/Security/ProperEscapingFunctionSniff.php | 2 +- .../Tests/Security/ProperEscapingFunctionUnitTest.inc | 10 ++++++++++ .../Tests/Security/ProperEscapingFunctionUnitTest.php | 2 ++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/WordPressVIPMinimum/Sniffs/Security/ProperEscapingFunctionSniff.php b/WordPressVIPMinimum/Sniffs/Security/ProperEscapingFunctionSniff.php index ae1d6725..5a966352 100644 --- a/WordPressVIPMinimum/Sniffs/Security/ProperEscapingFunctionSniff.php +++ b/WordPressVIPMinimum/Sniffs/Security/ProperEscapingFunctionSniff.php @@ -23,7 +23,7 @@ class ProperEscapingFunctionSniff extends Sniff { * * @var string */ - const ATTR_END_REGEX = '`(?href|src|url|\s+action)?=(?:(?:\\\\)?["\'])?$`i'; + const ATTR_END_REGEX = '`(?href|src|url|(^|\s+)action)?=(?:\\\\)?["\']*$`i'; /** * List of escaping functions which are being tested. diff --git a/WordPressVIPMinimum/Tests/Security/ProperEscapingFunctionUnitTest.inc b/WordPressVIPMinimum/Tests/Security/ProperEscapingFunctionUnitTest.inc index e477c716..35f20d1e 100644 --- a/WordPressVIPMinimum/Tests/Security/ProperEscapingFunctionUnitTest.inc +++ b/WordPressVIPMinimum/Tests/Security/ProperEscapingFunctionUnitTest.inc @@ -85,3 +85,13 @@ echo 'data-param-url="' . Esc_HTML::static_method( $share_url ) . '"'; // OK. // Not a target for this sniff (yet). printf( '', esc_attr( $content ) ); // OK. +?> + +// Making sure tabs and new lines before "action" are handled correctly. + +'; // OK. +echo ''; // Error. diff --git a/WordPressVIPMinimum/Tests/Security/ProperEscapingFunctionUnitTest.php b/WordPressVIPMinimum/Tests/Security/ProperEscapingFunctionUnitTest.php index 8db41f41..2a0e020b 100644 --- a/WordPressVIPMinimum/Tests/Security/ProperEscapingFunctionUnitTest.php +++ b/WordPressVIPMinimum/Tests/Security/ProperEscapingFunctionUnitTest.php @@ -53,6 +53,8 @@ public function getErrorList() { 79 => 1, 80 => 1, 82 => 1, + 92 => 1, + 97 => 1, ]; } From a6151099e5f32592db9ca97459587b87a811480e Mon Sep 17 00:00:00 2001 From: jrfnl Date: Thu, 22 Apr 2021 07:26:00 +0200 Subject: [PATCH 5/7] ProperEscapingFunction: deprecate, don't remove ... the `public` methods and as those use the `private` properties and extending sniffs may rely on the functionality of the `public` methods, we can't removed the `private` properties yet either, so deprecating those too. --- .../Security/ProperEscapingFunctionSniff.php | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/WordPressVIPMinimum/Sniffs/Security/ProperEscapingFunctionSniff.php b/WordPressVIPMinimum/Sniffs/Security/ProperEscapingFunctionSniff.php index 5a966352..6b7a6ce1 100644 --- a/WordPressVIPMinimum/Sniffs/Security/ProperEscapingFunctionSniff.php +++ b/WordPressVIPMinimum/Sniffs/Security/ProperEscapingFunctionSniff.php @@ -56,6 +56,39 @@ class ProperEscapingFunctionSniff extends Sniff { T_NS_SEPARATOR => T_NS_SEPARATOR, ]; + /** + * List of attributes associated with url outputs. + * + * @deprecated 2.3.1 Currently unused by the sniff, but needed for + * for public methods which extending sniffs may be + * relying on. + * + * @var array + */ + private $url_attrs = [ + 'href', + 'src', + 'url', + 'action', + ]; + + /** + * List of syntaxes for inside attribute detection. + * + * @deprecated 2.3.1 Currently unused by the sniff, but needed for + * for public methods which extending sniffs may be + * relying on. + * + * @var array + */ + private $attr_endings = [ + '=', + '="', + "='", + "=\\'", + '=\\"', + ]; + /** * Returns an array of tokens this test wants to listen for. * @@ -133,6 +166,48 @@ public function process_token( $stackPtr ) { } } + /** + * Tests whether provided string ends with open attribute which expects a URL value. + * + * @deprecated 2.3.1 + * + * @param string $content Haystack in which we look for an open attribute which exects a URL value. + * + * @return bool True if string ends with open attribute which expects a URL value. + */ + public function attr_expects_url( $content ) { + $attr_expects_url = false; + foreach ( $this->url_attrs as $attr ) { + foreach ( $this->attr_endings as $ending ) { + if ( $this->endswith( $content, $attr . $ending ) === true ) { + $attr_expects_url = true; + break; + } + } + } + return $attr_expects_url; + } + + /** + * Tests whether provided string ends with open HMTL attribute. + * + * @deprecated 2.3.1 + * + * @param string $content Haystack in which we look for open HTML attribute. + * + * @return bool True if string ends with open HTML attribute. + */ + public function is_html_attr( $content ) { + $is_html_attr = false; + foreach ( $this->attr_endings as $ending ) { + if ( $this->endswith( $content, $ending ) === true ) { + $is_html_attr = true; + break; + } + } + return $is_html_attr; + } + /** * Tests whether an attribute escaping function is being used outside of an HTML tag. * From c3c2bce73a4a7f07410742bf24e46cacb55fc05b Mon Sep 17 00:00:00 2001 From: jrfnl Date: Thu, 22 Apr 2021 05:35:51 +0200 Subject: [PATCH 6/7] ProperEscapingFunction: allow for comma's in first short open echo tag expression Short open echo tags will act as an echo for the first expression and allow for passing multiple comma-separated parameters. However, short open echo tags also allow for additional statements after, but those have to be full PHP statements, not expressions. So, the `T_COMMA` token should be allowed and skipped over in the first expression, but not for subsequent statements following a short open echo tag. `$phpcsFile->findStartOfStatement()` unfortunately is useless - even in its fixed-up form as will be in PHPCS 3.6.1-, as it will return the first token in the statement, which can be anything - variable, text string - without any indication of whether this is the start of a normal statement or a short open echo expression. So, if we used that, we'd still need to walk back from every start of statement to the previous non-empty to see if it is the short open echo tag. So to solve this conundrum, I've implemented a simple tracking system which will keep track of whether we have seen a short open echo tag and are within the first statement (expression) after this tag and will add the `T_COMMA` token if those conditions are fulfilled. Fixes 671 --- .../Security/ProperEscapingFunctionSniff.php | 52 ++++++++++++++-- .../ProperEscapingFunctionUnitTest.inc | 11 ++++ .../ProperEscapingFunctionUnitTest.php | 62 ++++++++++--------- 3 files changed, 91 insertions(+), 34 deletions(-) diff --git a/WordPressVIPMinimum/Sniffs/Security/ProperEscapingFunctionSniff.php b/WordPressVIPMinimum/Sniffs/Security/ProperEscapingFunctionSniff.php index 6b7a6ce1..7e876d5c 100644 --- a/WordPressVIPMinimum/Sniffs/Security/ProperEscapingFunctionSniff.php +++ b/WordPressVIPMinimum/Sniffs/Security/ProperEscapingFunctionSniff.php @@ -89,6 +89,14 @@ class ProperEscapingFunctionSniff extends Sniff { '=\\"', ]; + /** + * Keep track of whether or not we're currently in the first statement of a short open echo tag. + * + * @var int|false Integer stack pointer to the end of the first statement in the current + * short open echo tag or false when not in a short open echo tag. + */ + private $in_short_echo = false; + /** * Returns an array of tokens this test wants to listen for. * @@ -97,7 +105,10 @@ class ProperEscapingFunctionSniff extends Sniff { public function register() { $this->echo_or_concat_tokens += Tokens::$emptyTokens; - return [ T_STRING ]; + return [ + T_STRING, + T_OPEN_TAG_WITH_ECHO, + ]; } /** @@ -108,6 +119,35 @@ public function register() { * @return void */ public function process_token( $stackPtr ) { + /* + * Short open echo tags will act as an echo for the first expression and + * allow for passing multiple comma-separated parameters. + * However, short open echo tags also allow for additional statements after, but + * those have to be full PHP statements, not expressions. + * + * This snippet of code will keep track of whether or not we're in the first + * expression in a short open echo tag. + * $phpcsFile->findStartOfStatement() unfortunately is useless, as it will return + * the first token in the statement, which can be anything - variable, text string - + * without any indication of whether this is the start of a normal statement or + * a short open echo expression. + * So, if we used that, we'd need to walk back from every start of statement to + * the previous non-empty to see if it is the short open echo tag. + */ + if ( $this->tokens[ $stackPtr ]['code'] === T_OPEN_TAG_WITH_ECHO ) { + $end_of_echo = $this->phpcsFile->findNext( [ T_SEMICOLON, T_CLOSE_TAG ], ( $stackPtr + 1 ) ); + if ( $end_of_echo === false ) { + $this->in_short_echo = $this->phpcsFile->numTokens; + } else { + $this->in_short_echo = $end_of_echo; + } + + return; + } + + if ( $this->in_short_echo !== false && $this->in_short_echo < $stackPtr ) { + $this->in_short_echo = false; + } $function_name = strtolower( $this->tokens[ $stackPtr ]['content'] ); @@ -121,10 +161,14 @@ public function process_token( $stackPtr ) { return; } - $ignore = $this->echo_or_concat_tokens; - $start_of_statement = $this->phpcsFile->findStartOfStatement( $stackPtr, T_COMMA ); - if ( $this->tokens[ $start_of_statement ]['code'] === T_ECHO ) { + $ignore = $this->echo_or_concat_tokens; + if ( $this->in_short_echo !== false ) { $ignore[ T_COMMA ] = T_COMMA; + } else { + $start_of_statement = $this->phpcsFile->findStartOfStatement( $stackPtr, T_COMMA ); + if ( $this->tokens[ $start_of_statement ]['code'] === T_ECHO ) { + $ignore[ T_COMMA ] = T_COMMA; + } } $html = $this->phpcsFile->findPrevious( $ignore, $stackPtr - 1, null, true ); diff --git a/WordPressVIPMinimum/Tests/Security/ProperEscapingFunctionUnitTest.inc b/WordPressVIPMinimum/Tests/Security/ProperEscapingFunctionUnitTest.inc index 35f20d1e..c273f93f 100644 --- a/WordPressVIPMinimum/Tests/Security/ProperEscapingFunctionUnitTest.inc +++ b/WordPressVIPMinimum/Tests/Security/ProperEscapingFunctionUnitTest.inc @@ -95,3 +95,14 @@ echo ''; // OK. echo ''; // Error. + +// Verify correct handling of comma's in short open echo tags, without affecting subsequent statements. +?> +
html
+' , esc_attr( $test ) , ''; // Error. +printf( '', esc_attr( $content ) ); // OK. +echo ''; // Error. +?> +
html
+'; ?> +
html
diff --git a/WordPressVIPMinimum/Tests/Security/ProperEscapingFunctionUnitTest.php b/WordPressVIPMinimum/Tests/Security/ProperEscapingFunctionUnitTest.php index 2a0e020b..9a4b31c8 100644 --- a/WordPressVIPMinimum/Tests/Security/ProperEscapingFunctionUnitTest.php +++ b/WordPressVIPMinimum/Tests/Security/ProperEscapingFunctionUnitTest.php @@ -25,36 +25,38 @@ class ProperEscapingFunctionUnitTest extends AbstractSniffUnitTest { */ public function getErrorList() { return [ - 3 => 1, - 5 => 1, - 15 => 1, - 17 => 1, - 21 => 1, - 23 => 1, - 33 => 1, - 37 => 1, - 41 => 1, - 45 => 1, - 48 => 1, - 62 => 1, - 63 => 1, - 64 => 1, - 65 => 1, - 67 => 1, - 68 => 1, - 69 => 1, - 72 => 1, - 73 => 1, - 74 => 1, - 75 => 1, - 76 => 1, - 77 => 1, - 78 => 1, - 79 => 1, - 80 => 1, - 82 => 1, - 92 => 1, - 97 => 1, + 3 => 1, + 5 => 1, + 15 => 1, + 17 => 1, + 21 => 1, + 23 => 1, + 33 => 1, + 37 => 1, + 41 => 1, + 45 => 1, + 48 => 1, + 62 => 1, + 63 => 1, + 64 => 1, + 65 => 1, + 67 => 1, + 68 => 1, + 69 => 1, + 72 => 1, + 73 => 1, + 74 => 1, + 75 => 1, + 76 => 1, + 77 => 1, + 78 => 1, + 79 => 1, + 80 => 1, + 82 => 1, + 92 => 1, + 97 => 1, + 102 => 1, + 104 => 1, ]; } From a7439c9330500bb0102f3788837948114d16576c Mon Sep 17 00:00:00 2001 From: Rebecca Hum <16962021+rebeccahum@users.noreply.github.com> Date: Thu, 22 Apr 2021 11:38:29 -0600 Subject: [PATCH 7/7] Add changelog for 2.3.1 release --- CHANGELOG.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e3c3744d..ef8efb9c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,17 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [2.3.1] - 2021-04-23 + +Props: jrfnl + +### Fixed +- [#668](https://github.com/Automattic/VIP-Coding-Standards/pull/668): ProperEscapingFunction: fix overreach of comma usage in non-echo expressions for notAttrEscAttr. +- [#670](https://github.com/Automattic/VIP-Coding-Standards/pull/670): ProperEscapingFunction: improve "action" match precision for hrefSrcEscUrl. + +## Deprecated +- [#670](https://github.com/Automattic/VIP-Coding-Standards/pull/670): ProperEscapingFunction: private properties `$url_attrs` and `$attr_endings` are deprecated along with the public methods `is_html_attr()` and `attr_expects_url()`. + ## [2.3.0] - 2021-04-19 Props: jrfnl, rebeccahum, kevinfodness, GaryJones. @@ -539,6 +550,7 @@ Initial release. Props: david-binda, pkevan. +[2.3.1]: https://github.com/Automattic/VIP-Coding-Standards/compare/2.3.0...2.3.1 [2.3.0]: https://github.com/Automattic/VIP-Coding-Standards/compare/2.2.0...2.3.0 [2.2.0]: https://github.com/Automattic/VIP-Coding-Standards/compare/2.1.0...2.2.0 [2.1.0]: https://github.com/Automattic/VIP-Coding-Standards/compare/2.0.0...2.1.0