diff --git modules/filter/filter.api.php modules/filter/filter.api.php index 5e20ed2..d2070b9 100644 --- modules/filter/filter.api.php +++ modules/filter/filter.api.php @@ -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 whose presence in a text format can 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,86 @@ * - $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 parameter: + * - $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. + * + * - If the filter opens up a new exploit in a previously safe text format, + * or + * - If the filter could have specifically prevented an exploit if it had + * been configured in a different way. + * The callback retuns an array keyed by the the categories in which + * potential vulnerabilities exists, such as 'html' or 'php'. By far the most + * common category is 'html', which occurs when the web browser processes + * the content as HTML (for example, cross-site scripting); this includes + * both HTML itself as well as other languages (such as JavaScript) that can + * be included in HTML. For example, a filter that processes a certain kind + * of markup language and transforms safe text, such as "[script]", into + * unsafe HTML tags, such as SCRIPT. A filter which needs to output a warning + * about creation of a HTML-related vulnerability would therefore use return + * an array like: + * @code + * return array('html' => array( + * 'type' => FILTER_EXPLOT_CREATES, + * 'warning' => t('A message explaining the vulnerability.') + * )); + * @endcode + * Although HTML-related exploits are by far the most common category, others + * are possible for certain types of unusual filters. For example, the PHP + * module in Drupal core uses the 'php' category to indicate that the PHP + * filter which it provides contains an inherent vulnerability since content + * is executed as PHP code on the server; this vulnerability represents a + * separate risk that is independent from any HTML-related vulnerabilities, + * and can not be undone by a later filter. In this case, the relevant + * type is therefore always FILTER_EXPLOT_CREATES. + * @code + * return array('php' => array( + * 'type' => FILTER_EXPLOT_CREATES, + * 'warning' => t('A message explaining the vulnerability.') + * )); + * @endcode + * Similarly, a hypothetical filter that took the content passed in to it and + * executed it as Perl code by running a local program on the web server + * would use the same format for its warning, with 'perl' as the key. + * + * The constant FILTER_EXPLOIT_PREVENTS should be used if the filter prevents + * security exploits by thoroughly sanitizing previously-unsafe HTML; thus, a + * filter that escapes HTML would return: + * @code + * array('html' => array('type' => FILTER_EXPLOIT_PREVENTS)). + * @endcode + * The constant FILTER_EXPLOIT_ALLOWS should be used if the filter allows a + * security exploit, but does not create one. Typically used for a HTML + * filter that allows some unsafe HTML tags to pass through and wants + * to inform the user about the specifics of the risk: + * @code + * return array('html' => array( + * 'type' => FILTER_EXPLOT_ALLOWS, + * 'warning' => t('A message explaining the allowed tags.') + * )); + * @endcode + * If the security callback function does not include a particular category 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_filter_security($filter, &$warnings) { + * if (empty($filter->settings['remove_unsafe_html'])) { + * // The "remove unsafe HTML" configuration option was selected, so this + * // filter prevents HTML exploits. + * return array('html' => array('type' => FILTER_EXPLOIT_PREVENTS)); + * } + * } + * @endcode + * + * @see filter_format_warnings() + * * 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 +237,11 @@ * 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. Many filters do not need to implement this callback at all; it + * should only be used by filters whose presence in a text format can have + * security implications. * - '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 +263,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_security', 'settings callback' => '_filter_html_settings', 'default settings' => array( 'allowed_html' => '