Several developers are hooking into the awesome Theme Customizer API, and in many places even replacing traditional Theme Settings pages with the Theme Customizer. This is a great development, but there’s one caveat when using the Theme Mods API (as opposed to the Settings API): you have to be sure to sanitize on input.
With the Settings API, the Theme registers its setting via register_setting(), which accepts a sanitization callback as one of its parameters. When you hook into the Theme Customizer with Settings API-defined options, the user-input option data are automatically passed through the defined sanitization callback. But the Theme Mods API is designed to be much simpler (and generally more user-friendly), and has no analogous method to define a sanitization callback. That means that user-input option data must be explicitly sanitized on input.
Fortunately, the Theme Customizer API provides a way to sanitize Theme Mods option data: the ‘sanitize_callback’ parameter of the add_setting() argument array. Didn’t know about that parameter? Don’t worry; neither did I until recently. It’s so super-secret that it’s not even listed in the add_setting() method Codex entry. Fortunately, Konstantin Obenland discusses it here.
Here’s an example. Let’s say the setting is for a slider speed option. The user is expected to enter an integer (in seconds). Here are typical add_setting() and add_control() method calls:
$wp_customize->add_setting( 'prefix_slider_speed', array( 'default' => '5' ) ); $wp_customize->add_control( 'prefix_slider_speed', array( 'label' => __( 'Animation Speed in Seconds', 'textdomain' ), 'section' => 'prefix_slider_section', 'settings' => 'prefix_slider_speed', 'type' => 'text' ) );
See the problem? The user can enter anything into that text field, and WordPress will dutifully add the user-input data into the database, and output it upon request, via get_theme_mod(). What happens if the user inputs the following?
1000" onclick="javascript:alert(1)" data-foo="
(Note: don’t try this at home, kids)
Enter ‘sanitize_callback’:
$wp_customize->add_setting( 'prefix_slider_speed', array( 'default' => '5', 'sanitize_callback' => 'prefix_sanitize_integer' ) );
Once the callback is referenced, you just need to declare it (if it’s a custom function; in many cases, including this one, you could simply pass a core-defined sanitization function here and be done):
function prefix_sanitize_integer( $input ) {
return absint( $input );
}
Now, the saved input is sanitized as an actual integer.
There are several valid sanitization methods; the key here is to ensure that you’re aware of the need to perform sanitization.
P.S. Anyone want to show the Customizer API Codex entries some love? The sanitize_callback parameter isn’t mentioned, and none of the method entries have source references.