Here’s what I changed and why:
shortcode_ga_ua.php / shortcode_ga_g.php — the two files with the actual issues:
- Added
if (!defined('ABSPATH')) exit;at the top. Without it, the file could be requested directly, which WP.org guidelines require guarding against. - Added a regex check (
^[A-Za-z0-9\-]{1,30}$) that the stored option value looks like a real GA/UA code before echoing anything. This stops garbage or crafted values from ever reaching the page. - Wrapped the value in
esc_js()before writing it into the inline<script>block, andrawurlencode()+esc_url()for the value used in thesrcattribute. Previously the option value was interpolated straight into HTML/JS with no escaping — WP.org’s automated plugin checker flags this as “output not escaped” and it’s a real stored-XSS vector if the option ever contained something unexpected (e.g. from a database import, a bug elsewhere, or a compromised admin account). - Lowercased
ECHO→echoto match WordPress Coding Standards (PHP is case-insensitive here, but WPCS/PHPCS will flag the uppercase form).
form.php — added an explicit current_user_can('manage_options') check with wp_die() at the top of adminForm_quickgoogleanalytics(). The page was already gated via add_options_page(..., 'manage_options', ...), so this wasn’t exploitable, but the review team wants that capability check repeated in the function that actually processes the save actions, not just relied on indirectly through menu registration.
quickgoogleanalytics.php — added an explicit Text Domain: quick-google-analytics header. It worked without it (WP falls back to the folder name since 4.6), but explicit is what the guidelines ask for.
Removed from the package: sync.sh (your personal deploy script with SSH key path, username, and server host — should never ship inside the plugin zip) and the duplicate README.md (only readme.txt is read by wp.org, so it was just dead weight).
Everything else (nonces, sanitize_text_field, wp_kses, uninstall.php) was already solid and untouched.
