# File Integrity Alert Fired — Investigate and Restore

> GuardPress File Integrity Monitor flagged a changed or deleted file. Rule out plugin updates and deploys, then restore from WordPress.org or escalate.

- Canonical: <https://royalplugins.com/support/guardpress/file-integrity-alert-investigation/>
- HTML version: <https://royalplugins.com/support/guardpress/file-integrity-alert-investigation/>

---

GuardPress’s File Integrity Monitor flagged a file as modified, deleted, or newly added in `/wp-admin/`, `/wp-includes/`, a plugin, theme, or your `uploads/` directory. **Most alerts have a routine cause** (a plugin or theme just auto-updated, you ran a deploy, WordPress installed an update overnight) but a small minority are real compromises. This runbook is the triage flow: identify the file category in 60 seconds, rule out routine causes, then either Restore from the canonical WordPress.org source or escalate.

### Triage in 3 minutes — the short version

(1) Open **GuardPress → File Monitor**. (2) Check **WP Admin → Updates** and your last few audit-log entries — if a plugin/theme/core update happened in the last 24 hours, that’s almost certainly the cause and the alerts can be Ignored. (3) For anything else: if the row has a **Restore** button, click it — the file will be pulled from `core.svn.wordpress.org` or `downloads.wordpress.org` and written in place. (4) For files with no Restore button (custom themes, mu-plugins, `wp-config.php`), restore from a backup — [SiteVault Pro](https://royalplugins.com/sitevault/) has one-click restore.

## What a File Integrity Alert Actually Means

The File Integrity Monitor runs on the `guardpress_daily_scan` cron hook and walks WordPress core, active plugins, the active theme, and the `uploads/` directory. For each file it computes a SHA-256 hash via `hash_file()` and compares against the previous scan’s baseline. When a hash changes, the file appears as a row in the `gp_file_changes` table with one of three statuses, and a consolidated alert email is sent at the end of the scan (one email per scan since 1.6.24, not one per file).

The three statuses you’ll see in the File Monitor admin page:

- **Added** — the file didn’t exist at the previous scan and now does. Most common cause: a plugin update added a new file; less common but worth investigating: a webshell uploaded to `uploads/`.
- **Modified** — the file existed before, still exists, but its content hash changed. Most common cause: plugin / theme / core update.
- **Deleted** — the file existed before and is now gone. Most common cause: a plugin update removed a file that the new version no longer needs.

The alert is a *signal*, not a verdict. The signal is reliable (the hash comparison is exact). The interpretation is what this runbook is for.

## Step 1: Rule Out Routine Causes

In the overwhelming majority of cases, file integrity alerts have an easy-to-recognise legitimate source. Check these first before assuming the worst:

### Did a plugin or theme update just run?

Open **WP Admin → Dashboard → Updates** and scroll to the “Recently Installed Plugins” / “Recently Updated” sections. If anything updated in the last 24 hours, the file changes are expected. WordPress’s auto-updates run silently on a daily schedule for plugins and themes that opted in, so this is a more common cause than people expect.

### Did WordPress core auto-update?

If the changed files are under `/wp-admin/`, `/wp-includes/`, or are top-level files like `wp-blog-header.php`, check whether WordPress core auto-updated to a minor version (security release) overnight. WP Admin → Updates shows current core version; if it’s a recent timestamp, that’s your cause.

### Did you (or someone on your team) deploy code?

Custom themes, mu-plugins, and your own plugins won’t typically be auto-updated. But if you (or a developer / agency working on the site) ran a deploy, did a git pull on the server, or edited theme files in the WP admin theme editor, those files will show up as changed. Check your git log / deploy log / theme-editor history.

### Did a security plugin or migration plugin run?

Some plugins legitimately write files during normal operation: SiteVault during a backup or restore, ForgeCache during cache regeneration, page builders generating CSS files (Elementor’s `elementor/css/`, Divi’s `et-cache/`). These directories should generally be in the file-monitor skip list (added in 1.6.7+ via `guardpress_file_monitor_skip_patterns`), but custom setups can still surface them.

Quick correlation: timestamp matching

If the file-change timestamp in **GuardPress → File Monitor** matches the timestamp of a known event (Updates page entry, git deploy log, scheduled backup), you have your answer. If the timestamp doesn’t correlate with anything you can identify, that’s when investigation actually starts.

## Step 2: Identify the File Category (Determines Your Options)

GuardPress assigns every flagged file to one of four categories. The category determines whether you can Restore inline, and from where:

#### 1. WordPress core

Files under `/wp-admin/`, `/wp-includes/`, or top-level `wp-*.php` (e.g. `wp-login.php`, `wp-config-sample.php`).

##### Restore source

**Available.** Pulled from `core.svn.wordpress.org` at your installed WP version. Click the **Restore** button on the row in **GuardPress → File Monitor**.

#### 2. WordPress.org-hosted plugin

Files under `/wp-content/plugins/<slug>/` where `<slug>` matches a plugin on the WordPress.org Plugin Directory.

##### Restore source

**Available.** The latest plugin zip is downloaded from `downloads.wordpress.org/plugin/<slug>.zip`, the target file is extracted, and written in place. Note: this restores from the *latest* version on WP.org, not your currently-installed version — so if the changed file disappeared in a later plugin release, Restore will give you the newest version’s file (which may differ from what was there before).

#### 3. WordPress.org-hosted theme

Files under `/wp-content/themes/<slug>/` where `<slug>` matches a theme on the WordPress.org Theme Directory.

##### Restore source

**Available.** Same mechanism as plugins — latest theme zip from `downloads.wordpress.org/theme/<slug>.zip`.

#### 4. Custom / non-WP.org files

Files in `/wp-content/mu-plugins/`, `wp-config.php`, drop-ins (`object-cache.php`, `advanced-cache.php`), themes not hosted on WP.org (your custom theme, a premium theme like Astra Pro, a child theme), plugins not on WP.org (your own custom plugins, Royal Plugins Pro tier, anything you built or bought directly).

##### Restore source

**Not available inline.** The Restore button is hidden for these because GuardPress has no canonical source to compare against (we deliberately don’t cache shadow copies — that’s what backup plugins are for). The row will show *“No canonical source for this file — restore from a backup (SiteVault Pro) instead.”*

For categories 1, 2, and 3 you have a one-click recovery path. For category 4 you need a backup.

## Step 3: Take Action

### If Restore is available (categories 1, 2, 3)

#### Open the File Monitor admin page

Go to **GuardPress → File Monitor**. Locate the row for the changed file.

#### Click the Restore button

GuardPress fetches the canonical file (core from `core.svn.wordpress.org`, plugin/theme from `downloads.wordpress.org`), writes it to the target path via `WP_Filesystem`, and writes a `file_restore_attempt` audit log entry at INFO severity. On success the row updates to show the new clean baseline.

#### Confirm the change in the audit log

**GuardPress → Audit Log** → filter for the most recent entries. You should see `file_restore_attempt` with the file path. If the restore failed (network error fetching the zip, file-system permission issue, etc.), the audit log entry shows the failure reason.

#### Test the affected functionality

If the restored file is in a plugin or theme that you actively use, exercise the affected feature to confirm everything still works after restore. WP.org always serves the canonical version — if your customisations were on top of that file, Restore will overwrite them.

### If Restore is not available (category 4 — custom files)

The file has no canonical source GuardPress can fetch. Your options:

- **Restore from a backup** — if you’re running [SiteVault Pro](https://royalplugins.com/sitevault/), open it and restore the affected file from a backup taken before the change. SiteVault stores per-file diffs so you can restore a single file without rolling back the whole site.
- **If you (or your developer) made the change deliberately** — nothing more to do. The new file content automatically becomes the new baseline on the next scheduled scan. No manual action is needed; the row simply stops appearing once the next scan establishes the new hash as the baseline.
- **If you have no backup and don’t recognise the change** — this is the hard scenario. Compare the file content against a known-good copy from your git repo, staging environment, or a previous deploy artifact. If the file looks malicious (PHP eval, base64-decoded payload, obfuscated code), run the Malware Scanner from **GuardPress → Malware Scanner → Run Malware Scan Now** and treat the site as compromised — see [WordPress Malware Removal](https://royalplugins.com/blog/wordpress-malware-removal-guide/) for the full cleanup path.

Don’t restore wp-config.php from an old backup blindly

If `wp-config.php` shows as modified and you don’t remember changing it, investigate before restoring. The file legitimately changes when you (or WordPress) rotate authentication salts, change the table prefix, or add a constant. Restoring from an old backup may undo a security update you want to keep.

## Recognising False Positives (Common Patterns)

These are file changes that look alarming but are almost always benign:

- **Cache plugins regenerating CSS / JS** — Elementor’s `wp-content/uploads/elementor/css/`, Divi’s `wp-content/et-cache/`, page-builder block CSS files. These regenerate on theme save, page edit, plugin update. Add these paths to the file-monitor skip list under **GuardPress → Settings → Monitoring & Scanning** if they’re noisy.
- **Backup plugin working directories** — `wp-content/uploads/sitevault/`, `wp-content/updraft/`, `wp-content/backups*`, `wp-content/ai1wm-backups/`. The file monitor in 1.6.7+ ships skip patterns for the most common backup plugin paths, but custom setups can still surface them.
- **Vendor / node\_modules in custom plugins** — if your developer ran `composer install` or `npm install` on the server. The skip list covers `vendor/`, `node_modules/`, `.git/`, and `.svn/` by default.
- **SEO plugins regenerating sitemaps** — some SEO plugins write a sitemap file to disk instead of generating it dynamically.

## If You’re Getting Too Many File Integrity Emails

The emails are gated by deduplication state — pre-1.6.21 every daily scan re-emailed the same unresolved findings, and pre-1.6.24 the file monitor sent one email per changed file. Both bugs are fixed at 1.6.24+. If your inbox is being flooded, update GuardPress first. Full diagnosis flow at [**Quieting GuardPress Security Alert Email Flood**](https://royalplugins.com/support/guardpress/quieting-security-alert-emails/).

## Still Stuck? Email Priority Support

If you’ve worked through the triage flow and you’re not sure whether a file change is legitimate, or Restore is failing with an error, or you suspect a real compromise:

Email **[support@royalplugins.com](mailto:support@royalplugins.com)** with the diagnostic info below. Priority email support is included with your GuardPress Pro license — typical response time is within 24 hours, and we treat suspected-compromise tickets as highest priority.

#### Information to include in your email

- **GuardPress version** from **WP Admin → Plugins** (1.6.7+ ideally for the Restore feature, 1.6.24+ for clean email behaviour)
- **WordPress version** from **WP Admin → Updates**
- **The full file path(s)** flagged by the alert — e.g. `wp-content/plugins/example-plugin/includes/file.php`
- **The change type** — modified, deleted, or new
- **The timestamp** of the change from **GuardPress → File Monitor**
- **What category** the file is in — WP core / WP.org plugin / WP.org theme / custom / unknown
- **Whether the Restore button appeared** on the row, and if you clicked it, what audit-log entry was written
- **What changed in the last 24 hours** — updates, deploys, backups, content edits — anything that could correlate with the change timestamp
- **If you suspect compromise**: a one-line description of any other symptoms — unexpected admin users, traffic spikes, defaced pages, redirects, spam comments, etc.

Related GuardPress file-monitor and malware topics

If file changes are the start of a bigger investigation:

- [**WordPress Malware Removal**](https://royalplugins.com/blog/wordpress-malware-removal-guide/) — if the file change looks like a real compromise (PHP eval, base64 payloads, unknown admin users)
- [**Quieting Security Alert Email Flood**](https://royalplugins.com/support/guardpress/quieting-security-alert-emails/) — if file-monitor emails are arriving 100+ at a time or repeating daily
- [**File Integrity Monitor overview**](https://royalplugins.com/support/guardpress/#file-monitor) — the short feature description on the main GuardPress support page
- [**SiteVault Pro**](https://royalplugins.com/sitevault/) — one-click restore from per-file backups for custom files the canonical-source flow can’t reach

[Back to GuardPress Support](https://royalplugins.com/support/guardpress/)
[GuardPress Plugin Page](https://royalplugins.com/guardpress/)
