Skip to content

Commit 7f77f90

Browse files
committed
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.
1 parent 7decb5b commit 7f77f90

File tree

2 files changed

+16
-68
lines changed

2 files changed

+16
-68
lines changed

WordPressVIPMinimum/Sniffs/Security/ProperEscapingFunctionSniff.php

Lines changed: 13 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,13 @@
1818
*/
1919
class ProperEscapingFunctionSniff extends Sniff {
2020

21+
/**
22+
* Regular expression to match the end of HTML attributes.
23+
*
24+
* @var string
25+
*/
26+
const ATTR_END_REGEX = '`(?<attrname>href|src|url|\s+action)?=(?:(?:\\\\)?["\'])?$`i';
27+
2128
/**
2229
* List of escaping functions which are being tested.
2330
*
@@ -49,31 +56,6 @@ class ProperEscapingFunctionSniff extends Sniff {
4956
T_NS_SEPARATOR => T_NS_SEPARATOR,
5057
];
5158

52-
/**
53-
* List of attributes associated with url outputs.
54-
*
55-
* @var array
56-
*/
57-
private $url_attrs = [
58-
'href',
59-
'src',
60-
'url',
61-
'action',
62-
];
63-
64-
/**
65-
* List of syntaxes for inside attribute detection.
66-
*
67-
* @var array
68-
*/
69-
private $attr_endings = [
70-
'=',
71-
'="',
72-
"='",
73-
"=\\'",
74-
'=\\"',
75-
];
76-
7759
/**
7860
* Returns an array of tokens this test wants to listen for.
7961
*
@@ -134,57 +116,23 @@ public function process_token( $stackPtr ) {
134116
return;
135117
}
136118

137-
if ( $escaping_type !== 'url' && $this->attr_expects_url( $content ) ) {
119+
if ( preg_match( self::ATTR_END_REGEX, $content, $matches ) !== 1 ) {
120+
return;
121+
}
122+
123+
if ( $escaping_type !== 'url' && empty( $matches['attrname'] ) === false ) {
138124
$message = 'Wrong escaping function. href, src, and action attributes should be escaped by `esc_url()`, not by `%s()`.';
139125
$this->phpcsFile->addError( $message, $stackPtr, 'hrefSrcEscUrl', $data );
140126
return;
141127
}
142128

143-
if ( $escaping_type === 'html' && $this->is_html_attr( $content ) ) {
129+
if ( $escaping_type === 'html' ) {
144130
$message = 'Wrong escaping function. HTML attributes should be escaped by `esc_attr()`, not by `%s()`.';
145131
$this->phpcsFile->addError( $message, $stackPtr, 'htmlAttrNotByEscHTML', $data );
146132
return;
147133
}
148134
}
149135

150-
/**
151-
* Tests whether provided string ends with open attribute which expects a URL value.
152-
*
153-
* @param string $content Haystack in which we look for an open attribute which exects a URL value.
154-
*
155-
* @return bool True if string ends with open attribute which expects a URL value.
156-
*/
157-
public function attr_expects_url( $content ) {
158-
$attr_expects_url = false;
159-
foreach ( $this->url_attrs as $attr ) {
160-
foreach ( $this->attr_endings as $ending ) {
161-
if ( $this->endswith( $content, $attr . $ending ) === true ) {
162-
$attr_expects_url = true;
163-
break;
164-
}
165-
}
166-
}
167-
return $attr_expects_url;
168-
}
169-
170-
/**
171-
* Tests whether provided string ends with open HMTL attribute.
172-
*
173-
* @param string $content Haystack in which we look for open HTML attribute.
174-
*
175-
* @return bool True if string ends with open HTML attribute.
176-
*/
177-
public function is_html_attr( $content ) {
178-
$is_html_attr = false;
179-
foreach ( $this->attr_endings as $ending ) {
180-
if ( $this->endswith( $content, $ending ) === true ) {
181-
$is_html_attr = true;
182-
break;
183-
}
184-
}
185-
return $is_html_attr;
186-
}
187-
188136
/**
189137
* Tests whether an attribute escaping function is being used outside of an HTML tag.
190138
*

WordPressVIPMinimum/Tests/Security/ProperEscapingFunctionUnitTest.inc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,9 @@ echo 'data-param-url="' . Esc_HTML( $share_url ) . '"'; // Error.
3838

3939
?>
4040

41-
<form method="post" action="<?php echo esc_html(admin_url('admin.php?page='.$base_name.'&amp;mode=logs&amp;id='.$poll_id)); ?>">
42-
43-
41+
<form method="post" action="<?php echo esc_html(admin_url('admin.php?page='.$base_name.'&amp;mode=logs&amp;id='.$poll_id)); ?>"><!-- Error. -->
42+
<input data-action="<?php echo esc_attr( $my_var ); ?>"><!-- OK. -->
43+
<a href='https://demo.com?foo=bar&my-action=<?php echo esc_attr( $var ); ?>'>link</a><!-- OK. -->
4444

4545
<a href="#link"><?php echo esc_attr( 'testing' ); // Error.
4646
?> </a>

0 commit comments

Comments
 (0)