# SDD: WordPress.Security.ValidatedSanitizedInput ## Goal Ensure any input read from GET/POST/COOKIE/SERVER/REQUEST is unslashed, validated, and sanitized before use, reducing PHPCS warnings and security risk. ## Scope Files in `inc/`, `classes/`, and `views/` that read superglobals or external input. ## Project discovery (before changing) 1. Map access to `$_GET`, `$_POST`, `$_REQUEST`, and `$_SERVER`. 2. Reuse existing patterns: - `sanitize_text_field( wp_unslash( $_GET['foo'] ) )` - `sanitize_email( wp_unslash( $_POST['email'] ) )` - `absint( wp_unslash( $_GET['id'] ) )` - `sanitize_key()` + allowlist (`in_array`) for filters/ordering - `array_map( 'absint', (array) wp_unslash( $_GET['ids'] ) )` 3. Verify nonces for admin actions (see `.aiassistant/specs/phpcs/nonce-verification-recommended.md`). ## Decision (quick tree) 1. Is the input from a superglobal? If yes, apply `wp_unslash()`. 2. Is there a clear type/allowlist? Validate before use. 3. Sanitize with the correct function for the context. 4. If invalid/missing, use a safe default. ## Implementation patterns - **MissingUnslash**: always `wp_unslash()` before `sanitize_*`. - **InputNotSanitized**: apply `sanitize_*` or `esc_url_raw()`. - **InputNotValidated**: validate with allowlist, `absint`, `filter_var()`, or controlled regex. - Prefer `filter_input()`/`filter_input_array()` with `FILTER_SANITIZE_*` when possible. - If `filter_input()` returns `null` but `$_GET`/`$_POST` is set, fall back to `sanitize_text_field( wp_unslash( $_GET['field'] ) )` for compatibility. - Avoid `$_REQUEST`; prefer `$_GET` or `$_POST`. - For arrays, sanitize each item with `array_map`. - For URLs: `esc_url_raw()` + optionally `filter_var( ..., FILTER_VALIDATE_URL )`. - For multiline text: `sanitize_textarea_field()` (do not use `sanitize_text_field`). - For allowed HTML: `wp_kses_post()` (only when needed and documented). - For boolean flags: `filter_input( INPUT_POST, 'flag', FILTER_VALIDATE_BOOLEAN )` or `(bool) filter_input(...)`. - For filters/ordering (GET without side effects): validate nonce and allowlist. ## Examples ```php check_admin_referer( 'imagify_settings_save' ); $level = isset( $_POST['optimization_level'] ) ? absint( wp_unslash( $_POST['optimization_level'] ) ) : 1; ``` ```php $allowed = [ 'success', 'error', 'already_optimized' ]; $status = isset( $_GET['status'] ) ? sanitize_key( wp_unslash( $_GET['status'] ) ) : ''; $status = in_array( $status, $allowed, true ) ? $status : ''; ``` ```php $ids = isset( $_GET['ids'] ) ? array_map( 'absint', (array) wp_unslash( $_GET['ids'] ) ) : []; ``` ## Git Operations Do not run `git commit` or `git push`. You may only suggest a commit message. ## Verification - Run `composer phpcs` and confirm there are no: - `WordPress.Security.ValidatedSanitizedInput.InputNotSanitized` - `WordPress.Security.ValidatedSanitizedInput.InputNotValidated` - `WordPress.Security.ValidatedSanitizedInput.MissingUnslash`