Hi everyone. The REST API The REST API is an acronym for the RESTful Application Program Interface (API) that uses HTTP requests to GET, PUT, POST and DELETE data. It is how the front end of an application (think “phone app” or “website”) can communicate with the data store (think “database” or “file system”) https://developer.wordpress.org/rest-api/. team recently discovered a bug A bug is an error or unexpected result. Performance improvements, code optimization, and are considered enhancements, not defects. After feature freeze, only bugs are dealt with, with regressions (adverse changes from the previous version) being the highest priority. with parameter parsing in the API An API or Application Programming Interface is a software intermediary that allows programs to interact with each other and share data in limited, clearly defined ways. infrastructure, part of WordPress 4.4. For those of you using the API infrastructure, you need to be aware of a bug fix we’re making with the API.
The Problem
The REST API has several types of parameters that it mixes together. These come from several sources including the request body as either JSON JSON, or JavaScript Object Notation, is a minimal, readable format for structuring data. It is used primarily to transmit data between a server and web application, as an alternative to XML. or URL A specific web address of a website or web page on the Internet, such as a website’s URL www.wordpress.org-encoded form data ($_POST
), query parameters ($_GET
), the API route, and internally-set defaults. Unfortunately, due to an oversight on our behalf, these parameters can be inconsistently formatted.
In WordPress, the superglobal request variables ($_POST
and $_GET
) are “slashed”; effectively, turning magic quotes on for everyone. This was originally built into PHP The web scripting language in which WordPress is primarily architected. WordPress requires PHP 7.4 or higher as a feature to help guard against SQL injection, but was later removed. Due to compatibility concerns, WP cannot change this behaviour for the superglobals. This only applies to the PHP superglobals, not to other sources of input like a JSON body or parameters in the URL. It additionally does not apply to form data on PUT or DELETE requests.
Internally, some low-level WordPress functions expect slashed data. These functions internally call wp_unslash()
on the data you pass in. This means input data from the superglobals can be passed in directly, but other data needs to be wrapped with a call to wp_slash()
.
When the REST API gathers the data sources, it accidentally mixes slashed and unslashed sources. This results in inconsistent behaviour of parameters based on their source. For example, data passed as a JSON body is unslashed, whereas data passed via form data in the body is slashed (for POST requests).
For example, the following two pieces of data are equivalent in the REST API:
// JSON body:
{"title": "Foo"}
// Form-data ($_POST)
title=Foo
// Both result in:
$request->get_param('title') === 'Foo';
However, if the data contains slashes itself, this will be inconsistently passed to the callback:
// JSON body:
{"title": "Foo\Bar"}
// Results in:
$request->get_param('title') === 'Foo\Bar';
// Form-data ($_POST) (%3D = "\")
title=Foo%3DBar
// Results in:
$request->get_param('title') === 'Foo\\Bar';
This means that callbacks need to understand where parameters come from in order to consistently handle them internally. Specifically:
- Data passed in the query string (
$_GET
, $request->get_query_params()
) is slashed
- Data passed in the body as form-encoded (
$_POST
, $request->get_body_params()
) is slashed for POST
requests, and unslashed for PUT
and DELETE
requests.
- Data passed in the body as JSON-encoded (
$request->get_json_params()
) is unslashed.
- Data passed in the URL (
$request->get_url_params()
) is unslashed.
- Data passed as a default (
$request->get_default_params()
) is unslashed.
In addition, parameters set internally via $request->set_param()
are unslashed. Unit and integration tests for API endpoints typically use these directly, so the majority of tested code (such as the WP REST API plugin A plugin is a piece of software containing a group of functions that can be added to a WordPress website. They can extend functionality or add new features to your WordPress websites. WordPress plugins are written in the PHP programming language and integrate seamlessly with WordPress. These can be free in the WordPress.org Plugin Directory https://wordpress.org/plugins/ or can be cost-based plugin from a third-party) assumes parameters are unslashed.
See the related Trac An open source project by Edgewall Software that serves as a bug tracker and project management tool for WordPress. Ticket Created for both bug reports and feature development on the bug tracker. #36419 for more information.
The Solution for WordPress 4.4 and 4.5
We are regarding inconsistently-slashed data as a major bug, and are changing the API infrastructure to ensure unslashed data. This will ensure that data is consistent regardless of the source. Callbacks will now receive unslashed data only, and can rely on this regardless of the original data source or request method.
If you are using functions that expect slashed data in your callback, you will need to slash your data before passing into these functions. Commonly used functions that expect slashed data are wp_insert_post
, wp_update_post
, update_post_meta
, wp_insert_term
, wp_insert_user
, along with others. Before passing data into these functions, you must call wp_slash()
on your data.
The fix for this issue, will be included in the WordPress 4.5 release candidates and final release. Due to the severity The seriousness of the ticket in the eyes of the reporter. Generally, severity is a judgment of how bad a bug is, while priority is its relationship to other bugs. of the bug, we are also backporting the fix to the next minor WordPress 4.4 update. This also ensures you can update your plugins can act consistently across all versions of the REST API.
We understand that this may inadvertently break some plugins that are expecting slashed data. Right now, it’s not possible to consistently ensure that callbacks receive slashed data, so it is likely that these plugins will already break in some conditions.
tl;dr: if you’re using wp_insert_*
or *_post_meta
in your REST API callback, you need to ensure you are calling wp_slash()
on data you are passing in, regardless of source.
We apologize for this bug existing in the first place. Slashed data is a problem that has plagued WordPress for a long time, and we’re not immune to getting caught by the issue ourselves.
#4-4, #4-5, #rest-api