diff --git a/modules/block/block.module b/modules/block/block.module
index e0cb691..90bc6a1 100644
--- a/modules/block/block.module
+++ b/modules/block/block.module
@@ -242,7 +242,7 @@ function block_block_save($delta = 0, $edit = array()) {
 function block_block_view($delta = '') {
   $block = db_query('SELECT body, format FROM {block_custom} WHERE bid = :bid', array(':bid' => $delta))->fetchObject();
   $data['subject'] = NULL;
-  $data['content'] = check_markup($block->body, $block->format, '', TRUE);
+  $data['content'] = check_markup($block->body, $block->format, array('cache' => TRUE, 'type' => 'block', 'object' => $block));
   return $data;
 }
 
diff --git a/modules/book/book.test b/modules/book/book.test
index cc61778..4cbc6f4 100644
--- a/modules/book/book.test
+++ b/modules/book/book.test
@@ -165,7 +165,7 @@ class BookTestCase extends DrupalWebTestCase {
     // Check printer friendly version.
     $this->drupalGet('book/export/html/' . $node->nid);
     $this->assertText($node->title, t('Printer friendly title found.'));
-    $this->assertRaw(check_markup($node->body[LANGUAGE_NONE][0]['value'], $node->body[LANGUAGE_NONE][0]['format']), t('Printer friendly body found.'));
+    $this->assertRaw(check_markup($node->body[LANGUAGE_NONE][0]['value'], $node->body[LANGUAGE_NONE][0]['format'], array('type' => 'node', 'object' => $node)), t('Printer friendly body found.'));
 
     $number++;
   }
@@ -234,7 +234,7 @@ class BookTestCase extends DrupalWebTestCase {
     // Make sure each part of the book is there.
     foreach ($nodes as $node) {
       $this->assertText($node->title, t('Node title found in printer friendly version.'));
-      $this->assertRaw(check_markup($node->body[LANGUAGE_NONE][0]['value'], $node->body[LANGUAGE_NONE][0]['format']), t('Node body found in printer friendly version.'));
+      $this->assertRaw(check_markup($node->body[LANGUAGE_NONE][0]['value'], $node->body[LANGUAGE_NONE][0]['format'], array('type' => 'node', 'object' => $node)), t('Node body found in printer friendly version.'));
     }
 
     // Make sure we can't export an unsupported format.
diff --git a/modules/comment/comment.module b/modules/comment/comment.module
index 60a9ca4..fb2c7f8 100644
--- a/modules/comment/comment.module
+++ b/modules/comment/comment.module
@@ -2158,7 +2158,7 @@ function comment_submit($comment) {
     // 1) Filter it into HTML
     // 2) Strip out all HTML tags
     // 3) Convert entities back to plain-text.
-    $comment->subject = truncate_utf8(trim(decode_entities(strip_tags(check_markup($comment->comment_body[LANGUAGE_NONE][0]['value'], $comment->comment_body[LANGUAGE_NONE][0]['format'])))), 29, TRUE);
+    $comment->subject = truncate_utf8(trim(decode_entities(strip_tags(check_markup($comment->comment_body[LANGUAGE_NONE][0]['value'], $comment->comment_body[LANGUAGE_NONE][0]['format'], array('type' => 'comment', 'object' => $comment))))), 29, TRUE);
     // Edge cases where the comment body is populated only by HTML tags will
     // require a default subject.
     if ($comment->subject == '') {
diff --git a/modules/field/modules/text/text.module b/modules/field/modules/text/text.module
index 89c605c..bd0f6e2 100644
--- a/modules/field/modules/text/text.module
+++ b/modules/field/modules/text/text.module
@@ -156,9 +156,9 @@ function text_field_load($entity_type, $entities, $field, $instances, $langcode,
       // Only process items with a cacheable format, the rest will be handled
       // by formatters if needed.
       if (empty($instances[$id]['settings']['text_processing']) || filter_format_allowcache($item['format'])) {
-        $items[$id][$delta]['safe_value'] = isset($item['value']) ? _text_sanitize($instances[$id], $langcode, $item, 'value') : '';
+        $items[$id][$delta]['safe_value'] = isset($item['value']) ? _text_sanitize($instances[$id], $langcode, $entity_type, $entity, $item, 'value') : '';
         if ($field['type'] == 'text_with_summary') {
-          $items[$id][$delta]['safe_summary'] = isset($item['summary']) ? _text_sanitize($instances[$id], $langcode, $item, 'summary') : '';
+          $items[$id][$delta]['safe_summary'] = isset($item['summary']) ? _text_sanitize($instances[$id], $langcode, $entity_type, $entity, $item, 'summary') : '';
         }
       }
     }
@@ -261,7 +261,7 @@ function text_field_formatter_view($entity_type, $entity, $field, $instance, $la
     case 'text_default':
     case 'text_trimmed':
       foreach ($items as $delta => $item) {
-        $output = _text_sanitize($instance, $langcode, $item, 'value');
+        $output = _text_sanitize($instance, $langcode, $entity_type, $entity, $item, 'value');
         if ($display['type'] == 'text_trimmed') {
           $output = text_summary($output, $instance['settings']['text_processing'] ? $item['format'] : NULL, $display['settings']['trim_length']);
         }
@@ -272,10 +272,10 @@ function text_field_formatter_view($entity_type, $entity, $field, $instance, $la
     case 'text_summary_or_trimmed':
       foreach ($items as $delta => $item) {
         if (!empty($item['summary'])) {
-          $output = _text_sanitize($instance, $langcode, $item, 'summary');
+          $output = _text_sanitize($instance, $langcode, $entity_type, $entity, $item, 'summary');
         }
         else {
-          $output = _text_sanitize($instance, $langcode, $item, 'value');
+          $output = _text_sanitize($instance, $langcode, $entity_type, $entity, $item, 'value');
           $output = text_summary($output, $instance['settings']['text_processing'] ? $item['format'] : NULL, $display['settings']['trim_length']);
         }
         $element[$delta] = array('#markup' => $output);
@@ -301,7 +301,11 @@ function text_field_formatter_view($entity_type, $entity, $field, $instance, $la
  * @param $instance
  *   The instance definition.
  * @param $langcode
- *  The language associated to $item.
+ *   The language associated to $item.
+ * @param $entity_type
+ *   The entity type to sanitize, used for contextual data.
+ * @param $entity
+ *   The entity to sanitize, used for contextual data.
  * @param $item
  *   The field value to sanitize.
  * @param $column
@@ -310,13 +314,13 @@ function text_field_formatter_view($entity_type, $entity, $field, $instance, $la
  * @return
  *  The sanitized string.
  */
-function _text_sanitize($instance, $langcode, $item, $column) {
+function _text_sanitize($instance, $langcode, $entity_type, $entity, $item, $column) {
   // If the value uses a cacheable text format, text_field_load() precomputes
   // the sanitized string.
   if (isset($item["safe_$column"])) {
     return $item["safe_$column"];
   }
-  return $instance['settings']['text_processing'] ? check_markup($item[$column], $item['format'], $langcode) : check_plain($item[$column]);
+  return $instance['settings']['text_processing'] ? check_markup($item[$column], $item['format'], array('langcode' => $langcode, 'type' => $type, 'object' => $entity)) : check_plain($item[$column]);
 }
 
 /**
diff --git a/modules/filter/filter.api.php b/modules/filter/filter.api.php
index 6675e4a..13fb27a 100644
--- a/modules/filter/filter.api.php
+++ b/modules/filter/filter.api.php
@@ -65,6 +65,11 @@
  *     details.
  *   - process callback: (required) The name the function that performs the
  *     actual filtering. See hook_filter_FILTER_process() for details.
+ *   - 'context callback': The name of a function that extracts contextual data
+ *     from the object of the filtering. For example, a filter that uses the
+ *     name of the author of a node would use this to provide the name of the
+ *     author as context to the filter. This function will provide additional
+ *     contextual data to the prepare and process callbacks.
  *   - cache (default TRUE): Specifies whether the filtered text can be cached.
  *     Note that setting this to FALSE makes the entire text format not
  *     cacheable, which may have an impact on the site's overall performance.
@@ -189,8 +194,9 @@ function hook_filter_FILTER_settings($form, &$form_state, $filter, $format, $def
  *   The filter object containing settings for the given format.
  * @param $format
  *   The text format object assigned to the text to be filtered.
- * @param $langcode
- *   The language code of the text to be filtered.
+ * @param $context
+ *   The contextual data for the text to be filtered, including the
+ *   language code and any context provided in a 'context callback'.
  * @param $cache
  *   A Boolean indicating whether the filtered text is going to be cached in
  *   {cache_filter}.
@@ -200,7 +206,7 @@ function hook_filter_FILTER_settings($form, &$form_state, $filter, $format, $def
  * @return
  *   The prepared, escaped text.
  */
-function hook_filter_FILTER_prepare($text, $filter, $format, $langcode, $cache, $cache_id) {
+function hook_filter_FILTER_prepare($text, $filter, $format, $context, $cache, $cache_id) {
   // Escape <code> and </code> tags.
   $text = preg_replace('|<code>(.+?)</code>|se', "[codefilter_code]$1[/codefilter_code]", $text);
   return $text;
@@ -222,8 +228,9 @@ function hook_filter_FILTER_prepare($text, $filter, $format, $langcode, $cache,
  *   The filter object containing settings for the given format.
  * @param $format
  *   The text format object assigned to the text to be filtered.
- * @param $langcode
- *   The language code of the text to be filtered.
+ * @param $context
+ *   The contextual data for the text to be filtered, including the
+ *   language code and any context provided in a 'context callback'.
  * @param $cache
  *   A Boolean indicating whether the filtered text is going to be cached in
  *   {cache_filter}.
@@ -233,13 +240,52 @@ function hook_filter_FILTER_prepare($text, $filter, $format, $langcode, $cache,
  * @return
  *   The filtered text.
  */
-function hook_filter_FILTER_process($text, $filter, $format, $langcode, $cache, $cache_id) {
+function hook_filter_FILTER_process($text, $filter, $format, $context, $cache, $cache_id) {
   $text = preg_replace('|\[codefilter_code\](.+?)\[/codefilter_code\]|se', "<pre>$1</pre>", $text);
 
   return $text;
 }
 
 /**
+ * Context callback for hook_filter_info().
+ *
+ * Note: This is not really a hook. The function name is manually specified via
+ * 'context callback' in hook_filter_info(), with this recommended callback
+ * name pattern. It is called from check_markup().
+ *
+ * See hook_filter_info() for a description of the filtering process. This step
+ * is where the contextual data is generated for the filter.
+ *
+ * @param $text
+ *   The text string to be filtered.
+ * @param $filter
+ *   The filter object containing settings for the given format.
+ * @param $format
+ *   The text format object assigned to the text to be filtered.
+ * @param $type
+ *   The type of object being filtered.
+ * @param $object
+ *   The object variable of the object being filtered.
+ *
+ * @return
+ *   An associative array of contextual data from the object that, upon
+ *   changing, will require the filter to be rerun.
+ */
+function hook_filter_FILTER_context($text, $filter, $format, $type, $object) {
+  switch ($type) {
+    case 'node':
+    case 'comment':
+      $account = user_load($object->uid);
+      // Filter will have to recache when the account name changes, either when
+	  // the author of the comment/node changes or when the user changes their
+	  // name.
+      return array(
+        'user_name' => $account->name,
+      );
+  }
+}
+
+/**
  * Tips callback for hook_filter_info().
  *
  * Note: This is not really a hook. The function name is manually specified via
diff --git a/modules/filter/filter.module b/modules/filter/filter.module
index 773fa80..2dd5b58 100644
--- a/modules/filter/filter.module
+++ b/modules/filter/filter.module
@@ -704,18 +704,31 @@ function filter_list_format($format_id) {
  * @param $format_id
  *   The format id of the text to be filtered. If no format is assigned, the
  *   fallback format will be used.
- * @param $langcode
- *   Optional: the language code of the text to be filtered, e.g. 'en' for
- *   English. This allows filters to be language aware so language specific
- *   text replacement can be implemented.
- * @param $cache
- *   Boolean whether to cache the filtered output in the {cache_filter} table.
- *   The caller may set this to FALSE when the output is already cached
- *   elsewhere to avoid duplicate cache lookups and storage.
+ * @param $options
+ *   An associative array of options, used to override the defaults. Possible
+ *   values include:
+ *    - cache: Boolean whether to cache the filtered output in the
+ *      {cache_filter} table. The caller may set this to TRUE when the output
+ *      is not being cached elsewhere. Otherwise, this should be left as FALSE
+ *      to avoid duplicate cache lookups and storage. Defaults to FALSE.
+ *    - langcode: the language code of the text to be filtered, e.g. 'en' for
+ *      English. This allows filters to be language aware so language specific
+ *      text replacement can be implemented. Defaults to ''.
+ *    - object: an object from which contextual data can be pulled, such as a
+ *      node object, a user object, or a block. Defaults to NULL for no context.
+ *    - type: a string that identifies the type of object, such as 'node', or
+ *      'user', or 'block'. Defaults to '' for no context.
  *
  * @ingroup sanitization
  */
-function check_markup($text, $format_id = NULL, $langcode = '', $cache = FALSE) {
+function check_markup($text, $format_id = NULL, $options = array()) {
+  $options += array(
+    'cache' => FALSE,
+    'langcode' => '',
+    'object' => NULL,
+    'type' => '',
+  );
+
   if (!isset($format_id)) {
     $format_id = filter_fallback_format();
   }
@@ -726,10 +739,28 @@ function check_markup($text, $format_id = NULL, $langcode = '', $cache = FALSE)
   }
 
   // Check for a cached version of this piece of text.
-  $cache = $cache && !empty($format->cache);
+  $cache = $options['cache'] && !empty($format->cache);
   $cache_id = '';
+
+  // Get a complete list of filters, ordered properly.
+  $filters = filter_list_format($format->format);
+  $filter_info = filter_get_filters();
+
+  $context = array(
+    'langcode' => $options['langcode'],
+  );
+  foreach ($filters as $name => $filter) {
+    if ($filter->status && isset($filter_info[$name]['context callback']) && function_exists($filter_info[$name]['context callback'])) {
+      $function = $filter_info[$name]['context callback'];
+      $result = $function($text, $filter, $format, $options['type'], $options['object']);
+      if (is_array($result)) {
+        $context += $result;
+      }
+    }
+  }
+
   if ($cache) {
-    $cache_id = $format->format . ':' . $langcode . ':' . hash('sha256', $text);
+    $cache_id = $format->format . ':' . hash('sha256', serialize($context)) . ':' . hash('sha256', $text);
     if ($cached = cache_get($cache_id, 'cache_filter')) {
       return $cached->data;
     }
@@ -739,15 +770,11 @@ function check_markup($text, $format_id = NULL, $langcode = '', $cache = FALSE)
   // need to deal with one possibility.
   $text = str_replace(array("\r\n", "\r"), "\n", $text);
 
-  // Get a complete list of filters, ordered properly.
-  $filters = filter_list_format($format->format);
-  $filter_info = filter_get_filters();
-
   // Give filters the chance to escape HTML-like data such as code or formulas.
   foreach ($filters as $name => $filter) {
     if ($filter->status && isset($filter_info[$name]['prepare callback']) && function_exists($filter_info[$name]['prepare callback'])) {
       $function = $filter_info[$name]['prepare callback'];
-      $text = $function($text, $filter, $format, $langcode, $cache, $cache_id);
+      $text = $function($text, $filter, $format, $context, $cache, $cache_id);
     }
   }
 
@@ -755,7 +782,7 @@ function check_markup($text, $format_id = NULL, $langcode = '', $cache = FALSE)
   foreach ($filters as $name => $filter) {
     if ($filter->status && isset($filter_info[$name]['process callback']) && function_exists($filter_info[$name]['process callback'])) {
       $function = $filter_info[$name]['process callback'];
-      $text = $function($text, $filter, $format, $langcode, $cache, $cache_id);
+      $text = $function($text, $filter, $format, $context, $cache, $cache_id);
     }
   }
 
diff --git a/modules/filter/filter.test b/modules/filter/filter.test
index a3d1bde..584d4e8 100644
--- a/modules/filter/filter.test
+++ b/modules/filter/filter.test
@@ -1750,3 +1750,80 @@ class FilterHooksTestCase extends DrupalWebTestCase {
   }
 }
 
+/**
+ * Tests the filter system's contextual data handling.
+ */
+class FilterContextTestCase extends DrupalWebTestCase {
+  protected $format_id;
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Filter context',
+      'description' => 'Tests the ability of the filtering system to incorporate textual data.',
+      'group' => 'Filter',
+    );
+  }
+
+  function setUp() {
+    parent::setUp('filter_test_2');
+    $admin_user = $this->drupalCreateUser(array('administer filters'));
+    $this->drupalLogin($admin_user);
+    $format_name = $this->randomName();
+    $this->drupalPost('admin/config/content/formats/add', array('name' => $format_name, 'format' => strtolower($format_name), 'filters[filter_test_2_context][status]' => TRUE), t('Save configuration'));
+    $this->drupalLogout();
+    $this->format_id = db_query("SELECT format FROM {filter_format} WHERE name = :name", array(':name' => $format_name))->fetchField();
+    filter_formats_reset();
+  }
+
+  /**
+   * Test to make sure that filters are able to use contextual data, and that
+   * the caching system works properly with contextual data changes.
+   */
+  function testFilterContext() {
+    $text1 = $this->randomName();
+    $text2 = $this->randomName();
+    $var1 = (object)array('one' => $this->randomName());
+    $var2 = (object)array('one' => $this->randomName());
+
+    // Text 1 with object 1.
+    $result1 = check_markup($text1, $this->format_id, array('cache' => TRUE, 'type' => 'test', 'object' => $var1));
+    list($success, $text, $var, $rand1) = explode('/', $result1);
+    $this->assertEqual($success, 'Success', 'Context successfully passed.');
+    $this->assertEqual($text, $text1, 'Text matched.');
+    $this->assertEqual($var, $var1->one, 'Contextual variable matched.');
+    $rand_store[] = $rand1;
+
+    // Text 1 with object 1 again - make sure random variable stays the same.
+    $result2 = check_markup($text1, $this->format_id, array('cache' => TRUE, 'type' => 'test', 'object' => $var1));
+    list($success, $text, $var, $rand2) = explode('/', $result2);
+    $this->assertEqual($success, 'Success', 'Context successfully passed.');
+    $this->assertEqual($text, $text1, 'Text matched.');
+    $this->assertEqual($var, $var1->one, 'Contextual variable matched.');
+    $this->assertEqual($rand1, $rand2, 'Filter with contextual data was successfully cached.');
+
+    // Text 1 with object 2 - make sure cache invalidates.
+    $result3 = check_markup($text1, $this->format_id, array('cache' => TRUE, 'type' => 'test', 'object' => $var2));
+    list($success, $text, $var, $rand3) = explode('/', $result3);
+    $this->assertEqual($success, 'Success', 'Context successfully passed.');
+    $this->assertEqual($text, $text1, 'Text matched.');
+    $this->assertEqual($var, $var2->one, 'Contextual variable matched.');
+    $this->assertNotEqual($rand1, $rand3, 'Filter with contextual data successfully invalidated cache.');
+
+    // Back to text 1 with object 1 - cache should still be valid.
+    $result4 = check_markup($text1, $this->format_id, array('cache' => TRUE, 'type' => 'test', 'object' => $var1));
+    list($success, $text, $var, $rand4) = explode('/', $result4);
+    $this->assertEqual($success, 'Success', 'Context successfully passed.');
+    $this->assertEqual($text, $text1, 'Text matched.');
+    $this->assertEqual($var, $var1->one, 'Contextual variable matched.');
+    $this->assertEqual($rand1, $rand4, 'Filter with contextual data did not have cache invalidated.');
+
+    // Text 2 with object 2 - should be entirely new data.
+    $result5 = check_markup($text2, $this->format_id, array('cache' => TRUE, 'type' => 'test', 'object' => $var2));
+    list($success, $text, $var, $rand5) = explode('/', $result5);
+    $this->assertEqual($success, 'Success', 'Context successfully passed.');
+    $this->assertEqual($text, $text2, 'Text matched.');
+    $this->assertEqual($var, $var2->one, 'Contextual variable matched.');
+    $this->assertNotEqual($rand1, $rand5, 'No cache mix-up.');
+    $this->assertNotEqual($rand3, $rand5, 'No cache mix-up.');
+  }
+}
diff --git a/modules/node/node.api.php b/modules/node/node.api.php
index 3e8029c..fa86a1f 100644
--- a/modules/node/node.api.php
+++ b/modules/node/node.api.php
@@ -709,7 +709,7 @@ function hook_node_update_index($node) {
   $text = '';
   $comments = db_query('SELECT subject, comment, format FROM {comment} WHERE nid = :nid AND status = :status', array(':nid' => $node->nid, ':status' => COMMENT_PUBLISHED));
   foreach ($comments as $comment) {
-    $text .= '<h2>' . check_plain($comment->subject) . '</h2>' . check_markup($comment->comment, $comment->format, '', TRUE);
+    $text .= '<h2>' . check_plain($comment->subject) . '</h2>' . check_markup($comment->comment, $comment->format, array('cache' => TRUE, 'type' => 'comment', 'object' => $comment));
   }
   return $text;
 }
diff --git a/modules/profile/profile.module b/modules/profile/profile.module
index 2374fe8..6d6318e 100644
--- a/modules/profile/profile.module
+++ b/modules/profile/profile.module
@@ -286,7 +286,7 @@ function profile_view_field($account, $field) {
   if (isset($account->{$field->name}) && $value = $account->{$field->name}) {
     switch ($field->type) {
       case 'textarea':
-        return check_markup($value, filter_default_format($account), '', TRUE);
+        return check_markup($value, filter_default_format($account), array('cache' => TRUE, 'type' => 'user', 'object' => $account));
       case 'textfield':
       case 'selection':
         return $browse ? l($value, 'profile/' . $field->name . '/' . $value) : check_plain($value);
diff --git a/modules/taxonomy/taxonomy.module b/modules/taxonomy/taxonomy.module
index 50d2fd6..a8aa618 100644
--- a/modules/taxonomy/taxonomy.module
+++ b/modules/taxonomy/taxonomy.module
@@ -697,7 +697,7 @@ function taxonomy_term_view($term, $view_mode = 'full', $langcode = NULL) {
   // Add term description if the term has one.
   if (!empty($term->description)) {
     $build['description'] = array(
-      '#markup' => check_markup($term->description, $term->format, '', TRUE),
+      '#markup' => check_markup($term->description, $term->format, array('cache' => TRUE, 'type' => 'taxonomy_term', 'object' => $term)),
       '#weight' => 0,
       '#prefix' => '<div class="taxonomy-term-description">',
       '#suffix' => '</div>',
diff --git a/modules/taxonomy/taxonomy.pages.inc b/modules/taxonomy/taxonomy.pages.inc
index 3aed290..9016e8d 100644
--- a/modules/taxonomy/taxonomy.pages.inc
+++ b/modules/taxonomy/taxonomy.pages.inc
@@ -67,7 +67,7 @@ function taxonomy_term_feed($term) {
   $channel['title'] = variable_get('site_name', 'Drupal') . ' - ' . $term->name;
   // Only display the description if we have a single term, to avoid clutter and confusion.
   // HTML will be removed from feed description.
-  $channel['description'] = check_markup($term->description, $term->format, '', TRUE);
+  $channel['description'] = check_markup($term->description, $term->format, array('cache' => TRUE, 'type' => 'taxonomy_term', 'object' => $term));
   $nids = taxonomy_select_nodes($term->tid, FALSE, variable_get('feed_default_items', 10));
 
   node_feed($nids, $channel);
diff --git a/modules/taxonomy/taxonomy.test b/modules/taxonomy/taxonomy.test
index 1fd47f5..278573a 100644
--- a/modules/taxonomy/taxonomy.test
+++ b/modules/taxonomy/taxonomy.test
@@ -1099,7 +1099,7 @@ class TaxonomyTokenReplaceTestCase extends TaxonomyWebTestCase {
     $tests = array();
     $tests['[term:tid]'] = $term1->tid;
     $tests['[term:name]'] = check_plain($term1->name);
-    $tests['[term:description]'] = check_markup($term1->description, $term1->format);
+    $tests['[term:description]'] = check_markup($term1->description, $term1->format, array('type' => 'taxonomy_term', 'object' => $term1));
     $tests['[term:url]'] = url('taxonomy/term/' . $term1->tid, array('absolute' => TRUE));
     $tests['[term:node-count]'] = 0;
     $tests['[term:parent:name]'] = '[term:parent:name]';
@@ -1114,7 +1114,7 @@ class TaxonomyTokenReplaceTestCase extends TaxonomyWebTestCase {
     $tests = array();
     $tests['[term:tid]'] = $term2->tid;
     $tests['[term:name]'] = check_plain($term2->name);
-    $tests['[term:description]'] = check_markup($term2->description, $term2->format);
+    $tests['[term:description]'] = check_markup($term2->description, $term2->format, array('type' => 'taxonomy_term', 'object' => $term2));
     $tests['[term:url]'] = url('taxonomy/term/' . $term2->tid, array('absolute' => TRUE));
     $tests['[term:node-count]'] = 1;
     $tests['[term:parent:name]'] = check_plain($term1->name);
diff --git a/modules/taxonomy/taxonomy.tokens.inc b/modules/taxonomy/taxonomy.tokens.inc
index f8ae457..40a7f0c 100644
--- a/modules/taxonomy/taxonomy.tokens.inc
+++ b/modules/taxonomy/taxonomy.tokens.inc
@@ -106,7 +106,7 @@ function taxonomy_tokens($type, $tokens, array $data = array(), array $options =
           break;
 
         case 'description':
-          $replacements[$original] = $sanitize ? check_markup($term->description, $term->format, '', TRUE) : $term->description;
+          $replacements[$original] = $sanitize ? check_markup($term->description, $term->format, array('cache' => TRUE, 'type' => 'taxonomy_term', 'object' => $term)) : $term->description;
           break;
 
         case 'url':
diff --git a/modules/user/user.module b/modules/user/user.module
index de72baf..02ac31f 100644
--- a/modules/user/user.module
+++ b/modules/user/user.module
@@ -3341,7 +3341,7 @@ function user_comment_view($comment) {
     //   hypothetical process of loading, viewing, and saving will hijack the
     //   stored data. Consider renaming to $comment->signature_safe or similar
     //   here and elsewhere in Drupal 8.
-    $comment->signature = check_markup($comment->signature, $comment->signature_format, '', TRUE);
+    $comment->signature = check_markup($comment->signature, $comment->signature_format, array('cache' => TRUE, 'type' => 'comment', 'object' => $comment));
   }
   else {
     $comment->signature = '';
diff --git a/modules/user/user.test b/modules/user/user.test
index 6ecbfac..a304ef0 100644
--- a/modules/user/user.test
+++ b/modules/user/user.test
@@ -1754,7 +1754,7 @@ class UserSignatureTestCase extends DrupalWebTestCase {
     // Assert that the signature did not make it through unfiltered.
     $this->drupalGet('node/' . $node->nid);
     $this->assertNoRaw($signature_text, 'Unfiltered signature text not found.');
-    $this->assertRaw(check_markup($signature_text, $this->plain_text_format->format), 'Filtered signature text found.');
+    $this->assertRaw(check_markup($signature_text, $this->plain_text_format->format, array('type' => 'comment', 'object' => comment_load($comment_id))), 'Filtered signature text found.');
   }
 }
 
