Title: Bulwarden
Author: jgloeckl.de
Published: <strong>August 23, 2026</strong>
Last modified: August 23, 2026

---

Search plugins

![](https://ps.w.org/bulwarden/assets/banner-772x250.png?rev=3661811)

![](https://ps.w.org/bulwarden/assets/icon-256x256.png?rev=3661811)

# Bulwarden

 By [jgloeckl.de](https://profiles.wordpress.org/bulwarden/)

[Download](https://downloads.wordpress.org/plugin/bulwarden.1.13.7.zip)

 * [Details](https://wordpress.org/plugins/bulwarden/#description)
 * [Reviews](https://wordpress.org/plugins/bulwarden/#reviews)
 *  [Installation](https://wordpress.org/plugins/bulwarden/#installation)
 * [Development](https://wordpress.org/plugins/bulwarden/#developers)

 [Support](https://wordpress.org/support/plugin/bulwarden/)

## Description

Bulwarden is the **site agent**, installed on each managed
 WordPress site. It exposes
a signed REST API (`jgm/v1`) that a **Bulwarden hub calls to read health and security
data and to trigger updates. The hub is a separate application — it is not part 
of this plugin — and this plugin talks to no hub at all until you pair it with one.

#### Features

 * Site health snapshots (versions, pending updates, disk, WordPress Site Health
   tests)
 * Full plugin & theme inventory (version, active status, available update) per 
   site
 * Configuration-level security checks with a posture score
 * Remote core / plugin / theme updates, wrapped in maintenance mode
 * Zero-knowledge encrypted backups: the passphrase stays on your server and is 
   never transmitted
 * A dashboard card showing who maintains this site and how to reach them

#### Pairing

On activation the plugin provisions an API key + secret. Copy the **connect
 string

from the Bulwarden entry in the WordPress admin menu and paste
 it into the hub’s“
Connect a site” form. Your provider’s support details are then pushed to the site
automatically by the hub and appear on the dashboard.

#### Security

Hub  client requests are authenticated with the per-site API key and an
 HMAC-SHA256
signature over the method, route, timestamp, and body. Timestamps outside a 5-minute
window are rejected to limit replay. The secret never travels on the wire — it lives
only in this plugin and in the hub webapp.

### Privacy

Bulwarden is a client agent: on its own it sends data nowhere. Pairing this
 site
with a hub (yours, or your maintenance provider’s) is an explicit, opt-in action—
you choose when to copy the connect string from the Bulwarden screen in the WordPress
admin menu and hand it to that hub. Nothing is transmitted before that.

Once paired, data only moves in these cases:

 * **Health, inventory, and security checks.** The paired hub reads these from
    
   this site’s signed REST API when it polls or when a check is requested — WordPress/
   plugin/theme versions and update status, a full plugin & theme inventory, disk
   usage, and the configuration-level security posture score.
 * **Backups**, only when triggered (the Settings screen’s “Back up now”
    button,
   or a request from the paired hub): the full site is archived and encrypted on
   this server with a passphrase that is never transmitted anywhere, then the ciphertext
   is uploaded to the hub. Only someone who has the passphrase can decrypt a backup—
   the hub operator cannot read its contents.
 * **Malware scan results**, only when a scan is triggered (admin- or
    hub-initiated):
   findings (type, severity, file path, line, and a short excerpt) are sent to the
   hub that requested the scan.
 * **Finishing an interrupted update**, when the paired hub asks. Nothing is
    sent
   in that exchange; the site runs WordPress’ own database upgrade, or deletes an
   expired `.maintenance` lock file, and reports the outcome.

Independently of any hub pairing, this plugin verifies WordPress core and
 wordpress.
org-hosted plugin files by comparing local file hashes against the public checksum
APIs at `api.wordpress.org` and `downloads.wordpress.org`. Those requests carry 
only what identifies the release to look up — the WordPress version and locale, 
and each plugin’s slug and version. No file contents, hashes, URLs or user data 
are sent: the reference checksums come back and the comparison happens here, on 
this server.

Bulwarden does not call home on activation, does not collect analytics, and
 stores
data on no server this site hasn’t been explicitly connected to. The hub itself 
is a separate service outside this plugin’s control; consult your provider for how
it handles the data described above.

### External services

This plugin connects to the services below. Nothing here runs on activation.

#### Your Bulwarden hub

Bulwarden is the site-side agent for a **hub** — the management application an
 
agency or site owner runs to watch and maintain a fleet of WordPress sites. The 
hub is a separate product and is not part of this plugin.

The default hosted hub is operated by Bulwarden at https://bulwarden.net/ —
 terms
of use: https://bulwarden.net/terms/ , privacy policy: https://bulwarden.net/privacy/.
A hub can also be self-hosted, or run by the maintenance provider you buy from, 
in which case this plugin talks to that provider’s server instead and their terms
and privacy policy apply.

**No connection to any hub exists until you make one.** You pair a site by
 copying
the connect string from the Bulwarden screen in the WordPress admin menu and pasting
it into the hub; before that the plugin contacts no hub at all, and it never discovers
or chooses one on its own. Once paired, data moves only in these cases:

 * **When the hub asks for status.** It reads this site’s signed REST API and
    receives
   WordPress/plugin/theme versions and update status, the full plugin and theme 
   inventory, disk usage, the results of WordPress’ own Site Health tests, and the
   configuration-level security posture score.
 * **When a backup runs** (you press “Back up now”, or the hub requests one).
    The
   site is archived and encrypted here, with a passphrase that is never transmitted,
   and only the ciphertext is uploaded. The hub operator cannot read a backup’s 
   contents without that passphrase.
 * **When a malware scan runs** (started by you or by the hub). The findings —
    
   type, severity, file path, line number and a short excerpt — are sent to the 
   hub that asked for the scan.
 * **When the hub pushes your provider’s support details** — their name, logo,
    
   support address and accent colour — on connect and whenever they change them.
   Nothing is sent from the site in that exchange.

Every one of those requests is authenticated with this site’s own API key and
 an
HMAC-SHA256 signature; the shared secret never travels over the wire.

#### api.wordpress.org and downloads.wordpress.org

The malware scan verifies WordPress core and wordpress.org-hosted plugins
 against
their published checksums, using WordPress.org’s own public APIs at https://api.
wordpress.org/core/checksums/1.0/ and https://downloads.wordpress.org/plugin-checksums/.
This happens whenever a scan runs, whether or not the site is paired with a hub.

These requests identify only the release being looked up: the WordPress version

and locale, and each installed plugin’s slug and version. No file contents, hashes,
site URL or user data are sent — the reference checksums are returned and compared
locally.

These are WordPress.org services, covered by the WordPress.org privacy policy:
 
https://wordpress.org/about/privacy/

## Screenshots

[⌊The Bulwarden screen at a glance: whether the site is connected, whether
backups
are encrypted, and when the last backup and scan ran.⌉⌊The Bulwarden screen at a
glance: whether the site is connected, whether
backups are encrypted, and when the
last backup and scan ran.⌉[

The Bulwarden screen at a glance: whether the site is connected, whether backups
are encrypted, and when the last backup and scan ran.

[⌊Connecting the site: the connect string you paste into your hub, and the
API credentials
behind it.⌉⌊Connecting the site: the connect string you paste into your hub, and
the
API credentials behind it.⌉[

Connecting the site: the connect string you paste into your hub, and the API credentials
behind it.

[⌊Backups: a run in progress showing the phase it has reached and its log,
above
the encryption passphrase and the folders left out of the archive.⌉⌊Backups: a run
in progress showing the phase it has reached and its log,
above the encryption passphrase
and the folders left out of the archive.⌉[

Backups: a run in progress showing the phase it has reached and its log, above the
encryption passphrase and the folders left out of the archive.

[⌊The malware scan: what the last one found, grouped by kind, and how much of
the
site could be checked against the files WordPress.org published.⌉⌊The malware scan:
what the last one found, grouped by kind, and how much of
the site could be checked
against the files WordPress.org published.⌉[

The malware scan: what the last one found, grouped by kind, and how much of the 
site could be checked against the files WordPress.org published.

[⌊The activity log: an append-only record of credential changes, backups,
restores,
scans and repairs, including the ones the hub triggered.⌉⌊The activity log: an append-
only record of credential changes, backups,
restores, scans and repairs, including
the ones the hub triggered.⌉[

The activity log: an append-only record of credential changes, backups, restores,
scans and repairs, including the ones the hub triggered.

[⌊The dashboard support card — who maintains this site and how to reach
them, pushed
by the hub.⌉⌊The dashboard support card — who maintains this site and how to reach

them, pushed by the hub.⌉[

The dashboard support card — who maintains this site and how to reach them, pushed
by the hub.

## Installation

Bulwarden is one half of a pair: this plugin runs on the site, and a **hub** runs
somewhere else and manages it. Installing the plugin on its own does nothing until
you pair it with a hub.

 1. Install and activate the plugin as you would any other — upload it under Plugins
    → Add New → Upload Plugin, or install it from the directory.
 2. Go to **Bulwarden** in the WordPress admin menu. The plugin generated an API key
    and secret for this site on activation; the screen shows a single **connect string**
    that carries the site name, URL and both credentials.
 3. Copy that string and paste it into your hub’s “Connect a site” form. That is the
    whole pairing step — there is nothing to type on this side, and no hub address 
    to configure here.
 4. If you want encrypted backups, set a **backup passphrase** on the same screen. 
    It never leaves this server, and it is required to restore. Keep it somewhere you
    will still have it after the disaster you are backing up against — nobody, including
    your hub operator, can recover a backup without it.

#### Do I need a hub?

Yes, for anything beyond installing it. The hub is separate software: use the hosted
one, run your own, or use the one your maintenance provider runs. Until the site
is paired, this plugin contacts nothing and does nothing.

#### Upgrading

Updates install like any other plugin. Your credentials, passphrase and settings
survive an update; nothing needs re-pairing.

## FAQ

### Does this plugin send my site’s data anywhere on its own?

No. Before you pair it with a hub it contacts nothing at all, and it never
 discovers
or chooses a hub by itself. After pairing, data moves only for the things listed
under Privacy below — health checks, backups, malware scan findings — and only to
the hub you paired with.

### Can the hub operator read my backups?

No, provided you set a passphrase. The archive is encrypted **on this server**
 
with a key derived from your passphrase, and only the ciphertext is uploaded. The
passphrase is never transmitted, so a hub holds bytes it cannot decrypt. The same
property is why nobody can recover a lost passphrase for you.

### What happens if I deactivate or delete the plugin?

The site stops answering its hub, which the hub will notice and report as the
 agent
going unreachable. Deleting the plugin removes its settings, its audit-log table
and its working directories (see `uninstall.php`); backups already stored on a hub
are unaffected.

### Does it work on multisite?

The plugin runs per site. A network-wide database upgrade is reported but not
 performed—
core’s own network upgrade screen walks every site in the network, and that is where
it belongs.

### Why does the malware scan flag a file I know is fine?

The file-integrity check compares every core and WordPress.org-hosted file
 against
the checksums WordPress.org published for that exact release. A caching or optimisation
plugin that rewrites a stylesheet produces the same mismatch a backdoor does, which
is why “this file no longer matches what was published” is reported as a fact rather
than a verdict, and why non-executable files are warnings rather than critical findings.
Your hub can show you the actual diff.

### What does it do to my site’s performance?

Nothing on page loads: there is no front-end code path. Backups and malware
 scans
are real work and run in the background across WordPress cron ticks, to a time budget,
so they do not block visitors. Health checks are answered on demand when the hub
asks.

### Which PHP and WordPress versions are supported?

PHP 7.4 or newer and WordPress 6.0 or newer. Backups additionally need the
 sodium
extension (encryption) and either `zlib` or the `zip` extension (archiving); the
Settings screen tells you if either is missing.

## Reviews

There are no reviews for this plugin.

## Contributors & Developers

“Bulwarden” is open source software. The following people have contributed to this
plugin.

Contributors

 *   [ jgloeckl.de ](https://profiles.wordpress.org/bulwarden/)

[Translate “Bulwarden” into your language.](https://translate.wordpress.org/projects/wp-plugins/bulwarden)

### Interested in development?

[Browse the code](https://plugins.trac.wordpress.org/browser/bulwarden/), check 
out the [SVN repository](https://plugins.svn.wordpress.org/bulwarden/), or subscribe
to the [development log](https://plugins.trac.wordpress.org/log/bulwarden/) by [RSS](https://plugins.trac.wordpress.org/log/bulwarden/?limit=100&mode=stop_on_copy&format=rss).

## Changelog

#### 1.13.7

 * No change to the plugin. Like 1.13.6 it exists for the release itself: publishing
   to the plugin directory failed on the very first attempt, in the step that tells
   the directory which files a version has dropped — there was no previous version
   for this one to have dropped any, and the step could not cope with having nothing
   to do.

#### 1.13.6

 * No change to the plugin itself — it is 1.13.5 under a new number. The screenshots
   on the plugin directory name the version they were taken from, so publishing 
   them alongside a matching release is what keeps the listing and the download 
   describing the same thing.

#### 1.13.5

 * Fix: opening a running backup’s log squeezed it into the half of the panel beside
   the Cancel button, leaving the button stranded in the middle of a column of log
   lines. The log now gets the full width of the panel.
 * Fix: the progress bar for the encryption and upload phases sat empty at 0% for
   a few seconds after each page load, before the first update reached it — directly
   under a line already saying how much had been transferred. It now appears only
   once there is progress to draw.
 * Change: the encryption passphrase field no longer stretches the whole width of
   the panel.

#### 1.13.4

 * Change: the Bulwarden screen has been rebuilt around the question it never answered—
   is this site actually protected right now. It opens with the connection, the 
   encryption passphrase, the last backup and the last scan, each with its own state,
   and a site that has not been set up yet is walked through the three steps that
   finish it instead of being shown a disabled button and told to look elsewhere.
 * Add: a running backup now shows which phase it is in — database, files, encryption,
   upload — and its run log, which the site has been recording all along and never
   displayed. A failed or cancelled run stays on screen until something replaces
   it.
 * Add: the last scan is summarised with what it actually found, grouped by kind,
   and says plainly how much of the site could be checked against published originals
   and how much publishes none.
 * Add: a panel for what this server can do — PHP, the encryption extension, the
   archive backend, and whether WP-Cron is running — because a backup that never
   starts on one site is otherwise invisible from the admin.
 * Add: your provider’s support details, as pushed by the hub, are now visible on
   the screen rather than only on the dashboard.
 * Add: the connect string and API key can be copied with a button, and the secret
   is masked until you ask to see it.
 * Fix: the progress bar for the encryption and upload phases never appeared, so
   a long upload looked identical to a stalled one.
 * Fix: the button that removes a backup exclusion did nothing when the click landed
   on its icon.

#### 1.13.3

 * Change: Bulwarden now has its own entry in the WordPress admin menu instead of
   sitting under Settings. It is a screen you come back to — to pair the site, set
   the backup passphrase, start a backup or read the activity log — not something
   configured once and forgotten.
 * Add: a **Settings** link on the plugin’s row on the Plugins screen, so the way
   to it is where you look right after activating.

#### 1.13.2

 * Fix: an untouched WordPress could be reported as having a modified core file.
   WordPress publishes a separate package per language, and they differ in exactly
   one file it checks: `wp-includes/version.php`. The package a site installed is
   not the language it is displayed in — switching the admin language installs translation
   files and rewrites no core file at all — so a site whose two disagree (an English
   install later switched to German, or a German one switched to “Deutsch (Sie)”)
   had that one file compared against a package it never installed. It was reported
   as a critical modification on every scan, and nothing an operator could do would
   clear it. The package on disk now decides which checksums are fetched, and if
   WordPress.org publishes none for it, that one file is left unchecked rather than
   judged against another package’s.
 * Fix: core findings now tell the hub which package they were measured against,
   so the diff view can say why WordPress.org’s copy of `version.php` differs from
   a localized site’s rather than presenting it as an unexplained mismatch.

#### 1.13.1

 * Fix: some untouched plugins were reported as modified. WordPress.org publishes
   more than one accepted copy of a file whenever a release’s repository copy and
   its downloadable zip drift apart — both are genuine, and a site can legitimately
   have installed either. Every published copy is now accepted, so a file matching
   any of them is clean. Affected files were reported as critical findings on plugins
   nothing had touched.
 * Fix: findings on those files now tell the hub every hash the file was measured
   against, so it can show you the diff instead of reporting that WordPress.org 
   has no copy of the file.

#### 1.13.0

 * New: your hub can now see — and finish — an update that changed this site’s files
   but never completed. The two that strand a site are a pending WordPress database
   upgrade (the “Database Update Required” screen every administrator is sent to,
   which the public site hides completely) and a leftover `.maintenance` lock from
   an update that died half-way. Both are reported to the hub, and both can be finished
   from it: the repair runs exactly what WordPress itself would have run, and nothing
   else.
 * New: a plugin waiting on its own database migration (WooCommerce, most commonly)
   is reported too. It is reported only — that migration belongs to its author and
   runs from their own screen.
 * New: a restore can now put back **only the database**, leaving every file on 
   disk untouched. A bad content edit or a plugin that mangled its own tables is
   a database problem, and restoring the files alongside it would also undo every
   plugin, theme and core update made since the backup — including the security 
   ones. Restores made by an older hub are unaffected and still restore everything.
 * Add: the health report now includes this plugin’s own version, so your hub can
   tell which sites are new enough for a feature before offering it rather than 
   after failing.

#### 1.12.0

 * New: when a file no longer matches the version published on WordPress.org, your
   hub can now show you the actual diff — the published file beside the one on your
   site, with the changed lines marked. A checksum mismatch on its own can’t tell
   a caching plugin rewriting an asset apart from a backdoor appended to a core 
   file; this is what tells them apart. Findings now carry the release they were
   compared against and the hash they should have had, so the hub can prove the 
   copy it fetched really is the published one.
 * New: `POST /jgm/v1/file` returns the current contents of a file, and **only**
   of a file the site’s own last scan flagged. It is not a general file read: anything
   not named by a finding is refused, as are wp-config.php, symlinks, paths outside
   the site, and files over 1 MB.

#### 1.11.1

 * Fix: the malware scan called a site infected over files that cannot run. A stylesheet,
   image or font inside a plugin or theme that no longer matches its published release
   is now reported as a warning rather than as a critical finding — the usual author
   of a rewritten `style.min.css` is a caching or optimisation plugin, not an attacker,
   and the file cannot execute either way. It is still checked, still reported, 
   and still scanned for signatures; code files (PHP, JavaScript, HTML, SVG) and
   WordPress core are unaffected.
 * Change: findings now say what was actually observed — “no longer matches the 
   version published on WordPress.org” — instead of implying a verdict. A checksum
   mismatch means a file changed after it was installed, which is a fact about the
   file, not a diagnosis of the site.

#### 1.11.0

 * Fix: sites intermittently reported themselves as unreachable to their hub, clearing
   again on the next check. Every signed request now carries a single-use nonce,
   so two legitimate requests that arrive in the same second are no longer mistaken
   for one being replayed and refused.
 * **This release must be installed alongside the matching hub update** — the two
   sign requests to each other, and the signing form changed on both sides at once.

#### 1.10.4

 * Fix: the malware scan flagged a plugin’s readme file as “does not match the released
   version”. wordpress.org generates a plugin’s checksums once, at release, but 
   authors keep editing the tagged readme afterwards (a “Tested up to” bump, a changelog
   typo), so this fired on most healthy sites. Readme, changelog and licence files
   inside a plugin or theme are now reported as informational instead of as a modified
   plugin — they are still checked, and code files are unaffected.
 * Fix: when file-integrity findings from several plugins were listed together, 
   the section was titled after whichever plugin happened to sort first, so it named
   one plugin above a list that included others. Findings are now titled by what
   they are, with the affected plugin shown on each file.

#### 1.10.3

 * Fix: a missing or broken component at boot (e.g. an interrupted plugin update
   that leaves the site with a mix of old and new files) no longer takes down every
   page on the site. Each boot component now initializes in isolation, the same 
   way a single failing Site Health test already can’t break the rest of the health
   report.

#### 1.10.2

 * Fix: the uploads-folder hidden-PHP check still had false positives after 1.10.1
   on images whose embedded color profile or gamma curve happened to be readable-
   looking binary (a narrow, slowly-drifting run of bytes that lands in printable
   ASCII without being text — and, being copied verbatim into every thumbnail WordPress
   generates, showed up identically across a whole set of derivative image sizes).
   It now also requires the readable run to contain actual letters, which genuine
   injected PHP always has (a function name, a keyword, at least a superglobal like`
   $_GET`) and this kind of structured binary noise essentially never does.

#### 1.10.1

 * Fix: the malware scan’s uploads-folder check for hidden PHP could flag a legitimate
   image as a false positive — JPEG/PNG data is effectively random binary, and a
   large enough image has a real chance of containing a bare `<?=` by pure coincidence.
   It now also requires readable text to follow the tag, which genuine injected 
   PHP always has but random image data essentially never does.

#### 1.10.0

 * Add: the malware scan’s file-integrity check now also covers your **active theme**,
   the same byte-for-byte verification core files and wordpress.org-hosted plugins
   already get. A custom or premium theme with no published release to compare against
   is reported as unverifiable rather than treated as a finding, exactly like a 
   premium plugin.
 * Fix: the malware scan’s file-integrity check could wrongly report `wp-includes/
   version.php` as modified on a completely untouched WordPress install, on hosts
   where PHP’s own cached view of that file can briefly disagree with what’s actually
   on disk (e.g. after a core auto-update completes). The check now reads the version
   straight off disk instead of trusting that cache, and any other checksum mismatch
   is double-checked before being reported, in case it was caught mid-write.

#### 1.9.0

 * Remove: **white-labelling is gone.** The plugin always appears as “Bulwarden”
   with its real author in the plugins list, and can no longer be renamed, re-attributed
   or hidden from users who don’t administer the site. Your provider’s name, logo
   and support address still appear on the dashboard support card — that part is
   unchanged.
 * Change: all of this plugin’s stored data moved to a `bulw_` prefix, as the Plugin
   Directory guidelines require. **There is no automatic migration**: a site updated
   from an earlier release finds no stored settings, and has to be re-paired with
   its hub (Settings  Bulwarden  Regenerate credentials, then paste the new connect
   string into the hub). Note the backup passphrase has to be re-entered too, and
   existing backups still need the _old_ passphrase to decrypt — keep it before 
   you change it.
 * Change: the settings screen’s styles and scripts are now loaded as proper enqueued
   files instead of being written inline into the page, and two unnecessary loads
   of WordPress core files were removed.
 * Add: readme now documents every external service the plugin contacts, and what
   is sent to each.

#### 1.8.0

 * Add: when your provider restores a backup to this site, it can now choose whether
   to also rewrite every URL/domain found in the database to this site’s own — on
   by default (unchanged), with the option to leave the restored content exactly
   as backed up, which matters when a backup is restored onto a different domain
   than the one it came from.

#### 1.6.0

 * Add: every backup keeps a detailed **run log** — each phase with timings, per-
   table row counts, anything skipped or pruned and why, and the exact operation
   that failed. It shows live on the Settings screen while a backup runs, travels
   to your provider with every finished backup, and is attached to failure reports,
   so a failed backup can be diagnosed remotely without server access.
 * Add: **chunked, resumable uploads**. Large backups are now sent in small, individually
   retried pieces that resume mid-file after a network error, instead of one huge
   request that a proxy body-size limit or dropped connection could doom outright.
   Falls back automatically when the hub doesn’t support it yet. The old hard one-
   hour upload limit is gone — a genuinely stalled transfer still aborts within 
   about 2 minutes, but a slow, healthy one is never cut off again.
 * Add: **end-to-end integrity checks**. The finished archive is verified on disk
   before it is encrypted (exact size, plus a full read-back of the archive index),
   and a SHA-256 of the encrypted blob travels with the upload so the hub can prove
   it stored exactly the bytes this site produced.
 * Add: a **disk-space preflight** refuses to start a backup that clearly cannot
   fit (based on the previous backup’s size), failing in seconds with a clear message
   instead of after an hour of work — or filling the disk under the live site.
 * Add: a new streaming archive writer builds the backup in a single pass with no
   rewrites — dramatically less disk I/O on large sites (a 400 MB test tree dropped
   from ~24 GB of rewrite traffic to zero) — and already-compressed media (images,
   video, archives) is stored without recompression, cutting CPU time on media-heavy
   sites. Requires only zlib; ZipArchive remains as a fallback.
 * Fix: several ways a database dump could silently come out incomplete are now 
   hard failures instead — a dropped database connection mid-dump no longer masquerades
   as “table finished”, and a dump missing the options table is refused outright.
   Dumps are also taken as a single point-in-time snapshot, binary data is written
   in a corruption-proof form, database views are handled as views (previously their
   rows were duplicated as table data), and large rows can no longer exhaust memory.
 * Fix: an unreadable directory anywhere in the site (a root-owned folder, a mounted
   volume’s lost+found) no longer aborts the entire backup — it is skipped, recorded,
   and reported.
 * Fix: sites whose plugins or themes are installed as symlinks now get an explicit
   record that those directories were not archived, instead of silently missing 
   data.
 * Fix: a backup run killed by the host no longer leaves its temporary working directory—
   including an unencrypted copy of the site — behind forever; leftovers are cleaned
   up at the start of the next run.
 * Fix: a restored backup no longer carries the “backup in progress” state of the
   run that produced it, which could block new backups on the restored site for 
   up to an hour.

#### 1.4.1

 * Fix: two `phpcs:ignore` comments in the 1.4.0 working-directory cleanup referenced
   sniff codes that don’t exist, so they didn’t actually suppress anything — the
   WordPress Plugin Check tool correctly flagged direct `rmdir()`/`scandir()` use.
   No functional change.

#### 1.4.0

 * Add: a “Cancel backup” button on the Settings screen, shown while a backup is
   running. It works even if the backup process is wedged, not just when it’s responsive:
   it cleans up the working directory and notifies your provider immediately, rather
   than waiting for the process to notice.
 * Fix: a symlinked directory anywhere in the site (pointing at an ancestor, another
   site sharing storage, or a loop between two directories) could send the archiving
   step into unbounded recursion with no error — indistinguishable from a hang. 
   Symlinked directories are no longer followed.
 * Fix: a stray Unix socket or FIFO under the site (e.g. a cache/queue backend’s
   socket file) could make the archiver hang indefinitely trying to read it. Only
   regular files are ever archived now.
 * Fix: an upload that stalls completely (a proxy or load balancer silently dropping
   an idle transfer) now fails within about 2 minutes with a clear error, instead
   of hanging for up to an hour.
 * Fix: every backup’s temporary working directory is now fully removed when it 
   finishes — previously an empty folder was left behind after every single run,
   successful or not.

#### 1.3.0

 * Add: live backup status — the Settings screen now shows which step a running 
   backup is on (dumping the database, archiving, encrypting, uploading), its size,
   and upload speed, refreshed automatically while it runs. Your provider can now
   also query this status directly, so a backup that crashes without reporting back
   no longer leaves its record stuck at “running” forever.
 * Add: only one backup can run at a time; starting a second one while another is
   in progress is refused with a clear reason instead of the two colliding.

#### 1.2.1

 * Fix: a phpcs:ignore comment for the backup-exclusions form field no longer covered
   the line it was meant to (Settings.php), and the repository now ships a `.gitattributes`
   pinning source files to LF line endings — no functional change.

#### 1.2.0

 * Add: backup exclusions are now a plain editable list on the Settings screen (
   add/remove a directory row) instead of a freeform textarea, pre-filled with every
   exclusion currently in effect — including the defaults, which used to be invisible
   and hardcoded.
 * Add: new default exclusions for the folders the most common alternative backup
   plugins (UpdraftPlus, All-in-One WP Migration, Duplicator, BackupBuddy, Total
   Upkeep, WP Clone) use for their own local archives, so they no longer bloat every
   backup by default.
 * Add: a `.git` directory is now excluded wherever it occurs in the site tree (
   not just at the site root), and is pruned from the walk entirely rather than 
   iterated and discarded — much faster on a site with a large repository history.
 * Fix: sites that already had a custom backup-exclusions list keep the protection
   that used to be hardcoded (the cache/upgrade exclusion) via a one-time migration,
   so upgrading can’t silently shrink what gets excluded.

#### 1.1.1

 * Fix: the plugin’s own pre-branding default (Settings menu label, admin plugins-
   list name) is now `Bulwarden` instead of the generic `Site Maintenance` placeholder
   left over from before the rebrand — matches the hub’s own agency branding default,
   which already shipped as `Bulwarden`. An agency’s white-label branding still 
   overrides it after a site is paired.

#### 1.1.0

 * Add: the malware scan’s signature walk (Layer B) now skips any file already proven
   byte-identical to its published release by the checksum verifier (Layer A) — 
   a pattern match inside code the vendor actually shipped isn’t evidence of compromise
   on this site, so it no longer gets reported.
 * Fix: the scan no longer flags its own installation folder. It isn’t hosted on
   wordpress.org so it was never checksum-verified, and its own pattern documentation
   quotes the very strings the signature scanner looks for — which the scanner was
   matching against itself.

#### 1.0.2

 * Fix: text domain corrected to `bulwarden` (header and every translatable string).
   The 1.0.0 revert to `jg-maintenance` was itself a mistake: it matched this plugin’s
   source-repo folder name rather than its actual installed slug, which has shipped
   as `bulwarden` since 0.3.2.
 * Fix: the restore process’s self-protection check (skip this plugin’s own folder
   mid-restore, so it can’t overwrite the code that’s running it) was still checking`
   wp-content/plugins/jg-maintenance` and so silently failed to protect the real`
   wp-content/plugins/bulwarden` install.

#### 1.0.1

 * Fix: resolved the remaining WordPress Plugin Check findings — the header/translatable-
   string text domain regression from 1.0.0 (see below), a stale `Tested up to`,
   and several false-positive warnings (direct file I/O in the backup/restore subsystem,
   direct `$wpdb` calls, `set_time_limit()` in background jobs, and core-filter 
   lookups) now carry documented justification so they no longer flag.

#### 1.0.0

 * Fix: text domain reverted to `jg-maintenance` everywhere (header and every translatable
   string). It must match the plugin’s slug/folder name, not the `Bulwarden` brand—
   the earlier switch to `bulwarden` broke WordPress.org’s text-domain convention
   despite matching the new name.
 * Add: a Privacy section documenting exactly what data is sent to a paired hub,
   and when.
 * Harden: encrypted backup uploads now honor a site’s configured HTTP proxy and
   verify TLS certificates the way the WordPress HTTP API does, rather than relying
   on raw curl defaults.

#### 0.3.3

 * No plugin changes. Version bump only, to re-cut a release after a suite CI fix(
   release:maintenance/deploy:plugin were still looking up the pre-rebrand plugin
   slug).

#### 0.3.2

 * Fix: main plugin file renamed to bulwarden.php to match the Bulwarden rebrand(
   the CI build looks up the file by plugin slug).

#### 0.3.1

 * Rebrand: the plugin is now Bulwarden (user-facing strings, plugin header, and
   default branding).

#### 0.3.0

 * Rebrand: the plugin is now Bulwark, the site agent for Bulwarden (user-facing
   strings and plugin header).

#### 0.2.3

 * Backups: the archiver now tolerates files that are deleted or replaced mid-backup(
   e.g. another backup plugin rotating its own files) — the affected files are skipped
   and logged instead of aborting the whole backup.

#### 0.2.2

 * Backups: admin-configurable exclusion paths (Settings  JG Maintenance  Backup
   exclusions) so directories the plugin can’t know about on its own — e.g. a legacy
   backup plugin’s folder — can be left out of the archive instead of bloating every
   future backup.

#### 0.1.0

 * Initial scaffold: client agent with signed REST API, health + security collectors,
   remote updates, white-label settings. (Hub is a separate webapp.)

## Meta

 *  Version **1.13.7**
 *  Last updated **2 days ago**
 *  Active installations **Fewer than 10**
 *  WordPress version ** 6.0 or higher **
 *  Tested up to **7.1**
 *  PHP version ** 7.4 or higher **
 * Tags
 * [maintenance](https://wordpress.org/plugins/tags/maintenance/)[management](https://wordpress.org/plugins/tags/management/)
   [security](https://wordpress.org/plugins/tags/security/)[site health](https://wordpress.org/plugins/tags/site-health/)
   [updates](https://wordpress.org/plugins/tags/updates/)
 *  [Advanced View](https://wordpress.org/plugins/bulwarden/advanced/)

## Ratings

No reviews have been submitted yet.

[Your review](https://wordpress.org/support/plugin/bulwarden/reviews/#new-post)

[See all reviews](https://wordpress.org/support/plugin/bulwarden/reviews/)

## Contributors

 *   [ jgloeckl.de ](https://profiles.wordpress.org/bulwarden/)

## Support

Got something to say? Need help?

 [View support forum](https://wordpress.org/support/plugin/bulwarden/)