Skip to content

Changelog#

0.3.2 (2026-11-08)#

The remaining security items, plus two admin bugs found while testing them.

  • Code needs unfiltered_html. JavaScript and HTML snippets, and snippets on admin pages, the login page or the block editor, need WordPress's unfiltered_html capability to edit, delete, publish, toggle, restore or preview (WordPress's own rule for Additional CSS). Administrators and editors have it; the Web Designer role does not and now writes CSS for the site only, so it can no longer run script in an administrator's browser. Settings → Code restores the old plugin's behaviour; the bb_snippets_code_cap filter sets any capability.
  • </style in CSS snippets is printed as <\/style, so CSS cannot close its element and add script. No snippet on coalesce.io contains it.
  • Only snippets that print have public files. Inactive, expired, draft and other-environment snippets no longer leave readable {ID}.css / {ID}.js files under uploads.
  • Fix: Web Designers could not open "Add CSS" (since 0.2.0): removing WordPress's own Add New menu entry made the admin access check fall back to the Posts menu. The entry stays, relabelled "Add CSS".
  • Fix: "Add JavaScript" opened as CSS (since 0.2.0): the CSS defaults overrode the requested language.

0.3.1 (2026-11-08)#

Security review of 0.3.0 (three independent reviews: compile and file paths, admin and REST, output and cache). All findings reproduced on the local mirror, fixed, and re-tested; page output unchanged on all 323 public pages.

  • Critical: LESS could read server files. less.php's @import (inline) / (less) and data-uri() copied any readable file (wp-config.php included) into a snippet's CSS, which is published in uploads/custom-css-js. SASS and LESS now compile in a sandbox: imports only inside the snippet folders with stylesheet extensions (checked after resolving links and ..), LESS file functions refused in every source. The old plugin has the same hole.
  • High: contributors reached the preview route (and through it the compiler) by passing the ID of their own post. Preview now needs the snippet capability and a snippet ID.
  • Medium: stored XSS from an imported rule type in the list's "Where on site" column; imports and pushed meta are now normalised (allowed rule types and option values, scalars only, no objects when unserializing).
  • Medium: one malformed snippet broke every build, and a failing build was retried on every request. Each snippet builds in isolation; a failed build is retried after five minutes.
  • Medium: a never-ending SASS/LESS compile would have been retried on every request. Compiles are cached by content and marked failed when they do not finish.
  • Medium: shortcode placeholders were HTML-escaped only; {$x|url}, {$x|js}, {$x|int} added and javascript: values dropped.
  • Low: device-targeted snippets use BB Cache's device test and are not cached when BB Cache shares one copy across devices; one rebuild at a time when many requests find the manifest stale (12 concurrent requests built 11 times, now once); partial names without inner dots or trailing newlines; an .htaccess denying PHP in the snippet folder; the URL tester no longer names pages the user cannot read; to-file writes only .css/.scss/.less/.js/.html; admin-side body_open snippets never print on the site; nosniff on downloads; theme snippet files fingerprinted by content.
  • Docs: Security.

0.3.0 (2026-11)#

The integration items from the design.

  • SASS and LESS, compiled when a snippet is saved (never per request) with the versions Simple Custom CSS and JS PRO bundles: scssphp 1.13.0 and less.php 4.4.1. Partials (import-only snippets) are written under their file name for @import; editing one recompiles the snippets that import it and purges their pages. A snippet that stops compiling keeps printing its last good version, with the error on its edit screen and in Health. Editor: "Written in" CSS / SASS / LESS with SCSS and LESS editor modes, and the partial name. WP-CLI: --preprocessor, --partial.
  • Theme file snippets: .css, .scss, .less, .js, .html files with a header comment in the theme's snippets/ folder print like database snippets. Read-only list under Snippets → Theme files; "Copy to database" and "Download as a theme file" move a snippet either way (a database snippet with the same key wins, so nothing prints twice). Part of the fingerprint; a theme switch or a BB Migrate file push rebuilds at once (BB Migrate's new bb_migrate_file_changed action). WP-CLI: files, to-file; list includes them.
  • Loading (BB Cache critical CSS) per linked snippet: inline it in the page, or load it after the page. Printed as data-bb-critical, which BB Cache now reads; on linked JavaScript "after the page" is defer. WP-CLI: --critical.
  • Registered output (Settings → Output, off by default): front-end CSS snippets and linked JS snippets become WordPress styles and scripts (bb-snippet-{key}), printed at the same place and order. Checked on all 323 public pages of the local mirror: same code, same place. Inline JavaScript stays classic so BB Cache's delay rules treat it as before.
  • Purges also cover snippets whose output changed without being edited (a partial's importers).

0.2.0 (2026-11)#

Phase 2: the admin, plus the BB Cache and BB Migrate integration.

  • Edit screen: WordPress's code editor with linting per language; placement (language, position, inline or file, device for HTML, site/admin/login/block editor, order, minify); "Where on site" rule rows; details (key, environments, expiry, jQuery, owner, notes); status with warnings, the linked file's URL, Preview unsaved changes (for the current user only, on any URL) and Does it print here?.
  • List: active switch, type, placement, rules, order; filters by type and active state; bulk activate/deactivate.
  • Tools: Test a URL, Health (build and check times, warnings, unused files with a delete button, Rebuild now), export and import.
  • Settings: shared with the old plugin (comments, preview lifetime, Web Designer role).
  • Revisions store settings and rules; restoring brings all three back; the compare screen shows them.
  • REST routes bb-snippets/v1/test-url and /preview, behind capability checks.
  • BB Cache: a snippet change purges the URLs its rules name (before and after the change), or everything when the rules are broad. Needs BB Cache's fix for non-public post types (2026-11-07) to stay targeted.
  • BB Migrate: its snippet regeneration step calls BB Snippets when it is the active snippet plugin.
  • Fix: the URL tester recognised neither the front page nor the posts page when called over REST (WordPress never marks a REST request's main query as home); it now runs a separate query.
  • Docs site (MkDocs, Brightbase document system).

0.1.0 (2026-11)#

Phase 1: runtime, data compatibility and WP-CLI. No admin screens yet (phase 2); while it runs, snippets are edited with WP-CLI, or the old plugin is reactivated for its editor.

  • Drop-in for Simple Custom CSS and JS PRO 4.43. Same post type, meta (options, urls, _active, _slug), rules, print hooks, priority and order, and the same markup. Pauses itself while the old plugin is active.
  • Compiled manifest, rebuilt on every change path: status changes, saves from anywhere, deletes, revision restores, meta writes, imports, settings. A fingerprint check (admin, WP-CLI, hourly cron, front end every five minutes) catches changes made with SQL or a database push. Each build is a new file, so PHP's opcode cache never serves an old one.
  • The database is the source of truth. The old plugin's files and its two options are refreshed from it, so the old plugin can take over again without an admin save, and stale files (DB edited, file never rewritten) print correctly again.
  • No stripslashes() on stored code: backslashes the old plugin dropped on rebuilds (\d, \s in regexes) print as written.
  • External file versions are content checksums, not a random number regenerated for every snippet on any save.
  • Conditional rules without eval(): a parser for conditional tags with literal arguments; anything else is reported and never matches (BB_SNIPPETS_EVAL_CONDITIONALS restores eval).
  • New per-snippet fields in _bb_snippet: key, env (environments), expires, owner, notes, deps.
  • [ccj] shortcodes print HTML with escaped attributes; no PHP is executed.
  • WP-CLI: list, get, create, update, activate, deactivate, rebuild, doctor (with --clean for orphan files), test-url, export, import.