Skip to content

Tags: WordPress/browser-extension

Tags

v1.0.4

Toggle v1.0.4's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
Security: validate the origin of the popup's REST nonce probe (#118)

## Summary

Fixes a cross-origin disclosure of the WordPress REST nonce, plus a
same-tab
navigation race in the same code path, in the popup's nonce resolution.
Reported privately; a GitHub Security Advisory accompanies this release.
Severity: High.

## The issues

**1. Cross-origin redirect harvest** (`44a54e1`). When the active page
exposed
no REST nonce, `resolveNonceForTab` (`src/popup/lib/actions.js`) fell
back to
fetching `wp-admin/profile.php` with `credentials: 'include'` and
`redirect: 'follow'`, then scraped the `wp_rest` nonce from the response
without checking the final response origin. A page the victim opens the
popup
on could 302 that credentialed request to a WordPress install where the
victim
is a logged-in administrator; the extension followed it with the
victim's
cookies, harvested that origin's real nonce, and handed it to the
content
script on the attacker's origin (forwarded as an `X-WP-Nonce` header to
the
attacker's server).

Fix: refuse to read a nonce from a response whose final origin left the
base
that was probed (an origin-only `res.url` gate, mirroring the
fresh-detection
gate).

**2. Same-tab navigation race** (`d396efe`). The popup captures the
active tab
once, then awaits the nonce fetch before messaging the result back. If
the tab
navigated to another document during that gap, the message (keyed to the
tab
id) delivered the harvested nonce to whatever document then held the
tab.

Fix: bind the nonce to the origin it was read from; the receiving
content
document uses it only when that origin matches its own
`location.origin`.

## Impact

The disclosed secret is the REST nonce, not the session cookie, and a
WordPress nonce is session-bound. But WordPress accepts `_wpnonce` as a
request
parameter and honors the `_method=POST` override on a top-level GET,
which
carries default `SameSite=Lax` auth cookies, so a privileged REST write
such as
administrator-account creation is credible for a logged-in single-site
administrator.

- Affected: all versions before 1.0.4 (the nonce probe was introduced in
0.8.0).
- Patched: 1.0.4.

## Tests

Red-first reproductions: `test/actions.mjs` [49] (redirect harvest) and
[50]
(navigation source-binding), `test/content-lifecycle.js` [46] (receiver
drops a
cross-document nonce). Full suite green, lint clean, `dist/` and the
Safari
mirror in sync.

## Also in this PR

- Version bump to 1.0.4 (macOS build 5).
- `3de0ddb`: doc/preview cleanup, no shipped-behavior change.

A separate REST-helper `redirect: 'error'` hardening (defense in depth)
is
parked on `defer/rest-redirect-policy` and intentionally not included
here.

v1.0.3

Toggle v1.0.3's commit message

Unverified

This user has not yet uploaded their public signing key.
v1.0.3: version bump across manifest, package, lockfile, and Xcode pr…

…oject

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

v1.0.2

Toggle v1.0.2's commit message

Unverified

This user has not yet uploaded their public signing key.
Tests: state the [44] fallback coverage honestly

The block drives the derivation helper and target synthesis with the
real libs; it does not drive the React hook pipeline its comment
implied. Wording corrected per review; true integration coverage is a
possible follow-up.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

v1.0.1

Toggle v1.0.1's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
v1.0.1: version bump (#82)

Version bump for the coordinated store launch. 1.0.1 supersedes 1.0.0 as
the launch version: the approved Apple 1.0.0 build 1 predates the #76 QA
pass and the #81 popup hardening, so it releases quietly as a safeguard
while 1.0.1 (this content) ships everywhere as the announced version.

Checklist: manifest.json, package.json, package-lock.json (npm install
--package-lock-only), MARKETING_VERSION in four build configs, Safari
Resources mirror re-synced. CURRENT_PROJECT_VERSION stays 2 (#80; build
2 was never uploaded). Full test suite passes locally.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

v1.0.0-rc2

Toggle v1.0.0-rc2's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
Follow-up to #76: block-inspector precedence test, ROADMAP truth-up (#78

)

Lands the two follow-ups from the #76 review, plus one piece of
local-tooling hygiene.

## Regression test for the precedence fix

#76's change to `loadBlockInspectorPref` shipped with no coverage; the
review verified empirically that reintroducing the exact bug the new
guard prevents (explicit per-origin `false` falling through to a
`_global` `true`) passed the whole suite. New content-lifecycle block
[41] closes that: it stubs `WPDBlockInspector` on the harness context
and asserts all four precedence outcomes through the real content
script. The suite is now 286 assertions; the injected-regression check
fails as intended with the new block in place.

## ROADMAP accuracy

Store states an external contributor cannot see from the repo:

- v0.11.x status now reads "readiness complete; CWS submission approved,
publication pending" — the unlisted Chrome Web Store submission is
approved but has not been published, so "shipped" overstated it.
- The Safari row moves the App Store Connect record, listing assets, and
the submitted 1.0.0 build into Done, with App Review outcome as the
remaining gate; status is now "in review". The store-readiness checklist
ticks the bundle-identifier rename (#72) and the publisher account to
match.

## eslint ignore for build/

`build/` (gitignored since #75) holds the App Store archive and exported
installer. The archived `.app` contains copies of the shipped bundles,
so a local archive breaks `npm run lint` with ~175 errors on files that
are not lintable source. Added to the eslint ignores alongside
`safari-build/`.

No runtime changes; `dist/` untouched.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

v1.0.0-rc1

Toggle v1.0.0-rc1's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
v1.0.0: version bump (#73)

Version bump to 1.0.0, to be released first as the 1.0 release candidate
(tagged v1.0.0-rc1, GitHub pre-release).

Functionally identical to v0.11.2. The only change since is internal
Apple App Store preparation: Safari bundle identifiers moved to
org.wordpress.browserextension under the WordPress Foundation developer
account (#72).

Bump checklist: manifest.json, package.json, package-lock.json (npm
install --package-lock-only), MARKETING_VERSION in four build configs,
Safari Resources mirror re-synced. Full test suite passes locally.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

v0.11.2

Toggle v0.11.2's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
v0.11.2: version bump (#70)

Release metadata bump for 0.11.2.

## In this release

- Mobile Preview keeps one window per site: a repeat click reuses the
open preview, navigating it to the requested page and focusing it;
distinct sites keep distinct windows (#66, #67, #69).
- Dev-dependency security updates: ws 7.5.11 (#64), websocket-driver
0.7.5 (#68). Lockfile only, no shipped-code impact.

## Bump checklist

- manifest.json version
- package.json version
- package-lock.json (npm install --package-lock-only)
- MARKETING_VERSION in the four Safari build configs
- Safari Resources mirror re-synced (manifest picked up the new version)

Full test suite passes locally; CI runs the clean-rebuild dist/mirror
drift check.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

v0.11.1

Toggle v0.11.1's commit message
v0.11.1: store-facing summary copy

v0.11.0

Toggle v0.11.0's commit message
v0.11.0: Chrome Web Store readiness — permissions rationale + activeT…

…ab package trim (#61), privacy policy, lint + CI, shortcut hint fix