{"id":264276,"date":"2025-12-16T18:44:00","date_gmt":"2025-12-16T18:44:00","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/client-safe-mode\/"},"modified":"2026-01-06T21:54:04","modified_gmt":"2026-01-06T21:54:04","slug":"brenwp-client-safe-mode","status":"publish","type":"plugin","link":"https:\/\/pcd.wordpress.org\/plugins\/brenwp-client-safe-mode\/","author":23408568,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_crdt_document":"","version":"1.7.2","stable_tag":"1.7.2","tested":"6.9.4","requires":"6.0","requires_php":"7.4","requires_plugins":null,"header_name":"BrenWP Client Safe Mode","header_author":"Brendigo LTD","header_description":"Per-user Safe Mode (UI + optional safety restrictions) + role-based client restrictions for safer troubleshooting and clean client handoff.","assets_banners_color":"a1b2be","last_updated":"2026-01-06 21:54:04","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"https:\/\/brenwp.com","header_author_uri":"https:\/\/brendigo.com","rating":0,"author_block_rating":0,"active_installs":0,"downloads":312,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"1.7.1":{"tag":"1.7.1","author":"brendigo","date":"2026-01-02 02:14:00"},"1.7.2":{"tag":"1.7.2","author":"brendigo","date":"2026-01-06 21:54:04"}},"upgrade_notice":{"1.7.2":"<p>This is a maintenance + hardening + UX release.<\/p>\n\n<p>New in 1.7.2:\n* Expanded About tab with clearer purpose, scenarios, and links (plugin\/author\/support)\n* Optional settings export download (admin-only)\n* Optional 2FA reminder notice for restricted users (notice only)\n* Existing restrictions and redirect behavior refined for stability (loop prevention)<\/p>","1.7.1":"<p>This is a feature + hardening release.<\/p>\n\n<p>New in 1.7.1:\n* Admin-managed Safe Mode for other users (optional expiry; multisite-safe)\n* Activity log export (JSON\/CSV) + configurable retention with daily auto-prune\n* Custom wp-admin screen blocklists (separate lists for Safe Mode and Restrictions)<\/p>\n\n<p>If you use Restrictions, review settings after update (recommended: start with a single role and test with a staging user).<\/p>"},"ratings":[],"assets_icons":{"icon-128x128.png":{"filename":"icon-128x128.png","revision":3422374,"resolution":"128x128","location":"assets","locale":""},"icon-256x256.png":{"filename":"icon-256x256.png","revision":3422374,"resolution":"256x256","location":"assets","locale":""}},"assets_banners":{"banner-1544x500.png":{"filename":"banner-1544x500.png","revision":3422374,"resolution":"1544x500","location":"assets","locale":""},"banner-772x250.png":{"filename":"banner-772x250.png","revision":3422374,"resolution":"772x250","location":"assets","locale":""}},"assets_blueprints":{},"all_blocks":[],"tagged_versions":["1.7.1","1.7.2"],"block_files":[],"assets_screenshots":{"screenshot-1.png":{"filename":"screenshot-1.png","revision":3422374,"resolution":"1","location":"assets","locale":""},"screenshot-2.png":{"filename":"screenshot-2.png","revision":3422374,"resolution":"2","location":"assets","locale":""},"screenshot-3.png":{"filename":"screenshot-3.png","revision":3422374,"resolution":"3","location":"assets","locale":""},"screenshot-4.png":{"filename":"screenshot-4.png","revision":3422374,"resolution":"4","location":"assets","locale":""},"screenshot-5.png":{"filename":"screenshot-5.png","revision":3422376,"resolution":"5","location":"assets","locale":""},"screenshot-6.png":{"filename":"screenshot-6.png","revision":3422376,"resolution":"6","location":"assets","locale":""}},"screenshots":[],"jetpack_post_was_ever_published":false},"plugin_section":[],"plugin_tags":[466,31093,22939,600,8541],"plugin_category":[54],"plugin_contributors":[252368],"plugin_business_model":[],"class_list":["post-264276","plugin","type-plugin","status-publish","hentry","plugin_tags-client","plugin_tags-hardening","plugin_tags-restrictions","plugin_tags-security","plugin_tags-troubleshooting","plugin_category-security-and-spam-protection","plugin_contributors-brendigo","plugin_committers-brendigo"],"banners":{"banner":"https:\/\/ps.w.org\/brenwp-client-safe-mode\/assets\/banner-772x250.png?rev=3422374","banner_2x":"https:\/\/ps.w.org\/brenwp-client-safe-mode\/assets\/banner-1544x500.png?rev=3422374","banner_rtl":false,"banner_2x_rtl":false},"icons":{"svg":false,"icon":"https:\/\/ps.w.org\/brenwp-client-safe-mode\/assets\/icon-128x128.png?rev=3422374","icon_2x":"https:\/\/ps.w.org\/brenwp-client-safe-mode\/assets\/icon-256x256.png?rev=3422374","generated":false},"screenshots":[{"src":"https:\/\/ps.w.org\/brenwp-client-safe-mode\/assets\/screenshot-1.png?rev=3422374","caption":""},{"src":"https:\/\/ps.w.org\/brenwp-client-safe-mode\/assets\/screenshot-2.png?rev=3422374","caption":""},{"src":"https:\/\/ps.w.org\/brenwp-client-safe-mode\/assets\/screenshot-3.png?rev=3422374","caption":""},{"src":"https:\/\/ps.w.org\/brenwp-client-safe-mode\/assets\/screenshot-4.png?rev=3422374","caption":""},{"src":"https:\/\/ps.w.org\/brenwp-client-safe-mode\/assets\/screenshot-5.png?rev=3422376","caption":""},{"src":"https:\/\/ps.w.org\/brenwp-client-safe-mode\/assets\/screenshot-6.png?rev=3422376","caption":""}],"raw_content":"<!--section=description-->\n<p>BrenWP Client Safe Mode helps you troubleshoot safely and reduce risk when handing a WordPress site to clients or non-technical users.<\/p>\n\n<p>Safe Mode is <em>per-user<\/em>: it applies only to the currently logged-in user who enabled it. Visitors and other users are not affected.<\/p>\n\n<h4>Safe Mode (per-user) can optionally<\/h4>\n\n<ul>\n<li>Block access to risky wp-admin screens (plugin\/theme management, core updates, Site Health, and update actions)<\/li>\n<li>Disable file modifications (plugin\/theme installs, updates, editors)<\/li>\n<li>Optionally block update\/install capabilities (prevents running updates\/installs even via alternative flows)<\/li>\n<li>Optionally block destructive capabilities (prevents deleting plugins\/themes while Safe Mode is enabled)<\/li>\n<li>Optionally disable the built-in plugin\/theme editors (capability-based) while Safe Mode is enabled<\/li>\n<li>Hide update notices<\/li>\n<li>Trim selected admin bar nodes (Updates \/ Comments \/ New Content)<\/li>\n<li>Auto-disable after a configurable number of minutes (optional)<\/li>\n<\/ul>\n\n<h4>Client restrictions (role-based + optional user targeting) can<\/h4>\n\n<ul>\n<li>Optionally target a specific user account (in addition to roles)<\/li>\n<li>Hide risky menus<\/li>\n<li>Block direct access to sensitive wp-admin screens<\/li>\n<li>Disable file modifications<\/li>\n<li>Hide update notices<\/li>\n<li>Optionally limit the Media Library to a user\u2019s own uploads (privacy on multi-author sites)<\/li>\n<li>Optionally hide common Dashboard widgets for restricted roles (UI cleanup)<\/li>\n<li>Optionally hide the Screen Options dropdown (independent toggle)<\/li>\n<li>Optionally hide the Admin Bar on the front end for restricted roles<\/li>\n<li>Optionally block Customizer access (customize.php)<\/li>\n<li>Optionally block Users screens (Users list\/Add\/Edit) even if the broader screen blocklist is disabled<\/li>\n<li>Optionally block Tools screens (Tools\/Import\/Export) even if the broader screen blocklist is disabled<\/li>\n<li>Optionally lock profile email\/password changes for restricted roles (prevents self-service account takeover)<\/li>\n<li>Optionally show a dismissible 2FA security reminder notice (notice only)<\/li>\n<li>Optionally hide the Admin Bar on the front end for restricted roles<\/li>\n<\/ul>\n\n<h4>General hardening (site-wide, optional)<\/h4>\n\n<ul>\n<li>Disable XML-RPC<\/li>\n<li>Disable the built-in plugin\/theme editors for all users (capability-based)<\/li>\n<li>Optional settings export download (admin-only) via a nonce-protected endpoint (default OFF)<\/li>\n<\/ul>\n\n<p>Administrators are never restricted by client restrictions. On multisite, super-admins are also excluded.<\/p>\n\n<h4>Privacy<\/h4>\n\n<p>This plugin does not send data to external services. It performs <strong>no tracking, telemetry, analytics, or \u201cphone-home\u201d requests<\/strong>.<\/p>\n\n<h4>Data stored on your site<\/h4>\n\n<p>The plugin stores the minimum required data to provide Safe Mode and optional auditing:<\/p>\n\n<ul>\n<li><strong>Options (Settings)<\/strong>: stored in the <code>brenwp_csm_options<\/code> option (site option). This contains your configured settings.<\/li>\n<li><strong>Activity log (optional)<\/strong>: stored in the <code>brenwp_csm_activity_log<\/code> option <strong>only if Activity logging is enabled<\/strong>. This log is bounded by <strong>Max entries<\/strong> and can optionally be pruned by age (Retention days).<\/li>\n<li><strong>Operational options<\/strong>: internal housekeeping options such as <code>brenwp_csm_last_settings_change<\/code> and a short-lived lock key used to avoid concurrent log writes.<\/li>\n<li><strong>User meta (Safe Mode)<\/strong>:\n\n<ul>\n<li><code>brenwp_csm_safe_mode<\/code> (on\/off flag for a user)<\/li>\n<li><code>brenwp_csm_safe_mode_until<\/code> (optional expiry timestamp if auto-off is enabled)<\/li>\n<\/ul><\/li>\n<\/ul>\n\n<h4>Data minimization and retention<\/h4>\n\n<ul>\n<li>Activity logging is <strong>disabled by default<\/strong>.<\/li>\n<li>The activity log does <strong>not<\/strong> store IP addresses and attempts to redact likely secrets from context values.<\/li>\n<li>Retention controls:\n\n<ul>\n<li><strong>Max entries<\/strong> caps log size.<\/li>\n<li><strong>Retention days<\/strong> can automatically prune older entries (0 = disabled).<\/li>\n<li>The <strong>Clear log<\/strong> action removes all log entries immediately (admin-only, nonce protected).<\/li>\n<\/ul><\/li>\n<\/ul>\n\n<h4>Privacy tools<\/h4>\n\n<p>The plugin:\n* Adds suggested text to the Privacy Policy Guide (Settings \u2192 Privacy)\n* Registers a personal data exporter and eraser for the Safe Mode user meta<\/p>\n\n<h4>Data deletion<\/h4>\n\n<p>On uninstall (delete), the plugin removes its options, optional log option, Safe Mode user meta, and (best-effort) the optional <code>bren_client<\/code> role if it was created by the plugin.<\/p>\n\n<h3>Security<\/h3>\n\n<p>This plugin follows WordPress hardening best practices:<\/p>\n\n<ul>\n<li><strong>CSRF protection<\/strong>: all state-changing actions use <strong>POST<\/strong> and require a <strong>WordPress nonce<\/strong>.<\/li>\n<li><strong>Authorization<\/strong>: privileged admin actions are gated by <strong>capability checks<\/strong> (<code>manage_options<\/code> by default, filterable).<\/li>\n<li><strong>XSS defense<\/strong>: user-controlled data is sanitized on input and escaped on output.<\/li>\n<li><strong>No remote requests<\/strong>: the plugin does not make outbound HTTP requests.<\/li>\n<li><strong>Data minimization<\/strong>: the activity log is bounded, does not store IP addresses, and redacts likely secrets in log context values.<\/li>\n<\/ul>\n\n<p>Assumptions and scope:<\/p>\n\n<ul>\n<li>The plugin enforces policies inside WordPress; it does not replace server\/WAF hardening.<\/li>\n<li>Safe Mode is <strong>per-user<\/strong> and does not modify the site\u2019s active plugins\/themes list.<\/li>\n<\/ul>\n\n<h3>Troubleshooting<\/h3>\n\n<h4>I don\u2019t see the Safe Mode toggle in the admin bar<\/h4>\n\n<ul>\n<li>Confirm the WordPress admin bar is enabled for your account.<\/li>\n<li>Confirm <strong>Enforcement<\/strong> is enabled in the plugin settings.<\/li>\n<li>Confirm your role is included in <strong>Who can toggle Safe Mode<\/strong> (or you are an administrator \/ multisite super-admin).<\/li>\n<\/ul>\n\n<h4>My profile email\/password cannot be changed<\/h4>\n\n<p>If <strong>Restrictions \u2192 Lock profile email\/password<\/strong> is enabled and your account is restricted, you will not be able to change your own email or password. Contact an administrator.<\/p>\n\n<h4>XML-RPC stopped working<\/h4>\n\n<p>If you rely on legacy services that require XML-RPC (some old mobile apps \/ integrations), disable <strong>General \u2192 Disable XML-RPC<\/strong>.<\/p>\n\n<h4>I get redirected with an \u201cAccess blocked\u201d notice<\/h4>\n\n<p>A configured policy blocked a sensitive admin screen. Review:\n* <strong>Restrictions \u2192 Block direct screen access<\/strong> (for restricted roles)\n* <strong>Safe Mode \u2192 Block risky admin screens<\/strong> (for your account if Safe Mode is enabled)<\/p>\n\n<h4>Safe Mode is enabled but I want to turn it off<\/h4>\n\n<ul>\n<li>Use the <strong>Safe Mode<\/strong> tab to toggle it off.<\/li>\n<li>If auto-off is enabled, it will disable automatically after the configured time window.<\/li>\n<li>If Enforcement is OFF, the UI provides a <strong>Clear stored Safe Mode<\/strong> button to remove the stored flag.<\/li>\n<\/ul>\n\n<h3>Developer Hooks<\/h3>\n\n<p>Filters:\n* <code>brenwp_csm_required_cap<\/code> \u2014 change the capability required to manage this plugin (default: <code>manage_options<\/code>).\n* <code>brenwp_csm_presets<\/code> \u2014 customize Dashboard presets (label\/description\/patch arrays).\n* <code>brenwp_csm_create_client_role<\/code> \u2014 return <code>false<\/code> to prevent creating the <code>bren_client<\/code> role on activation.\n* <code>brenwp_csm_client_role_caps<\/code> \u2014 customize capabilities assigned to the <code>bren_client<\/code> role on activation.\n* <code>brenwp_csm_remove_client_role_on_uninstall<\/code> \u2014 return <code>false<\/code> to keep the <code>bren_client<\/code> role during uninstall cleanup.<\/p>\n\n<!--section=installation-->\n<ol>\n<li>Upload the plugin folder to \/wp-content\/plugins\/brenwp-client-safe-mode\/<\/li>\n<li>Activate the plugin via Plugins \u2192 Installed Plugins<\/li>\n<li>Open BrenWP Safe Mode in wp-admin<\/li>\n<li>Configure Safe Mode and Restrictions as needed<\/li>\n<\/ol>\n\n<!--section=faq-->\n<dl>\n<dt id='does%20safe%20mode%20affect%20visitors%3F'><h3>Does Safe Mode affect visitors?<\/h3><\/dt>\n<dd><p>No. Safe Mode is per-user. Visitors and users without Safe Mode enabled see the normal site.<\/p><\/dd>\n<dt id='will%20administrators%20be%20restricted%3F'><h3>Will administrators be restricted?<\/h3><\/dt>\n<dd><p>Administrators are never restricted by client restrictions (role\/user targeting). If an administrator enables Safe Mode for their own account, optional Safe Mode policies (like blocking file modifications) can apply to that account.<\/p><\/dd>\n<dt id='can%20i%20restrict%20a%20single%20user%20without%20creating%20a%20new%20role%3F'><h3>Can I restrict a single user without creating a new role?<\/h3><\/dt>\n<dd><p>Yes. In the <strong>Restrictions<\/strong> tab, you can select a specific user account in <strong>Restricted user (optional)<\/strong>. This applies the same restrictions even if that user\u2019s role is not selected. Administrators (and multisite super-admins) are excluded to prevent lock-outs.<\/p><\/dd>\n<dt id='does%20this%20plugin%20collect%20personal%20data%3F'><h3>Does this plugin collect personal data?<\/h3><\/dt>\n<dd><p>It stores a per-user Safe Mode flag so it can remember whether Safe Mode is enabled for that account. If auto-expiry is enabled, it also stores an expiry timestamp. No tracking, analytics, or external requests.<\/p><\/dd>\n<dt id='how%20do%20i%20remove%20all%20plugin%20data%3F'><h3>How do I remove all plugin data?<\/h3><\/dt>\n<dd><p>When you uninstall (delete) the plugin, it removes its options, its activity log option, Safe Mode user meta, and the optional bren_client role (best-effort).<\/p><\/dd>\n<dt id='why%20does%20the%20admin%20bar%20safe%20mode%20toggle%20require%20javascript%3F'><h3>Why does the admin bar Safe Mode toggle require JavaScript?<\/h3><\/dt>\n<dd><p>To prevent state changes via GET requests (and potential link prefetch), the admin bar toggle submits the action as a POST request. This is handled using lightweight JavaScript.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>1.7.2<\/h4>\n\n<ul>\n<li>UX: About tab expanded with clearer purpose, use cases, scenarios, and direct links (plugin\/author\/support).<\/li>\n<li>New (General): Optional \u201cSettings export download\u201d toggle (admin-only, nonce-protected endpoint) to download settings JSON as a file.<\/li>\n<li>New (Restrictions): Optional, dismissible 2FA reminder notice for restricted users (notice only; no integrations).<\/li>\n<li>Fix: Prevent redirect loops when a blocked-screen redirect destination is also restricted.<\/li>\n<li>Maintenance: Documentation updates and minor UI consistency cleanup.<\/li>\n<\/ul>\n\n<h4>1.7.1<\/h4>\n\n<ul>\n<li>UX: Simplified settings layout (Basics\/Recommended\/Advanced) so new users are not overwhelmed.<\/li>\n<li>UX: Moved the About screen into an \u201cAbout\u201d tab to reduce admin menu clutter.<\/li>\n<li>New: Admin-managed Safe Mode for other users (optional per-user expiry).<\/li>\n<li>New: Activity log export (JSON\/CSV) and configurable retention with daily auto-prune.<\/li>\n<li>New: Custom wp-admin screen blocklists (separate lists for Safe Mode and Restrictions).<\/li>\n<li>New: Optional restriction toggles: Hide Screen Options only, Block Customizer access, Block Users screens.<\/li>\n<li>New: Safe Mode toggle to block destructive capabilities (delete plugins\/themes).<\/li>\n<li>Fix: Improved i18n compliance (missing translators comment for placeholders).<\/li>\n<li>Security: Hardened admin actions (capability checks, POST-only, nonces) and safer input handling\/escaping.<\/li>\n<li>Compatibility: Multisite safeguards (never restrict Network Admin; protect super-admin accounts).<\/li>\n<li>Performance: Per-request caching and safer option storage (autoload off for log \/ large options).<\/li>\n<\/ul>\n\n<h4>1.7.0<\/h4>\n\n<ul>\n<li>Dashboard: Added Quick Actions (presets, settings export\/import JSON, reset to defaults).<\/li>\n<li>Restrictions: Added optional \u201cRestricted access\u201d banner and user selector with AJAX search (better for large sites).<\/li>\n<li>Restrictions: Added optional profile hardening (lock email\/password) for restricted roles.<\/li>\n<li>Safe Mode: Added optional UI hardening (hide admin notices) and additional safety toggles.<\/li>\n<li>Security\/Hardening: Improved state-changing admin actions (nonces, capability checks, POST-only), and safer activity log writes.<\/li>\n<\/ul>\n\n<h4>1.6.9<\/h4>\n\n<ul>\n<li>Security: Hardened settings submission capability checks and improved defensive checks around admin assets.<\/li>\n<li>Compatibility: Replaced PHP filter_input() usage with WordPress-native input handling (wp_unslash + sanitize_*).<\/li>\n<li>Performance: Added lightweight per-request caching for Safe Mode and restriction checks.<\/li>\n<li>Multisite: Avoided applying restrictions inside Network Admin.<\/li>\n<\/ul>","raw_excerpt":"Per-user Safe Mode plus role-based client restrictions for safer troubleshooting and cleaner client handoff.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/pcd.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/264276","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/pcd.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/pcd.wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/pcd.wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=264276"}],"author":[{"embeddable":true,"href":"https:\/\/pcd.wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/brendigo"}],"wp:attachment":[{"href":"https:\/\/pcd.wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=264276"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/pcd.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=264276"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/pcd.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=264276"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/pcd.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=264276"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/pcd.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=264276"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/pcd.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=264276"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}