Everything is in the question.
For a notices system to show warnings/errors in the admin, I´m using transient.
When I published my first plugin, I received an email to ask me to sanitize/validate/escape data which inserts in database so…
I´m doing a function to wrap set_transient()
to do this but I´m not sure if in this case is necessary. WordPress should do this.
secure_set_transient
function secure_set_transient( string $transient_name, $value ) {
$f_transient_name = maybe_serialize( esc_attr( sanitize_key( $transient_name ) ) );
$f_value = ( !is_scalar( $value ) ) ? maybe_serialize( $value ) : esc_attr( sanitize_text_field( $value ) );
return set_transient( $f_transient_name, $f_value );
}
-
Is it necessary to use
esc_attr()
,sanitize_key()
andsanitize_text_field()
? -
Do I serialize the non-scalar value?
Everything works if I don´t serialize the array value.
When I use maybe_serialize()
, the data as array is serialized but continue to be a serialzed string when I use get_transient()
.
When I inspect the wordpress core, I can see it´s never serialized but on the top of the function set_transient()
, it´s written : @param mixed $value Transient value. Must be serializable if non-scalar.
I´m a bit confused.
What I suppose to do ?
1 Answer
tl;dr
- Should I serialize the data? No, it will be done for you as long as everything is serializable.
- Should I sanitize/escape the data? Partially. The data will be escaped automatically for you to prevent SQL injection attacks, but you should sanitize and validate it to assure data consistency.
Explanation
If there’s no object cache in place, transients stores the data in the database with $wpdb->update()
, which secures the input from SQL Injection attacks by using PDO prepared statements.
If object cache is in place, it just persists it in the object cache class with WP_Object_Cache::set()
, which performs no sanitization whatsoever. I don’t think this is a problem since object cache doesn’t suffer any kind of injection like SQL does.
It can only be a security issue if you then fetch this data and output it without properly escaping it, so it’s something that you might want to be careful about.
You don’t need to serialize the value, you just have to make sure that if it’s an object, it is serializable (by implementing the Serializable
interface), and if it’s an array, that the values are also serializable. All scalar types are serializable out of the box, such as string, int, float, etc.
This is exactly what @param mixed $value Transient value. Must be serializable if non-scalar.
that you quoted in your question means.
It’s worth mentioning that, for transients being stored in object cache, it’s the duty of the object cache to serialize the value, but I wouldn’t worry about that, since this is a basic feature of any object cache storage. Memcached serializes it by default, while Redis relies on the drop-in to do so, but either way, you can consider object cache to serialize your value for you.