| 1 |
# SDD: WordPress.Security.EscapeOutput.OutputNotEscaped |
| 2 |
|
| 3 |
## Goal |
| 4 |
Ensure all HTML output is escaped in the correct context, reducing PHPCS warnings |
| 5 |
and preventing XSS. |
| 6 |
|
| 7 |
## Scope |
| 8 |
Templates and PHP that use `echo`, `print`, `printf` in `views/`, `inc/`, and `classes/`. |
| 9 |
|
| 10 |
## Project discovery (before changing) |
| 11 |
1. Map all output points. |
| 12 |
2. Reuse existing patterns: |
| 13 |
- `esc_html__`, `esc_html_e`, `esc_attr__`, `esc_attr_e` |
| 14 |
- `esc_html()`, `esc_attr()`, `esc_url()` |
| 15 |
- `wp_kses()` and `wp_kses_post()` when HTML is allowed |
| 16 |
3. When a translated string contains HTML, use `wp_kses()` with an allowlist. |
| 17 |
|
| 18 |
## Decision by context |
| 19 |
- HTML text: `esc_html()` |
| 20 |
- HTML attribute / `data-*`: `esc_attr()` |
| 21 |
- URL: `esc_url()` |
| 22 |
- Inline JS: `esc_js()` or `wp_json_encode()` + `esc_attr()` |
| 23 |
- Allowed HTML: `wp_kses_post()` or `wp_kses( $html, $allowed_html )` |
| 24 |
|
| 25 |
## Implementation patterns |
| 26 |
- Escape at the output boundary, not at the source. |
| 27 |
- Use pre-escaped translation helpers (`esc_html__`, `esc_attr__`, etc). |
| 28 |
- For `printf`/`sprintf`, escape each variable before injecting. |
| 29 |
- Avoid raw `echo $html`; use `wp_kses` with an explicit allowlist. |
| 30 |
- Do not double-escape when the value is already escaped. |
| 31 |
- Do not use `echo esc_html_e()`/`echo esc_attr_e()` (these already echo). |
| 32 |
- For dynamic classes/ids, prefer `esc_attr()` or `sanitize_html_class()` as appropriate. |
| 33 |
|
| 34 |
## Examples |
| 35 |
```php |
| 36 |
echo esc_html( $message ); |
| 37 |
``` |
| 38 |
|
| 39 |
```php |
| 40 |
printf( |
| 41 |
esc_html__( 'Optimized %s images.', 'imagify' ), |
| 42 |
esc_html( $count ) |
| 43 |
); |
| 44 |
``` |
| 45 |
|
| 46 |
```php |
| 47 |
echo wp_kses( |
| 48 |
sprintf( |
| 49 |
__( 'See <a href="%s">documentation</a>.', 'imagify' ), |
| 50 |
esc_url( $url ) |
| 51 |
), |
| 52 |
[ 'a' => [ 'href' => true, 'target' => true, 'rel' => true ] ] |
| 53 |
); |
| 54 |
``` |
| 55 |
|
| 56 |
```php |
| 57 |
echo esc_url( $link ); |
| 58 |
``` |
| 59 |
|
| 60 |
## Exceptions |
| 61 |
- Only for internally built and validated HTML, always run through `wp_kses`. |
| 62 |
- Never ignore `OutputNotEscaped` without a clear justification and review. |
| 63 |
|
| 64 |
## Git Operations |
| 65 |
Do not run `git commit` or `git push`. You may only suggest a commit message. |
| 66 |
|