security
Installation
SKILL.md
Security
Escape output at the point you print it, sanitize and validate input where it arrives, and check permissions before acting. Read Escaping Data for the full list of functions.
PHP output
- Escape for the context you print into:
esc_html()for text,esc_attr()for attribute values,esc_url()forhrefandsrc,wp_kses_post()for HTML that must keep its markup. Translated strings too:esc_html__(),esc_attr__(). - In a render callback, every block attribute, post meta value, option and
theme.jsonvalue is untrusted, however numeric or preset-like it looks. A registered attribute's schema checks its type, not its content. - Print
$content(the rendered inner blocks) as is.get_block_wrapper_attributes()escapes the values you pass it but not the attribute names, so keep names literal. WP_HTML_Tag_Processor::set_attribute()escapes the value and passes URL attributes throughesc_url(). Pass the raw value: it encodes every&, so a pre-escaped value shows&. It does not make anon*orstylevalue safe.safecss_filter_attr()drops disallowed CSS but does not escape HTML:"><script>passes through. Print its result withesc_attr()orset_attribute().- JSON printed inside an inline
<script>goes throughwp_json_encode()withJSON_HEX_TAG.
Input and permissions
- Sanitize with the function for the type (
sanitize_text_field(),absint(),sanitize_key()), then validate against what you expect. See Sanitizing Data and Data Validation. - A REST route argument with a
typeis validated and sanitized against its schema. One with notypeand no callbacks reaches your callback raw. - For a file name from input, allow only the characters you expect (
sanitize_key()or a strict pattern) and join it to a known directory. For a full path, check that itsrealpath()stays inside the base directory.validate_file()is not enough: it returns0for..,foo/..and absolute paths. - Design every API around who may read and who may change its data, and enforce that on the server. Check capabilities with
current_user_can()(in a REST route, from itspermission_callback;__return_trueonly for data logged-out visitors may read), prefer an object-level check such ascurrent_user_can( 'edit_post', $post_id )over a blanketedit_posts, and return only data the caller is allowed to see. See Roles and Capabilities.