-
Notifications
You must be signed in to change notification settings - Fork 40
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
1fa0266
commit 219303b
Showing
3 changed files
with
155 additions
and
0 deletions.
There are no files selected for viewing
82 changes: 82 additions & 0 deletions
82
WordPressVIPMinimum/Sniffs/Security/InlineScriptEscapingSniff.php
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
<?php | ||
/** | ||
* WordPressVIPMinimum Coding Standard. | ||
* | ||
* @package VIPCS\WordPressVIPMinimum | ||
* @link https://github.com/Automattic/VIP-Coding-Standards | ||
*/ | ||
|
||
namespace WordPressVIPMinimum\Sniffs\Security; | ||
|
||
use WordPressVIPMinimum\Sniffs\Sniff; | ||
use PHP_CodeSniffer\Util\Tokens; | ||
|
||
/** | ||
* Checks whether proper escaping function is used between script tags. | ||
* | ||
* @package VIPCS\WordPressVIPMinimum | ||
*/ | ||
class InlineScriptEscapingSniff extends Sniff { | ||
|
||
/** | ||
* Property to keep track of between script tags. | ||
* | ||
* @var array | ||
*/ | ||
private $in_script = false; | ||
|
||
/** | ||
* Returns an array of tokens this test wants to listen for. | ||
* | ||
* @return array | ||
*/ | ||
public function register() { | ||
return [ | ||
'T_INLINE_HTML' => T_INLINE_HTML, | ||
'T_STRING' => T_STRING, | ||
]; | ||
} | ||
|
||
/** | ||
* Process this test when one of its tokens is encountered | ||
* | ||
* @param int $stackPtr The position of the current token in the stack passed in $tokens. | ||
* | ||
* @return void | ||
*/ | ||
public function process_token( $stackPtr ) { | ||
$content = trim( $this->tokens[ $stackPtr ]['content'] ); | ||
|
||
if ( $content === '' ) { | ||
return; | ||
} | ||
|
||
if ( $this->has_open_script_tag( $content ) === true ) { | ||
$this->in_script = true; | ||
} elseif ( strpos( '</script>', $content ) !== false ) { | ||
$this->in_script = false; | ||
} | ||
|
||
if ( $this->in_script === true && $this->tokens[ $stackPtr ]['content'] === 'esc_js' ) { | ||
$message = 'Please do not use `esc_js()` for inline script escaping. See our code repository for | ||
examples on how to escape within: https://github.com/Automattic/vip-code-samples/blob/master/10-security/js-dynamic.php'; | ||
$this->phpcsFile->addError( $message, $stackPtr, 'InlineScriptEsc' ); | ||
return; | ||
} | ||
} | ||
|
||
/** | ||
* Check if a content string contains <script> tag. | ||
* | ||
* @param string $content Haystack where we look for complete <script> tag. | ||
* | ||
* @return bool True if the string contains <script> tag, false otherwise. | ||
*/ | ||
public function has_open_script_tag( $content = null ) { | ||
if ( substr( $content, -1 ) !== '>' ) { | ||
return false; // Incomplete tag, bail. | ||
} | ||
|
||
return $content !== null && strpos( $content, '<script' ) !== false; | ||
} | ||
} |
30 changes: 30 additions & 0 deletions
30
WordPressVIPMinimum/Tests/Security/InlineScriptEscapingUnitTest.inc
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
<?php | ||
$color = 'blue'; | ||
$url = 'https://test.com'; | ||
$themeURI = get_template_directory_uri(); | ||
$ga_ua = 'foo'; | ||
$page_title = '<h1>Test</h1>'; | ||
?> | ||
<script type="text/javascript"> | ||
var name = decodeURIComponent( '<?php echo esc_js( $name ); ?>' ); // Error. | ||
var html = document.createElement('h1'); | ||
html.innerText = name; | ||
</script> | ||
<script> | ||
window.location.replace('<?php echo esc_js(site_url());?>/foo/#bar'); // Error. | ||
ga('create', <?php echo (esc_js($ga_ua)); ?>, 'auto'); // Error. | ||
</script> | ||
<script type="text/javascript" src="<?php echo esc_js($themeURI.'/js/lib.min.js' ); // OK - Not in script scope. | ||
?>"></script> | ||
<script> | ||
var url = <?php echo wp_json_encode( esc_url( $url ) ) ?>; // OK. | ||
var title = decodeURIComponent( '<?php echo rawurlencode( (string) $page_title ); ?>' ); // OK. | ||
</script> | ||
|
||
<style> | ||
h1 { | ||
color: <?php echo esc_js( $color ) ?>; /* OK - Not in script scope. */ | ||
font-family: verdana; | ||
font-size: 300%; | ||
} | ||
</style> |
43 changes: 43 additions & 0 deletions
43
WordPressVIPMinimum/Tests/Security/InlineScriptEscapingUnitTest.php
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
<?php | ||
/** | ||
* Unit test class for WordPressVIPMinimum Coding Standard. | ||
* | ||
* @package VIPCS\WordPressVIPMinimum | ||
*/ | ||
|
||
namespace WordPressVIPMinimum\Tests\Security; | ||
|
||
use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; | ||
|
||
/** | ||
* Unit test class for the InlineScriptEscaping sniff. | ||
* | ||
* @package VIPCS\WordPressVIPMinimum | ||
* | ||
* @covers \WordPressVIPMinimum\Sniffs\Security\InlineScriptEscapingSniff | ||
*/ | ||
class InlineScriptEscapingUnitTest extends AbstractSniffUnitTest { | ||
|
||
/** | ||
* Returns the lines where errors should occur. | ||
* | ||
* @return array <int line number> => <int number of errors> | ||
*/ | ||
public function getErrorList() { | ||
return [ | ||
9 => 1, | ||
14 => 1, | ||
15 => 1, | ||
]; | ||
} | ||
|
||
/** | ||
* Returns the lines where warnings should occur. | ||
* | ||
* @return array <int line number> => <int number of warnings> | ||
*/ | ||
public function getWarningList() { | ||
return []; | ||
} | ||
|
||
} |