Using the Theme Customizer with the Theme Mods API

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.