Index: modules/filter/filter.api.php =================================================================== RCS file: /cvs/drupal/drupal/modules/filter/filter.api.php,v retrieving revision 1.13 diff -u -p -r1.13 filter.api.php --- modules/filter/filter.api.php 27 Aug 2009 21:18:19 -0000 1.13 +++ modules/filter/filter.api.php 7 Sep 2009 16:01:45 -0000 @@ -40,6 +40,10 @@ * content before the actual filtering happens. * - 'process callback': The name the function that performs the actual * filtering. + * - When a text format is checked to determine if it is configured securely, + * the following properties may be used: + * - 'security callback': The name of a function that determines whether the + * filter allows new exploits or prevents existing ones. * * Filtering is a two-step process. First, the content is 'prepared' by calling * the 'prepare callback' function for every filter. The purpose of the 'prepare @@ -64,6 +68,14 @@ * format is an entire filter setup: which filters to enable, in what order * and with what settings. * + * Different filters can introduce or remove security vulnerabilities in the + * text formats that contain them, depending on how they are configured. + * Filters that have implications for security should therefore use the + * 'security callback' function to provide information about whether they are + * configured securely. The filtering system will collect this information and + * use it to automatically determine whether the text format as a whole is + * secure. + * * Filters that require settings should provide the form controls to configure * the settings in a form builder function, specified in 'settings callback'. * The filter system stores the settings in the database per text format. @@ -122,6 +134,56 @@ * - $format: The format object of the text to be filtered. * - $long: Boolean whether to return long or short filter guidelines. * + * 'security callback' is invoked with the following parameters: + * - $filter: An object representing the filter within the text format that is + * being checked. The most important property is $filter->settings, which + * contains an array of settings for this filter as it is configured within + * the current text format. The security callback function should inspect + * these settings if they are relevant for determining when the filter is + * configured securely. + * - &$warnings: An array which the security callback function should fill with + * warning messages in one of two cases: (1) If the filter opens up a new + * exploit in a previously safe text format, or (2) If the filter could have + * specifically prevented an exploit if it had been configured in a different + * way. The warning messages should be keyed by the type of output in which + * the potential vulnerability exists. For example, use $warnings['html'][] + * for an exploit that occurs when content that passes through the text + * format is output as HTML (e.g., cross-site scripting exploits). This is + * the most common type of output, but others are possible; for example, the + * PHP module uses $warnings['php'][] to indicate that the PHP filter + * contains an inherent vulnerability due to the fact that content which + * passes through it is executed as PHP code. + * + * The return value of the 'security callback' function is an optional array + * representing the effect of the filter on each type of output. The constant + * FILTER_EXPLOIT_PREVENTS should be used if the filter prevents security + * exploits by sanitizing previously-unsafe content; for example, a filter that + * escapes HTML would return array('html' => FILTER_EXPLOIT_PREVENTS). The + * constant FILTER_EXPLOIT_ALLOWS should be used if the filter allows a new + * security exploit, even if the content passed in to the filter was previously + * sanitized. For example, a filter that evaluates PHP code would return + * array('php' => FILTER_EXPLOIT_ALLOWS). If the security callback function + * does not include a particular type of output in the returned array, this is + * taken to mean that the filter does not affect the security of this type of + * output one way or the other; unsanitized content passed in to the filter + * remains unsanitized after the filter is applied, and sanitized content + * passed in to the filter similarly remains sanitized. + * + * @code + * function mymodule_check_security($filter, &$warnings) { + * if (empty($filter->settings['remove_unsafe_html'])) { + * $warnings['html'][] = t('The "mymodule" filter is configured to allow unsafe HTML. Either select the "remove unsafe HTML" option in the configuration settings for this filter, or add another filter after it that separately removes unsafe HTML.'); + * } + * else { + * // The "remove unsafe HTML" configuration option was selected, so this + * // filter prevents HTML exploits. + * return array('html' => FILTER_EXPLOIT_PREVENTS); + * } + * } + * @endcode + * + * @see filter_format_is_secure() + * * For performance reasons content is only filtered once; the result is stored * in the cache table and retrieved from the cache the next time the same piece * of content is displayed. If a filter's output is dynamic, it can override the @@ -145,6 +207,9 @@ * of the filtering. * - 'process callback': (required) The callback function to call in the * 'process' step of the filtering. + * - 'security callback': A callback function that determines whether the + * filter is configured to allow new security exploits or prevent existing + * ones. * - 'settings callback': A callback function that provides form controls * for the filter's settings. Each filter should apply either the default * settings or the configured settings contained in $filter->settings. The @@ -166,6 +231,7 @@ function hook_filter_info() { 'title' => t('Limit allowed HTML tags'), 'description' => t('Allows you to restrict the HTML tags the user can use. It will also remove harmful content such as JavaScript events, JavaScript URLs and CSS styles from those tags that are not removed.'), 'process callback' => '_filter_html', + 'security callback' => '_filter_html_check_security', 'settings callback' => '_filter_html_settings', 'default settings' => array( 'allowed_html' => '