Repository navigation
Releases: Kamrul5242/khseo-wordpress
Release list
v0.2.0 — Phase 2: technical SEO audit
Phase 1 final hardening and Phase 2A/2B/2C: the first working SEO audit.
MINOR version: new backwards-compatible features. Every feature below has unit and/or
real-WordPress integration tests.
Phase 1 final
- Rules now declare an
evidence_requirement. Only a runtimeRuleResultsays what was
measured on this site, and it cannot carry evidence that contradicts its status
(e.g. NOT TESTED + VERIFIED is rejected). SafeFetcher:- RFC 3986 redirect resolution (
../,./, query-only, fragment, protocol-relative); - HTTPS → HTTP downgrades refused after the full guard check;
- redirects carrying credentials are never silently rebuilt without them.
- RFC 3986 redirect resolution (
UrlGuard: optional trusted origins, the exact scheme+host+port of this site only, so
KHSEO can audit itself on a private network. Credentials and control characters are
still refused, the connection is still pinned, and redirects away are re-checked.- Logger strips terminal escape sequences (ANSI/OSC); the redactor masks secret query
parameters (code,access_token,sig,api_key, …). - Status reports encryption strength: dedicated, standard, degraded (database salt) or unavailable.
- Migrations: a failed step no longer advances the version.
Phase 2A — technical SEO engine
- Bounded HTML parser: libxml, no network, never runs JavaScript, 2 MB parse cap, legacy
charsets converted. Each page is parsed once into aPageSnapshot. - Checks:
- HTTP status, redirects, content type, HTTPS;
- robots meta and X-Robots-Tag (including googlebot-scoped values);
- canonical (missing, multiple, relative, cross-host, mismatch, noindex conflict,
http on https, target status within scope); - title and meta description (missing, empty, multiple, length in characters, markup,
duplicates within scope); - headings (H1, skipped levels, empty),
lang, charset; - images (alt, decorative alt, width/height);
- links (empty text, internal links, broken targets only when fetched in this audit).
- robots.txt parser with universal KHSEO / RFC 9309 semantics. XML sitemap parser that refuses DOCTYPE/ENTITY (XXE).
AuditRunner:- scopes: homepage, one URL on this site, or a sitemap sample;
- hard limits on pages, sitemap files and total bytes;
- resumable steps with a lock, driven by WP-Cron or the dashboard.
Phase 2B — social metadata and structured data
- Open Graph (missing core tags, conflicting values, relative URLs) and Twitter/X cards.
- JSON-LD parser with depth and entity caps; validation of context and type, required
properties for 12 common types, conflicting@id, unknown types, url/sameAs URLs. - INFERRED visible-content checks: the name or headline must appear on the page, and rating
or review markup needs visible review text. - Google Rich Results Test: NOT TESTED.
Phase 2C — findings, score, fixes, UI and API
- Findings table
{prefix}khseo_issues(migration v3, per-site):- deterministic finding keys;
- "ignored" survives re-audits, and stale findings resolve;
- bounded growth (30-day pruning of resolved rows, 20,000-row cap).
- KHSEO Score: deterministic, documented formula with weighted categories and a P0 cap at
49. Unknown and not-tested checks are excluded and shown as coverage. Labelled as
"not a Google ranking score". - Safe fixes: preview → approval of that exact change → recovery point (journal) →
ChangeGate→ apply → validate → rollback (blocked if the value changed since). The
first fix covers search-engine visibility (SEO-INDEX-001, R3). - REST:
GET /status;GET|POST /audit,POST /audit/step,POST /audit/cancel;GET /issues(filters, pagination),GET /issues/{id},POST /issues/{id}/status;POST /fixes/preview|approve|apply|rollback.
- Admin:
- Overview with score, scope, coverage and audit controls (works without JavaScript);
- Issues list with filters;
- issue detail with before/after diff and the change journal;
- audit limits in Settings.
- Detection of other SEO plugins (Yoast, Rank Math, AIOSEO, SEOPress, The SEO Framework,
Slim SEO, Squirrly). KHSEO outputs no metadata (PLANNED).
Tests
- 128 unit tests.
- 138 real-WordPress integration checks:
- full sitemap audit, governed fix with rollback;
- XSS escaping, SQL-injection inertness;
- REST and admin permissions, locking, multisite.
- Mutation-checked: evidence spoofing, score manipulation, unsafe auto-fix, credential
redirect, ChangeGate bypass, secret leak, SQL injection.
Verified: 128 unit tests (PHP 8.1–8.4), 139 real-WordPress integration checks (0 skipped), PHPCS and PHPStan level 8 clean, composer audit clean. Details: docs/QUALITY.md
Phase 2 of 9. The KHSEO Score is an internal diagnostic score, not a Google ranking score. KHSEO does not output metadata yet (PLANNED).
v0.1.1 — Phase 1 hardening
Phase 1 hardening, from a full audit of 0.1.0. Each fix has a regression test.
Security
- Safe Fetcher (
src/Http): the only component allowed to make outbound requests.- Pins the connection to the validated IP with
CURLOPT_RESOLVE(DNS-rebinding defence) and refuses the request if pinning cannot be applied. - Re-validates every redirect hop and caps redirects.
- Enforces connection and total timeouts, a raw-size cap, a decoded-size cap (gzip-bomb guard) and a content-type allow-list.
- A unit test fails the build if code outside
src/Httpcallswp_remote_*, curl,fsockopenor remotefile_get_contents.
- Pins the connection to the validated IP with
UrlGuardrefuses decimal, hex, octal and shortened IPv4 hosts (2130706433,0x7f.1,127.1). curl reads these as loopback. It also treats a trailing dot (localhost.) as the same name and allows only ASCII host names.SecretStore:- never builds a key from WordPress's placeholder salts ("put your unique phrase here"), which would make the key public;
- prefers
KHSEO_SECRET_KEY, then the real wp-config salts, then WordPress's database salt; - no longer causes a fatal error when no key material exists: key saving is disabled and the UI says why;
- rejects non-string, oversized or malformed ciphertext without throwing.
Loggerstores single-line, tag-free messages capped at 500 characters and context capped at 2 KB. Previously a 1 MB entry with a forged second line was stored as-is.
Fixed
- Multisite:
- network activation and uninstall covered only the first 100 sites (
get_sites()default); - sites created after network activation got no KHSEO capabilities. Migration v2 now grants the defaults on each site's first boot.
- network activation and uninstall covered only the first 100 sites (
- REST
/statussaid AI was "configured" when only a key was saved. It now reportsstate(not_configured/key_saved) andfeatures: PLANNED; theconfiguredfield is kept for compatibility. It also reports which encryption key source is in use.
Added
Governance\ChangeGate: the single R0–R4 decision point that future engines must use before applying any change.- Tests:
- 88 unit tests (was 53);
- 76 real-WordPress integration checks (was 30), now including:
- real-HTTP login, nonce and capability attacks on admin-post;
- Safe Fetcher refusals inside WordPress;
- a live DNS-pinning proof;
- multisite activation, per-site isolation and uninstall.
docs/QUALITY.md: the current verified quality status.
Verified: 88 unit tests (PHP 8.1–8.4), 76 real-WordPress integration checks, PHPCS and PHPStan level 8 clean, composer audit clean. Details: docs/QUALITY.md
Phase 1 of 9 — foundation only. SEO engines are not built yet.