WP Manifestindependent plugin directory
manifest / updates / wss-core

WSS Core WP Registry grade D+. High-severity findings · 3 findingsWP RegistryHigh-severity findings · 3 findingsOpen the reportD+

Webshopsschool Core Plug-in for clients by @joey.developer

★ 0stars
154release downloads
≈20active sites
1.13.0latest · 4mo ago

Install

Download wss-core.zip From the 1.13.0 release on GitHub, Jun 19, 2026

Upload it under Plugins → Add New Plugin → Upload Plugin, then activate.

Install straight from GitHub with WP-CLI:

wp plugin install https://github.com/ecomscene/wss-core/releases/download/1.13.0/wss-core.zip
Updates itself. It ships its own updater, so new versions appear under Dashboard → Updates.

Lightweight base plugin for Webshopschool client websites. No frontend/admin features yet — it exists as a stable foundation that can auto-update from GitHub so future functionality can be rolled out to all client sites by publishing a new release.


How it works

  • The plugin polls https://api.github.com/repos/{owner}/{repo}/releases/latest (cached for 6 hours).
  • It compares the GitHub release tag against the installed version.
  • If the release tag is newer, WordPress shows an update notice exactly like a wordpress.org plugin.
  • Update package preference:
    1. A release asset named wss-core.zip (recommended — produced by the bundled GitHub Action).
    2. Otherwise the auto-generated GitHub zipball_url (the folder rename is corrected automatically).
  • The Update URI header points to GitHub so the wordpress.org updater never collides with this plugin.

Configuration

Edit includes/class-wss-core.php:

const GITHUB_OWNER = 'webshopschool';
const GITHUB_REPO  = 'wss-core';

That is the only configuration. Everything else is derived from the plugin headers.


Setup guide

1. Create the GitHub repository

  1. Create a new public GitHub repo (e.g. webshopschool/wss-core).
  2. Update GITHUB_OWNER and GITHUB_REPO in includes/class-wss-core.php to match.

2. Upload the plugin

git init
git remote add origin git@github.com:webshopschool/wss-core.git
git add .
git commit -m "Initial commit: WSS Core 1.0.0"
git branch -M main
git push -u origin main

3. Create the first release

  1. Bump the version in both:
    • wss-core.php — Version: header and WSS_CORE_VERSION constant.
    • readme.txt — Stable tag:.
  2. Commit and push.
  3. On GitHub: Releases → Draft a new release.
  4. Tag: 1.0.1 (plain SemVer — 1.0.1, 1.1.0, 2.0.0, …). v1.0.1 also works but plain is preferred.
  5. Title: 1.0.1.
  6. Write release notes — they appear in the WP "View details" modal.
  7. Publish release.
  8. The bundled GitHub Action automatically builds and attaches wss-core.zip to the release. Wait ~1 minute for it to finish.

4. Install on a client website

Three options:

A. Manual install (first time):

  1. Download the wss-core.zip asset from the GitHub release.
  2. WP admin → Plugins → Add New → Upload Plugin → choose the zip → Install → Activate.

B. SFTP/SSH:

  • Upload the wss-core folder to wp-content/plugins/.
  • Activate via WP admin.

C. WP-CLI:

wp plugin install https://github.com/webshopschool/wss-core/releases/latest/download/wss-core.zip --activate

5. Push a future update

  1. Make your changes.
  2. Bump Version: in wss-core.php, WSS_CORE_VERSION, and Stable tag: in readme.txt.
  3. Commit & push.
  4. Draft a new release with the matching tag (e.g. 1.0.2).
  5. Publish — within 6 hours every client site sees an update notice in Plugins → Installed Plugins. Click "update now" as usual.
  6. To force an immediate check, visit Dashboard → Updates → Check again or run wp plugin update wss-core.

Folder-name caveat

WordPress requires the unzipped plugin folder to be named exactly wss-core/.

  • GitHub auto-generated zipballs unpack into a folder like webshopschool-wss-core-abc1234/ — this plugin's updater automatically renames that to wss-core/ during installation, so it still works.
  • But the safest approach is to ship a release asset named exactly wss-core.zip containing a top-level wss-core/ folder. The included GitHub Action (.github/workflows/release.yml) does this for you on every release.

Cache & debugging

  • Release data is cached in a transient (wss_core_github_release) for 6 hours.
  • Failed API calls cache an error marker for 15 minutes to prevent hammering GitHub.
  • The transient is cleared automatically when WSS Core itself updates and on activation/deactivation.
  • Force-clear manually:
    wp transient delete wss_core_github_release
    wp transient delete update_plugins --network

Private repos

Currently public-only. To support a private repo you would need to send an Authorization: token … header in wp_remote_get() and use the asset API URL (not browser_download_url) with Accept: application/octet-stream. Out of scope for v1.0.0.

Releases

15 releases. Each count is every asset in that release; expand a row for the breakdown.

Tag
Published
Assets
Downloads
1.13.0 latest
Jun 19, 2026 4mo ago
wss-core.zip
54
Jun 18, 2026 4mo ago
wss-core.zip
24
Jun 4, 2026 4mo ago
wss-core.zip
28
Jun 1, 2026 5mo ago
wss-core.zip
7
May 28, 2026 5mo ago
wss-core.zip
16
May 28, 2026 5mo ago
wss-core.zip
9
May 27, 2026 5mo ago
wss-core.zip
3
May 25, 2026 5mo ago
wss-core.zip
9
May 25, 2026 5mo ago
wss-core.zip
0
May 17, 2026 5mo ago
wss-core.zip
2
May 17, 2026 5mo ago
wss-core.zip
0
May 17, 2026 5mo ago
wss-core.zip
0
May 14, 2026 5mo ago
wss-core.zip
0
May 14, 2026 5mo ago
wss-core.zip
1
May 14, 2026 5mo ago
wss-core.zip
1

Active-site estimate ≈20 comes from the median of recent superseded releases. Method.

D+ grade

Security

WSS Core 1.13.0 · audited by WP Registry

High-severity findings.

2 high 1 medium
Audited release
1.13.0
Findings
3
Worst severity
high
Content hash
793c79b68644152939b64033…

Findings

  • high Hub-synced PHP snippets executed via eval() on every request

    eval_by_design

    WSS_Snippets::run_php_snippets loads active snippets from option OPT_SNIPPETS (populated by signed hub sync when status=approved) and passes each type=php snippet through safe_eval(), which strips a leading <?php tag and eval()s the code. Anyone who controls the hub or the stored site secret can deliver arbitrary PHP that runs as the web server user on plugins_loaded. This is intentional remote code execution surface for managed hosting.

    includes/class-wss-snippets.php:37-87

    Recommendation

    Avoid eval of remotely supplied code where possible; if retained as a product feature, isolate execution (separate process/user), require explicit local admin approval per snippet, and document that hub compromise equals full site RCE. Prefer file-based mu-plugins written only after dual control.

  • high HMAC REST endpoints can read and overwrite wp-config.php and theme functions.php

    file_access

    WSS_Webhook registers POST/GET /wss-core/v1/wp-config and /theme-functions with permission_callback authorize (HMAC). handle_wp_config_get returns full file contents; handle_wp_config_post and handle_theme_functions_post write attacker/hub-supplied content via file_put_contents after a token_get_all syntax check. Combined with plugin-action/self-update routes, a valid site secret yields complete remote site control without a WordPress admin session.

    includes/class-wss-webhook.php:102-253

    Recommendation

    Remove remote wp-config/theme-functions write from the default build, or require an additional local confirmation token. At minimum, deny reading secrets-bearing files over the wire and restrict writes to a narrow allowlisted set of constants. Treat OPT_SITE_SECRET like a root password (not stored in plain options backups).

  • medium Inbound webhook HMAC nonce is not replay-protected

    missing_nonce

    authorize() requires X-WSS-Nonce in the signed payload and enforces a 300-second timestamp window, but never records or rejects reused nonces. A captured valid signed request (e.g. plugin-action, wp-config POST, reset-pairing) can be replayed for up to five minutes. SSO login correctly stores nonces in a transient; the REST path does not.

    includes/class-wss-webhook.php:144-172

    Recommendation

    After a successful signature check, reject if a transient for the nonce already exists, then set_transient(nonce_key, 1, 300) mirroring WSS_SSO::maybe_handle.

WP Registry hashes the installable build and reports on that exact bytes-for-bytes copy. Embargoed findings are withheld until they are disclosed, so a clean verdict means nothing public is outstanding. WP Manifest does not audit code itself.