Advanced Custom Fields (ACF 5)
Advanced Custom Fields (ACF) is a popular plugin that many VIP clients choose to use on their sites. However, ACF has not undergone a full, line-by–line review for use on WordPress VIP. Clients wishing to use ACF accept the security and performance risks of using it. This page outlines some additional steps needed to make ACF more secure and performant, but should not be interpreted as the equivalent of a line-by-line review, or VIP’s approval of the plugin.
Please note that while ACF version 5 can be used on most VIP Go sites (at customer discretion), ACF 4 should not be used.
Steps to avoid performance issues
When using ACF 5 and ACF 5 Pro, several additional steps are needed in order to make ACF secure, and avoid performance issues:
- Hide the Admin UI
- Define fields in PHP
- Use taxonomies for searchable fields
- Avoid
the_field
 and escape all output viaget_field
- Secure fields that allow arbitrary output
Hide the ACF Admin UI
The fields UI can be used to add arbitrary fields, including unsafe fields. For example it can allow an admin to display the passwords of users. You can disable the UI using this filter:
add_filter( 'acf/settings/show_admin', '__return_false' );
Define fields in PHP
In order to make sure that all ACF usage is secure, define the fields in PHP or local JSON, rather than at runtime. This way they remain versioned and safe. This can be done via the import export menu of a local developer environment to set up the fields available and export them to PHP.
Documentation on how to do this can be found on the ACF website.
Alternatively, fields can be defined via the local JSON feature as described here, but keep in mind: saving local JSON will not work because the WordPress VIP filesystem is read only, and it would also bypass the security benefits
Being mindful of taxonomy term storage
If an ACF field is going to be queried, filtered, or searched for in a post query, use the taxonomy data checkbox so that the field is stored as a term, not a post meta value. This ensures performance is not impacted by expensive post meta queries while generating HTML for readers.
the_field
and output escaping
the_field
(which echoes field values) has no ability to know the context it’s called in, so it doesn’t know if it should be using esc_url
, esc_attr
or wp_kses_post
, which makes it a security risk; it should never be used. Instead, use get_field
in combination with an escaping function:
$url = get_field( 'custom_link' );
echo esc_url( $url );
Flexible content is the exception to this, and should be clearly marked when used in code via inline comments.
Fields that use arbitrary output
If field types that allow arbitrary output are to be used, they must be accounted for in the acf/format_value
and equivalent filters such as acf/format_value/type=textarea
.
For example:
function vip_make_acf_text_areas_safe( $value, $post_id, $field ) {
return wp_kses_post( $value );
}
add_filter( 'acf/format_value/type=textarea', 'vip_make_acf_text_areas_safe', 10, 3 );
This way, different escaping can be applied via different '$field'
values. Alternatively, if all fields of that type use the same escaping, this can be done instead:
add_filter( 'acf/format_value/type=textarea', 'wp_kses_post', 10, 1 );
More information on format_value
can be found here.
Working with image fields
Due to how VIP Go handles intermediate image sizes, when working with image fields that use ‘Image Array’ or ‘Image ID’ return format, the ‘sizes’ array will be empty in the field value. So instead of directly accessing your preferred file size URL with $field_value['sizes']['large']
, themes will need to use the returned image ID to retrieve the correct URL:
<?php
$my_image_field = get_field('image');
?>
<img src="<?php echo esc_url( wp_get_attachment_image_src( $my_image_field['ID'], 'large' )[0] );?>" alt="<?php echo esc_attr( $my_image_field['alt'] ); ?>" />