Index: includes/coder_security.inc =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/coder/includes/coder_security.inc,v retrieving revision 1.15.2.17.2.1 diff -u -p -r1.15.2.17.2.1 coder_security.inc --- includes/coder_security.inc 29 Sep 2008 13:12:32 -0000 1.15.2.17.2.1 +++ includes/coder_security.inc 19 Nov 2008 13:19:00 -0000 @@ -16,7 +16,21 @@ function coder_security_reviews() { $rules = array( array( '#type' => 'regex', - '#value' => 'l\(check_plain\(.*', + '#value' => '[\s\(]drupal_set_title\s*\(.*\$', + '#never' => '(^function\s|drupal_set_title\s*\(\s*(((st|t|\$t)\s*\(.*?array\([^!]+\))|(format_plural|filter_xss_admin|check_plain|check_markup)\s*\().*$)', + '#source' => 'allphp', + '#warning_callback' => '_coder_security_drupal_set_title_filter_warning', + ), + array( + '#type' => 'regex', + '#value' => '[\s\(]drupal_set_message\s*\(.*\$', + '#never' => '(^function\s|drupal_set_message\s*\(\s*(((st|t|\$t)\s*\(.*?array\([^!]+\))|(format_plural|filter_xss_admin|check_plain|check_markup)\s*\().*$)', + '#source' => 'allphp', + '#warning_callback' => '_coder_security_drupal_set_message_filter_warning', + ), + array( + '#type' => 'regex', + '#value' => '[\s\(]l\(check_plain\(.*', '#never' => '[\'"]html[\'"]\s*=>\s*(TRUE|1)', '#source' => 'allphp', '#warning_callback' => '_coder_security_l_check_plain_warning', @@ -77,6 +91,28 @@ function coder_security_reviews() { * Define the warning callbacks. */ +function _coder_security_drupal_set_title_filter_warning() { + return t('!drupal_set_title() only accepts filtered text, be sure to use !t(), !check_plain(), !filter_xss_admin() or similar.', + array( + '!drupal_set_title' => theme('drupalapi', 'drupal_set_title'), + '!t' => theme('drupalapi', 't'), + '!check_plain' => theme('drupalapi', 'check_plain'), + '!filter_xss_admin' => theme('drupalapi', 'filter_xss_admin'), + ) + ); +} + +function _coder_security_drupal_set_message_filter_warning() { + return t('!drupal_set_message() only accepts filtered text, be sure to use !t(), !check_plain(), !filter_xss_admin() or similar.', + array( + '!drupal_set_message' => theme('drupalapi', 'drupal_set_message'), + '!t' => theme('drupalapi', 't'), + '!check_plain' => theme('drupalapi', 'check_plain'), + '!filter_xss_admin' => theme('drupalapi', 'filter_xss_admin'), + ) + ); +} + function _coder_security_l_check_plain_warning() { return t('!l() already contains a !check_plain() call by default', array( Index: tests/coder_security.test =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/coder/tests/Attic/coder_security.test,v retrieving revision 1.1.2.8 diff -u -p -r1.1.2.8 coder_security.test --- tests/coder_security.test 27 Sep 2008 16:59:57 -0000 1.1.2.8 +++ tests/coder_security.test 19 Nov 2008 13:19:00 -0000 @@ -5,7 +5,7 @@ class CoderSecurityTest extends CoderTes function __construct($id = NULL) { parent::__construct('security', $id); } - + function getInfo() { return array( 'name' => t('Coder Security Tests'), @@ -13,7 +13,7 @@ class CoderSecurityTest extends CoderTes 'group' => t('Coder'), ); } - + function testSecurityCheckPlain() { $this->assertCoderFail('$var = l(check_plain($input), "path/to/drupal");'); $this->assertCoderFail('$var = l(check_plain($input), "path/to/drupal", array("html" => FALSE);'); @@ -52,4 +52,32 @@ class CoderSecurityTest extends CoderTes $this->assertCoderPass(' $sql = "INSERT INTO {foo} (1,%d)";'); $this->assertCoderPass(' $sql = "INSERT INTO {foo} (1, %d)";'); } + + function testDrupalSetMessageTitle() { + $this->assertCoderPass(' drupal_set_message(t("Here is some safe_data"));'); + $this->assertCoderPass(' drupal_set_message(t("Here is some @safe_data", array("@safe_data" => $tainted_data));'); + $this->assertCoderPass(' drupal_set_message(t("Here is some %safe_data", array("%safe_data" => $tainted_data));'); + $this->assertCoderPass(' drupal_set_message(check_plain($tainted_data));'); + $this->assertCoderPass(' drupal_set_message(filter_xss_admin($tainted_data));'); + $this->assertCoderPass(' drupal_set_message(format_plural($tainted_count, "1 item", "@count items"));'); + $this->assertCoderPass(' drupal_set_message(check_markup($tainted_data));'); + $this->assertCoderFail(' drupal_set_message($tainted_data);'); + $this->assertCoderFail(' drupal_set_message("Here is some ". $tainted_data);'); + $this->assertCoderFail(' drupal_set_message("Here is some $tainted_data");'); + $this->assertCoderFail(' drupal_set_message(t("Here is some ". $tainted_data));'); + $this->assertCoderFail(' drupal_set_message(t("Here is some !tainted_data", array("!tainted_data" => $tainted_data)));'); + + $this->assertCoderPass(' drupal_set_title(t("Here is some safe_data"));'); + $this->assertCoderPass(' drupal_set_title(t("Here is some @safe_data", array("@safe_data" => $tainted_data));'); + $this->assertCoderPass(' drupal_set_title(t("Here is some %safe_data", array("%safe_data" => $tainted_data));'); + $this->assertCoderPass(' drupal_set_title(check_plain($tainted_data));'); + $this->assertCoderPass(' drupal_set_title(filter_xss_admin($tainted_data));'); + $this->assertCoderPass(' drupal_set_title(format_plural($tainted_count, "1 item", "@count items"));'); + $this->assertCoderPass(' drupal_set_title(check_markup($tainted_data));'); + $this->assertCoderFail(' drupal_set_title($tainted_data);'); + $this->assertCoderFail(' drupal_set_title("Here is some ". $tainted_data);'); + $this->assertCoderFail(' drupal_set_title("Here is some $tainted_data");'); + $this->assertCoderFail(' drupal_set_title(t("Here is some ". $tainted_data));'); + $this->assertCoderFail(' drupal_set_title(t("Here is some !tainted_data", array("!tainted_data" => $tainted_data));'); + } }