How to use ACF Fields securely

The ACF (Advanced Custom Fields) plugin has gained popularity among developers for several reasons. The plugin provides a simple and intuitive interface within the WordPress dashboard, allowing developers to easily create and manage custom fields without extensive coding.

ACF significantly speeds up the development process by enabling developers to swiftly incorporate custom fields and meta-data into their themes or templates, reducing the need for extensive custom coding. It is also well-documented, and its active community provides support and resources. This aids developers in troubleshooting issues, finding solutions, and exploring innovative ways to implement custom fields.

As a developer using ACF, I know that there are situations where it’s necessary to store HTML for potentially unsafe output. For example, using a Text Area field to store full <script> tags that users need to edit. In such cases, especially when I’m confident that every registered user on my site has contributor or higher access levels, I recommend using echo get_field() to output this potentially unsafe HTML. This approach ensures that the HTML is not filtered during the output process.

Securing Your ACF Implementation

For all other fields, I’d also recommend using get_field to output the value, but making sure you apply the right escaping for the type of field you need. This is likely to be something like the wp_kses_post function, for example:

echo wp_kses_post( get_field('field_name') );

Disabling the Shortcode

Using the ACF shortcode provides access to any field on any post type. This implies that any user with permission to publish posts on my site can view any ACF data if they know the field name or key. To enhance security, I suggest disabling the shortcode if it’s not actively utilized on my site. This can be done by adjusting the following settings:

add_action( 'acf/init', 'set_acf_settings' );
function set_acf_settings() {
    acf_update_setting( 'enable_shortcode', false );
}

Detection and notice information

If you want to disable the error messages entirely, this is also possible via the following filter:

add_filter( 'acf/admin/prevent_escaped_html_notice', '__return_true' );

This filter will also disable the log being populated when set to true, so if you wish to use this to only hide the messages from certain users, ensure you only add the filter in an is_admin() check.

ACF is actively maintained and updated, ensuring compatibility with the latest WordPress versions and addressing security concerns. This commitment to updates instills confidence among developers using the plugin for various projects.

How to use proper escaping of user input in WordPress

esc_html() escapes a string so that it is not parsed as HTML. Characters like < are converted to &lt;, for example. This will look the same to the reader, but it means that if the value being output is <script> then it won’t be interpreted by the browser as an actual script tag.

Use this function whenever the value being output should not contain HTML.

esc_attr() escapes a string so that it’s safe to use in an HTML attribute, like class="" for example. This prevents a value from breaking out of the HTML attribute. For example, if the value is "><script>alert();</script> and you tried to output it in an HTML attribute it would close the current HTML tag and open a script tag. This is unsafe. By escaping the value it won’t be able to close the HTML attribute and tag and output unsafe HTML.

Use this function when outputting a value inside an HTML attribute.

esc_url() escapes a string to make sure that it’s a valid URL.

Use this function when outputting a value inside an href="" or src="" attribute.

esc_textarea() escapes a value so that it’s safe to use in a <textarea> element. By escaping a value with this function it prevents a value being output inside a <textarea< from closing the <textarea> element and outputting its own HTML.

Use this function when outputting a value inside a <textarea> element.

esc_html() and esc_attr() also have versions ending in __()_e() and _x(). These are for outputting translatable strings.

WordPress has functions, __()_e() and _x(), for outputting text that can be translated. __() returns a translatable string, _e() echoes a translatable string, and _x() returns a translatable string with a given context. You’ve probably seen them before.

Since you can’t necessarily trust a translation file to contain safe values, using these functions when outputting a translatable string ensures that the strings being output can’t cause the same issue described above.

Use these functions when outputting translatable strings.