php8.5
Home/ Manual/ reference / taint/ Propagation and Checked Sinks

Propagation and Checked Sinks

The taint mark is a single bit stored on the string itself, not on the variable holding it. Assigning, passing or otherwise sharing a tainted string keeps the mark. String concatenation and interpolation propagate it as well:

How the taint mark is propagated

The taint mark is a single bit stored on the string itself, not on the variable holding it. Assigning, passing or otherwise sharing a tainted string keeps the mark. String concatenation and interpolation propagate it as well:

= (assignment, including list()/array destructuring)
. (concatenation)
.= (concatenating assignment)
"{$var}" (string interpolation, including the ROPE fast path)

In addition, taint understands a fixed set of string functions: when any of the relevant string arguments is tainted, the returned string is marked tainted too. Both the regular call and, on PHP 8.4+, the frameless fast-path call are covered.

trim(), rtrim(), ltrim()
substr(), strstr()
str_replace(), str_ireplace()
str_pad(), strtolower(), strtoupper(), strval()
explode() (every element of the resulting array)
implode()/join() (a tainted separator taints the result as well)
sprintf(), vsprintf() (only the %s specifier carries the mark; sprintf("%d", $t) returns a clean string)
dirname(), basename(), pathinfo()

Any function taint does not explicitly understand returns a fresh, unmarked string — including escaping helpers such as htmlspecialchars(), htmlentities() or mysqli_real_escape_string(). This is deliberate: taint over-reports rather than trying to decide whether a value is safe for a particular output context. Use untaint() to clear the mark on values you have validated yourself.

Where taint raises warnings

When a tainted string reaches one of the sinks below, taint raises a warning (by default an E_USER_WARNING; the level is configurable via taint.error_level). Only top-level string arguments are inspected; dumping an array that merely contains tainted values does not warn.

SinkChecked
echo, printthe echoed/printed expression
printf(), vprintf()the format string and the substituted values
print_r(), var_dump(), var_export()the value being dumped, when it is a string
exit/die with a messagethe message
file_put_contents(), fwrite(), fputs() to php://outputthe data being written
SinkChecked
fopen(), opendir(), unlink()the path
file(), readfile(), file_get_contents(), highlight_file()/show_source()the path
copy(), rename(), move_uploaded_file()both the source and destination paths
mkdir(), rmdir(), touch()the path
include, include_once, require, require_oncethe file path
SinkChecked
mysqli_query(), mysqli_prepare(), mysqli_real_query(), mysqli_multi_query()the query string
mysql_query(), sqlite_query(), sqlite_single_query(), oci_parse(), pg_query(), pg_send_query()the query string
mysqli::query, mysqli::prepare, mysqli::real_query, mysqli::multi_querythe query string
PDO::query, PDO::prepare, PDO::execthe query string
SQLite3::query, SQLite3::prepare, SQLite3::exec, SQLiteDatabase::query, SQLiteDatabase::singleQuerythe query string
SinkChecked
exec(), system(), passthru(), shell_exec() (including the backtick operator)the command string
proc_open(), popen()the command string
evalthe evaluated code
dynamic calls such as $func(), $obj->$method(), call_user_func(), array callablesthe function/method/class name being resolved
preg_match(), preg_match_all(), preg_replace(), preg_split(), preg_grep(), preg_replace_callback()the pattern (and the callback name for preg_replace_callback())
SinkChecked
header()the header string
setcookie(), setrawcookie()the cookie name and value
SinkChecked
unserialize()the serialized string
mail()to, subject, additional parameters and additional headers (the message body is content and is not checked)

Warnings follow the format function_name() [sink]: message, where sink identifies the checked operation (for example echo, include or the function name) and the message describes what was found to be possibly tainted.

Source: reference/taint/detail.xml · from the official PHP manual (php/doc-en)