PluginProbe
Vigilant – 100% Free Security Suite: Firewall, 2FA, Login, Headers, Scanner… / 3.0.2
Vigilant – 100% Free Security Suite: Firewall, 2FA, Login, Headers, Scanner… v3.0.2
3.0.5 3.0.4 3.0.3 3.0.2 3.0.1 3.0.0 2.11.12 2.11.11 2.11.10 2.11.9 2.11.7 2.11.8 2.11.6 2.11.5 2.11.4 2.11.3 2.11.1 2.11.2 2.11.0 2.10.5 2.10.4 2.10.3 2.10.2 2.10.1 2.10.0 All 93 releases
← All changes | admin/class-admin.php +39 -226 3.0.3 → 3.0.2 View file →
@@ -1829,8 +1829,9 @@
1829 1829 'scanComplete' => __( 'Scan complete', 'vigilante' ),
1830 1830 'loading' => __( 'Loading...', 'vigilante' ),
1831 1831 'searching' => __( 'Searching...', 'vigilante' ),
1832 1832 'noUsersFound' => __( 'No users found', 'vigilante' ),
1833 + 'searchError' => __( 'Error searching users', 'vigilante' ),
1833 1834 'sending' => __( 'Sending...', 'vigilante' ),
1834 1835 'sendNotification' => __( 'Send notification now', 'vigilante' ),
1835 1836 'notificationsSent' => __( 'notifications sent', 'vigilante' ),
1836 1837 'skipped' => __( 'skipped', 'vigilante' ),
@@ -1849,9 +1850,9 @@
1849 1850 'modified' => __( 'Modified', 'vigilante' ),
1850 1851 'suspicious' => __( 'Suspicious', 'vigilante' ),
1851 1852 'totalScanned' => __( 'Total Scanned', 'vigilante' ),
1852 1853 'suspiciousFiles' => __( 'Suspicious Files', 'vigilante' ),
1853 - 'suspiciousWarning' => __( 'Files that can run code where none is expected, or that contain code written the way malware hides itself. Real infections show up here, and so do harmless files that plugins generate. Check the path and the reason before acting.', 'vigilante' ),
1854 + 'suspiciousWarning' => __( 'These files may contain malicious code or are in unexpected locations. Review immediately!', 'vigilante' ),
1854 1855 'file' => __( 'File', 'vigilante' ),
1855 1856 'reason' => __( 'Reason', 'vigilante' ),
1856 1857 'type' => __( 'Type', 'vigilante' ),
1857 1858 'unknown' => __( 'Unknown', 'vigilante' ),
@@ -1860,13 +1861,13 @@
1860 1861 'logWhatItMeans' => __( 'What it means', 'vigilante' ),
1861 1862 'logWhatToDo' => __( 'What to do', 'vigilante' ),
1862 1863 'logSelfSeeDetails' => __( 'Open File Integrity for the full detail', 'vigilante' ),
1863 1864 'modifiedFiles' => __( 'Modified Files', 'vigilante' ),
1864 - 'modifiedDescription' => __( 'These files do not match the copy WordPress.org publishes for the installed version.', 'vigilante' ),
1865 + 'modifiedDescription' => __( 'These files (apparently) differ from the original WordPress or plugin versions.', 'vigilante' ),
1865 1866 'extraFiles' => __( 'Extra Files', 'vigilante' ),
1866 1867 'extra' => __( 'Extra', 'vigilante' ),
1867 1868 'ignored' => __( 'Ignored', 'vigilante' ),
1868 - 'extraDescription' => __( 'Files that are not part of WordPress, or of the plugin or theme they sit in. Many are legitimate, and an injected file looks the same from here, so confirm where each one comes from.', 'vigilante' ),
1869 + 'extraDescription' => __( 'PHP files found in plugins or themes that are not part of the original distribution from WordPress.org.', 'vigilante' ),
1869 1870 'actions' => __( 'Actions', 'vigilante' ),
1870 1871 'ignore' => __( 'Ignore', 'vigilante' ),
1871 1872 'ignoring' => __( 'Ignoring...', 'vigilante' ),
1872 1873 'fileIgnored' => __( 'File added to ignored list.', 'vigilante' ),
@@ -1874,8 +1875,9 @@
1874 1875 'confirmClearIgnored' => __( 'Remove all files from the ignored list? They will appear in scan results again.', 'vigilante' ),
1875 1876 'ignoredCleared' => __( 'Ignored files list cleared. Page will reload...', 'vigilante' ),
1876 1877 'selectAll' => __( 'Select all', 'vigilante' ),
1877 1878 'bulkIgnoreSelected' => __( 'Ignore selected', 'vigilante' ),
1879 + 'bulkUnignoreSelected'=> __( 'Stop ignoring selected', 'vigilante' ),
1878 1880 'bulkNoSelection' => __( 'Select at least one file first.', 'vigilante' ),
1879 1881 'bulkConfirmIgnore' => __( 'Ignore the selected files? They will be hidden from future scan results until you remove them from the ignored list.', 'vigilante' ),
1880 1882 'bulkConfirmUnignore' => __( 'Remove the selected files from the ignored list? They will appear in scan results again.', 'vigilante' ),
1881 1883 'bulkProcessing' => __( 'Processing...', 'vigilante' ),
@@ -1880,11 +1882,11 @@
1880 1882 'bulkConfirmUnignore' => __( 'Remove the selected files from the ignored list? They will appear in scan results again.', 'vigilante' ),
1881 1883 'bulkProcessing' => __( 'Processing...', 'vigilante' ),
1882 1884 /* translators: %d: number of files selected for bulk action. */
1883 1885 'bulkSelectedCount' => __( '%d selected', 'vigilante' ),
1884 - 'allClear' => __( 'Good job! Nothing to report in the files that were checked.', 'vigilante' ),
1886 + 'allClear' => __( 'All files verified - no issues found!', 'vigilante' ),
1885 1887 'criticalConfigTitle' => __( 'Critical config files modified', 'vigilante' ),
1886 - 'criticalConfigDesc' => __( 'These files changed since you last approved them. They are a common target for code injection, and they are also rewritten by cache, security and redirection plugins, often on every update. Review the changes and approve them if they belong to something you use: approving records the current content as the reference and does not touch the file. Vigilant\'s own blocks are excluded from this check, and Vigilant never restores these files by itself.', 'vigilante' ),
1888 + 'criticalConfigDesc' => __( 'These files are common targets for code injection. Review the changes and approve if they are legitimate. Vigilant\'s own blocks are excluded from this check.', 'vigilante' ),
1887 1889 'approve' => __( 'Approve', 'vigilante' ),
1888 1890 'approving' => __( 'Approving...', 'vigilante' ),
1889 1891 'approvalLockedNotice' => $this->critical_approval_notice(),
1890 1892 'criticalApproved' => __( 'Change approved. Next scan will use the current state as baseline.', 'vigilante' ),
@@ -1977,10 +1979,13 @@
1977 1979 'noLogsToExport' => __( 'No logs to export', 'vigilante' ),
1978 1980 'exportFailed' => __( 'Export failed', 'vigilante' ),
1979 1981 'exportLogs' => __( 'Export Logs', 'vigilante' ),
1980 1982 // Backup strings
1983 + 'backupCreated' => __( 'Backup created successfully.', 'vigilante' ),
1981 1984 'createBackupNow' => __( 'Download Backup', 'vigilante' ),
1982 1985 'downloadBackup' => __( 'Download Backup (.zip)', 'vigilante' ),
1986 + /* translators: %d: number of tables */
1987 + 'tablesCount' => __( '%d tables', 'vigilante' ),
1983 1988 /* translators: 1: table count, 2: human-readable size */
1984 1989 'dbTablesTotal' => __( '%1$d tables total (%2$s)', 'vigilante' ),
1985 1990 /* translators: 1: selected count, 2: human-readable size */
1986 1991 'dbTablesSelected' => __( '%1$d tables selected (%2$s)', 'vigilante' ),
@@ -1987,8 +1992,9 @@
1987 1992 // Settings search strings
1988 1993 'searchNoResults' => __( 'No matching settings found.', 'vigilante' ),
1989 1994 /* translators: %d: number of results that did not fit in the list. */
1990 1995 'searchMoreResults' => __( '%d more results. Refine the search to see them.', 'vigilante' ),
1996 + 'searchInTab' => __( 'in', 'vigilante' ),
1991 1997 // Modules string
1992 1998 /* translators: 1: enabled count, 2: total count */
1993 1999 'modulesEnabled' => __( '%1$d / %2$d modules enabled', 'vigilante' ),
1994 2000 // Activity log label maps for JS rendering
@@ -1993,9 +1999,8 @@
1993 1999 'modulesEnabled' => __( '%1$d / %2$d modules enabled', 'vigilante' ),
1994 2000 // Activity log label maps for JS rendering
1995 2001 'eventTypeLabels' => array(
1996 2002 'login' => __( 'Login', 'vigilante' ),
1997 - '2fa' => __( 'Two-factor', 'vigilante' ),
1998 2003 'user' => __( 'User', 'vigilante' ),
1999 2004 'content' => __( 'Content', 'vigilante' ),
2000 2005 'plugin' => __( 'Plugin', 'vigilante' ),
2001 2006 'theme' => __( 'Theme', 'vigilante' ),
@@ -2061,8 +2066,10 @@
2061 2066 /* translators: 1: first item number, 2: last item number, 3: total items */
2062 2067 'paginationOf' => __( '%1$d–%2$d of %3$d', 'vigilante' ),
2063 2068 'paginationEmpty' => __( '0 items', 'vigilante' ),
2064 2069 // Security Analyzer strings
2070 + 'analyzerScanNow' => __( 'Scan now', 'vigilante' ),
2071 + 'analyzerScanning' => __( 'Scanning…', 'vigilante' ),
2065 2072 'analyzerFastPhase' => __( 'Running fast checks…', 'vigilante' ),
2066 2073 'analyzerSlowPhase' => __( 'Running remote checks…', 'vigilante' ),
2067 2074 'analyzerScanComplete' => __( 'Security scan complete.', 'vigilante' ),
2068 2075 'analyzerScanFailed' => __( 'Security scan failed.', 'vigilante' ),
@@ -2068,8 +2075,11 @@
2068 2075 'analyzerScanFailed' => __( 'Security scan failed.', 'vigilante' ),
2069 2076 'analyzerShowDetails' => __( 'Show detailed breakdown', 'vigilante' ),
2070 2077 'analyzerHideDetails' => __( 'Hide detailed breakdown', 'vigilante' ),
2071 2078 'analyzerGoToSetting' => __( 'Go to setting', 'vigilante' ),
2079 + 'analyzerNoData' => __( 'No data yet — run a scan to populate this category.', 'vigilante' ),
2080 + 'analyzerJustNow' => __( 'just now', 'vigilante' ),
2081 + 'analyzerAgo' => __( 'ago', 'vigilante' ),
2072 2082 'analyzerSettingsSaved' => __( 'Analyzer settings saved.', 'vigilante' ),
2073 2083 'analyzerLastScanJustNow' => __( 'Last scan just now', 'vigilante' ),
2074 2084 'analyzerQualityExcellent' => __( 'Excellent', 'vigilante' ),
2075 2085 'analyzerQualityGood' => __( 'Good', 'vigilante' ),
@@ -2075,8 +2085,9 @@
2075 2085 'analyzerQualityGood' => __( 'Good', 'vigilante' ),
2076 2086 'analyzerQualityFair' => __( 'Fair', 'vigilante' ),
2077 2087 'analyzerQualityPoor' => __( 'Poor', 'vigilante' ),
2078 2088 'analyzerQualityCritical' => __( 'Critical', 'vigilante' ),
2089 + 'analyzerPts' => __( 'pts', 'vigilante' ),
2079 2090 'analyzerLearnMore' => __( 'Learn more', 'vigilante' ),
2080 2091 'analyzerInfoAllClear' => __( 'All clear', 'vigilante' ),
2081 2092 /* translators: %d: number of findings in an info-only category */
2082 2093 'analyzerInfoFindings' => __( '%d findings', 'vigilante' ),
@@ -3730,9 +3741,8 @@
3730 3741 <label>
3731 3742 <input type="checkbox" name="firewall[block_bad_bots]" value="1" <?php disabled( $vg_main_locked ); ?> <?php checked( ! empty( $options['block_bad_bots'] ) ); ?>>
3732 3743 <?php esc_html_e( 'Block known malicious bots and scanners', 'vigilante' ); ?>
3733 3744 </label>
3734 - <p class="description"><?php esc_html_e( 'The list also stops SEO crawlers such as Ahrefs, Semrush, Majestic and Screaming Frog, and command line clients such as curl, wget and python-requests. To let one of them through, add its name to the User-Agent Whitelist below. On Apache part of the list is applied in .htaccess, before WordPress loads, so those requests get a 403 and do not appear in the Security Audit.', 'vigilante' ); ?></p>
3735 3745 </td>
3736 3746 </tr>
3737 3747 </table>
3738 3748
@@ -4045,9 +4055,9 @@
4045 4055 <th scope="row"><?php esc_html_e( 'Limit HTTP Methods', 'vigilante' ); ?></th>
4046 4056 <td>
4047 4057 <label>
4048 4058 <input type="checkbox" name="firewall[limit_http_methods]" value="1" <?php checked( ! empty( $options['limit_http_methods'] ) ); ?>>
4049 - <?php esc_html_e( 'Block the HTTP methods WordPress does not use (TRACE, TRACK, CONNECT and any unknown one). GET, POST, HEAD, OPTIONS, PUT, PATCH and DELETE keep working.', 'vigilante' ); ?>
4059 + <?php esc_html_e( 'Allow only GET, POST, HEAD (blocks PUT, DELETE, TRACE, etc.)', 'vigilante' ); ?>
4050 4060 </label>
4051 4061 </td>
4052 4062 </tr>
4053 4063 </table>
@@ -6328,9 +6338,9 @@
6328 6338 <select id="vigilante-f-audit-alerts-immediate-min-severity" name="audit_alerts[immediate][min_severity]">
6329 6339 <option value="critical" <?php selected( $alert_severity, 'critical' ); ?>><?php esc_html_e( 'Critical only (recommended)', 'vigilante' ); ?></option>
6330 6340 <option value="warning" <?php selected( $alert_severity, 'warning' ); ?>><?php esc_html_e( 'Warning and Critical', 'vigilante' ); ?></option>
6331 6341 </select>
6332 - <p class="description"><?php esc_html_e( 'A closed plugin is logged as Critical, so "Critical only" covers it. A new administrator and a change of role are logged as Warning: they have their own emails, in Users > Admin monitoring, and reach this alert only with "Warning and Critical".', 'vigilante' ); ?></p>
6342 + <p class="description"><?php esc_html_e( 'A new administrator, a closed plugin or a privilege escalation are all logged as Critical, so "Critical only" already covers them.', 'vigilante' ); ?></p>
6333 6343 </td>
6334 6344 </tr>
6335 6345 <tr id="field-audit-alerts-threshold">
6336 6346 <th scope="row"><?php esc_html_e( 'Threshold alerts', 'vigilante' ); ?></th>
@@ -6423,9 +6433,8 @@
6423 6433
6424 6434 // Label maps for translated display
6425 6435 $type_labels = array(
6426 6436 'login' => __( 'Login', 'vigilante' ),
6427 - '2fa' => __( 'Two-factor', 'vigilante' ),
6428 6437 'user' => __( 'User', 'vigilante' ),
6429 6438 'content' => __( 'Content', 'vigilante' ),
6430 6439 'plugin' => __( 'Plugin', 'vigilante' ),
6431 6440 'theme' => __( 'Theme', 'vigilante' ),
@@ -6454,9 +6463,8 @@
6454 6463 <input type="text" id="vigilante-log-search" aria-label="<?php esc_attr_e( 'Search the activity log', 'vigilante' ); ?>" size="1" placeholder="<?php esc_attr_e( 'Search logs (min. 3 characters)...', 'vigilante' ); ?>" class="vigilante-log-search-input">
6455 6464 <select id="vigilante-log-type-filter" aria-label="<?php esc_attr_e( 'Filter the log by event type', 'vigilante' ); ?>">
6456 6465 <option value=""><?php esc_html_e( 'All Types', 'vigilante' ); ?></option>
6457 6466 <option value="login"><?php esc_html_e( 'Login', 'vigilante' ); ?></option>
6458 - <option value="2fa"><?php esc_html_e( 'Two-factor', 'vigilante' ); ?></option>
6459 6467 <option value="user"><?php esc_html_e( 'User', 'vigilante' ); ?></option>
6460 6468 <option value="content"><?php esc_html_e( 'Content', 'vigilante' ); ?></option>
6461 6469 <option value="plugin"><?php esc_html_e( 'Plugin', 'vigilante' ); ?></option>
6462 6470 <option value="theme"><?php esc_html_e( 'Theme', 'vigilante' ); ?></option>
@@ -7000,49 +7008,8 @@
7000 7008 </details>
7001 7009 <?php
7002 7010 }
7003 7011
7004 - /**
7005 - * Print what each kind of finding in a list usually is and what to do
7006 - *
7007 - * One line per kind actually present in the list, from the single source
7008 - * of that text, Vigilante_File_Integrity::finding_guidance().
7009 - *
7010 - * @param array $items Findings of one section of the last scan.
7011 - */
7012 - private function render_fi_guidance( $items ) {
7013 - $seen = array();
7014 - $guides = array();
7015 -
7016 - foreach ( (array) $items as $item ) {
7017 - $type = is_array( $item ) ? (string) ( $item['type'] ?? '' ) : '';
7018 -
7019 - if ( '' === $type || 'vigilante_self' === $type || isset( $seen[ $type ] ) ) {
7020 - continue;
7021 - }
7022 - $seen[ $type ] = true;
7023 -
7024 - $guide = Vigilante_File_Integrity::finding_guidance( $type );
7025 -
7026 - if ( '' !== $guide['advice'] ) {
7027 - // A plugin and a theme share their text: one line for both,
7028 - // under the two names.
7029 - $guides[ $guide['advice'] ][] = $guide['label'];
7030 - }
7031 - }
7032 -
7033 - if ( empty( $guides ) ) {
7034 - return;
7035 - }
7036 - ?>
7037 - <ul class="vigilante-fi-guidance" style="margin: 8px 0 12px 18px; list-style: disc;">
7038 - <?php foreach ( $guides as $advice => $labels ) : ?>
7039 - <li><strong><?php echo esc_html( implode( ', ', $labels ) ); ?>:</strong> <?php echo esc_html( $advice ); ?></li>
7040 - <?php endforeach; ?>
7041 - </ul>
7042 - <?php
7043 - }
7044 -
7045 7012 private function render_tab_file_integrity() {
7046 7013 $is_disabled = $this->render_module_disabled_notice( 'file_integrity' );
7047 7014 $options = $this->settings->get_section( 'file_integrity' );
7048 7015 // On the main site of a network the critical-file scan is the network's
@@ -7114,10 +7081,9 @@
7114 7081 <h2>
7115 7082 <?php esc_html_e( 'File Integrity Monitoring', 'vigilante' ); ?>
7116 7083 <span class="vigilante-method-badge php"><?php esc_html_e( 'PHP', 'vigilante' ); ?></span>
7117 7084 </h2>
7118 - <p><?php esc_html_e( 'Compares WordPress, and the plugins and themes that come from WordPress.org, with the official copy of each file, looks for code where there should be none (uploads and the site root) and watches wp-config.php and .htaccess for changes.', 'vigilante' ); ?></p>
7119 - <p class="description"><?php esc_html_e( 'What it cannot compare: plugins and themes that are not on WordPress.org, must-use plugins, drop-ins (advanced-cache.php, object-cache.php and the like) and the other folders of wp-content have no official copy. They are searched for hidden code, which finds malware that disguises itself and misses most code written in the open. The results name what could not be compared.', 'vigilante' ); ?></p>
7085 + <p><?php esc_html_e( 'Detects file modifications using WordPress.org checksums.', 'vigilante' ); ?></p>
7120 7086
7121 7087 <table class="form-table">
7122 7088 <tr>
7123 7089 <th scope="row"><?php esc_html_e( 'Automatic Scans', 'vigilante' ); ?></th>
@@ -7140,13 +7106,13 @@
7140 7106 <tr>
7141 7107 <th scope="row"><label for="vigilante-f-file-integrity-notify-level"><?php esc_html_e( 'Email Notifications', 'vigilante' ); ?></label></th>
7142 7108 <td>
7143 7109 <select id="vigilante-f-file-integrity-notify-level" name="file_integrity[notify_level]">
7144 - <option value="all" <?php selected( $notify_level, 'all' ); ?>><?php esc_html_e( 'Every finding, modified files included', 'vigilante' ); ?></option>
7145 - <option value="suspicious_only" <?php selected( $notify_level, 'suspicious_only' ); ?>><?php esc_html_e( 'Serious findings only', 'vigilante' ); ?></option>
7110 + <option value="all" <?php selected( $notify_level, 'all' ); ?>><?php esc_html_e( 'All issues (modified + suspicious)', 'vigilante' ); ?></option>
7111 + <option value="suspicious_only" <?php selected( $notify_level, 'suspicious_only' ); ?>><?php esc_html_e( 'Suspicious files only', 'vigilante' ); ?></option>
7146 7112 <option value="disabled" <?php selected( $notify_level, 'disabled' ); ?>><?php esc_html_e( 'Disabled', 'vigilante' ); ?></option>
7147 7113 </select>
7148 - <p class="description"><?php esc_html_e( 'Serious findings are suspicious and extra files, changes in wp-config.php or .htaccess and closed plugins. That is the recommended choice: a file that is only modified is rarely more than an update that did not finish. The email goes out when a scan finds something new: a finding you were already told about is not sent again, unless the file changes once more.', 'vigilante' ); ?></p>
7114 + <p class="description"><?php esc_html_e( '"Suspicious files only" reduces noise by skipping modified file notifications. Recommended for most sites.', 'vigilante' ); ?></p>
7149 7115 </td>
7150 7116 </tr>
7151 7117 <tr>
7152 7118 <th scope="row"><?php esc_html_e( 'Instant Alert', 'vigilante' ); ?></th>
@@ -7152,11 +7118,11 @@
7152 7118 <th scope="row"><?php esc_html_e( 'Instant Alert', 'vigilante' ); ?></th>
7153 7119 <td>
7154 7120 <label>
7155 7121 <input type="checkbox" name="file_integrity[instant_alert]" value="1" <?php checked( ! empty( $options['instant_alert'] ) ); ?>>
7156 - <?php esc_html_e( 'Email every finding when a scan ends, modified files included, and email a closed plugin as soon as the daily check finds it', 'vigilante' ); ?>
7122 + <?php esc_html_e( 'Send immediate alert when modified, suspicious or additional files are detected, or when a closed plugin is found', 'vigilante' ); ?>
7157 7123 </label>
7158 - <p class="description"><?php esc_html_e( 'This takes precedence over the choice above, Disabled included.', 'vigilante' ); ?></p>
7124 + <p class="description"><?php esc_html_e( 'Fires even if the Email Notifications setting above is set to Disabled.', 'vigilante' ); ?></p>
7159 7125 <p class="description">
7160 7126 <?php
7161 7127 printf(
7162 7128 /* translators: %s: Link to notification settings */
@@ -7182,29 +7148,29 @@
7182 7148 <td>
7183 7149 <fieldset>
7184 7150 <label>
7185 7151 <input type="checkbox" name="file_integrity[scan_core]" value="1" <?php checked( $options['scan_core'] ?? true ); ?>>
7186 - <?php esc_html_e( 'WordPress core (compared with WordPress.org) and the other files in the site root', 'vigilante' ); ?>
7152 + <?php esc_html_e( 'Core files (compare against WordPress.org checksums)', 'vigilante' ); ?>
7187 7153 </label>
7188 7154 <br>
7189 7155 <label>
7190 7156 <input type="checkbox" name="file_integrity[scan_plugins]" value="1" <?php checked( $options['scan_plugins'] ?? true ); ?>>
7191 - <?php esc_html_e( 'Plugins (compared with WordPress.org; the rest, and the other folders of wp-content, are only searched for hidden code)', 'vigilante' ); ?>
7157 + <?php esc_html_e( 'Plugins (WordPress.org repository plugins)', 'vigilante' ); ?>
7192 7158 </label>
7193 7159 <br>
7194 7160 <label>
7195 7161 <input type="checkbox" name="file_integrity[scan_themes]" value="1" <?php checked( $options['scan_themes'] ?? true ); ?>>
7196 - <?php esc_html_e( 'Themes (compared with WordPress.org; the rest are only searched for hidden code)', 'vigilante' ); ?>
7162 + <?php esc_html_e( 'Themes (WordPress.org repository themes)', 'vigilante' ); ?>
7197 7163 </label>
7198 7164 <br>
7199 7165 <label>
7200 7166 <input type="checkbox" name="file_integrity[scan_uploads]" value="1" <?php checked( $options['scan_uploads'] ?? true ); ?>>
7201 - <?php esc_html_e( 'Uploads directory (PHP and other scripts, double extensions, .htaccess and PHP configuration files)', 'vigilante' ); ?>
7167 + <?php esc_html_e( 'Uploads directory (detect PHP files, double extensions, .htaccess)', 'vigilante' ); ?>
7202 7168 </label>
7203 7169 <br>
7204 7170 <label>
7205 7171 <input type="checkbox" name="file_integrity[scan_critical_config]" value="1" <?php disabled( $vg_main_locked ); ?> <?php checked( $options['scan_critical_config'] ?? true ); ?>>
7206 - <?php esc_html_e( 'wp-config.php and .htaccess (any change since you last approved them)', 'vigilante' ); ?>
7172 + <?php esc_html_e( 'Critical config files (wp-config.php, .htaccess baseline monitoring)', 'vigilante' ); ?>
7207 7173 <?php if ( $vg_main_locked ) : ?>
7208 7174 <span class="description" style="display:block;margin-left:24px;"><?php echo esc_html( Vigilante_Settings::get_shared_files_notice() ); ?></span>
7209 7175 <?php endif; ?>
7210 7176 </label>
@@ -7218,10 +7184,10 @@
7218 7184 </tr>
7219 7185 <tr>
7220 7186 <th scope="row"><label for="vigilante-f-file-integrity-excluded-paths"><?php esc_html_e( 'Excluded Paths', 'vigilante' ); ?></label></th>
7221 7187 <td>
7222 - <textarea id="vigilante-f-file-integrity-excluded-paths" name="file_integrity[excluded_paths]" rows="4" class="large-text code" placeholder="wp-content/backups"><?php echo esc_textarea( implode( "\n", $options['excluded_paths'] ?? array() ) ); ?></textarea>
7223 - <p class="description"><?php esc_html_e( 'One path per line, relative to the WordPress root. A path such as wp-content/backups excludes exactly that folder and everything under it. A name on its own, such as backups, excludes any folder called exactly that, wherever it is. Nothing in an excluded folder is looked at, so keep the list short.', 'vigilante' ); ?></p>
7188 + <textarea id="vigilante-f-file-integrity-excluded-paths" name="file_integrity[excluded_paths]" rows="4" class="large-text code" placeholder="wp-content/cache&#10;wp-content/languages"><?php echo esc_textarea( implode( "\n", $options['excluded_paths'] ?? array() ) ); ?></textarea>
7189 + <p class="description"><?php esc_html_e( 'One path per line, relative to the WordPress root. A path such as wp-content/cache excludes exactly that folder and everything under it. A name on its own, such as cache, excludes any folder called exactly that, wherever it is.', 'vigilante' ); ?></p>
7224 7190 </td>
7225 7191 </tr>
7226 7192 <tr>
7227 7193 <th scope="row"><label for="vigilante-f-file-integrity-excluded-extensions"><?php esc_html_e( 'Excluded Extensions', 'vigilante' ); ?></label></th>
@@ -7264,49 +7230,11 @@
7264 7230 <div id="vigilante-scan-results" class="vigilante-settings-section" style="display:none;"></div>
7265 7231
7266 7232 <?php $this->render_self_protection_box( $options ); ?>
7267 7233
7268 - <?php
7269 - // Whole folders of code left out of every scan. A partial scan tells
7270 - // how to check the rest by excluding what it did check, and those
7271 - // lines have to come out afterwards: with them in place a scan comes
7272 - // out complete and clean without having looked there. Said for as
7273 - // long as they are in the list, whoever put them there and why.
7274 - $vg_fi_tool = new Vigilante_File_Integrity( $this->settings, $this->database );
7275 - $vg_excluded_code = $vg_fi_tool->excluded_code_folders();
7276 - $vg_folders_to_skip = $vg_fi_tool->folders_to_exclude( $last_results );
7277 - ?>
7278 - <?php if ( ! empty( $vg_excluded_code ) ) : ?>
7279 - <div id="vigilante-fi-excluded-code" class="notice notice-warning inline">
7280 - <p>
7281 - <strong>
7282 - <?php
7283 - printf(
7284 - /* translators: %s: Comma separated list of folders */
7285 - esc_html__( 'Excluded Paths holds whole folders of plugins or themes, or the uploads folder: %s.', 'vigilante' ),
7286 - esc_html( implode( ', ', $vg_excluded_code ) )
7287 - );
7288 - ?>
7289 - </strong>
7290 - <?php esc_html_e( 'No scan looks inside them, the scheduled one included, and a scan can come out complete and clean without having checked them. If you added them to check the rest of a large site, take them out once that scan is done.', 'vigilante' ); ?>
7291 - </p>
7292 - </div>
7293 - <?php endif; ?>
7294 -
7295 7234 <?php if ( $last_scan || $has_closed || $closed_last_check > 0 ) : ?>
7296 7235 <div id="vigilante-section-fi-last-scan" class="vigilante-settings-section">
7297 7236 <h2><?php esc_html_e( 'Last Scan Results', 'vigilante' ); ?></h2>
7298 - <?php
7299 - // A scan the server stops halfway stores nothing, and neither
7300 - // does one WordPress never starts: the tab kept showing the
7301 - // last result that did finish, with nothing to say that scans
7302 - // had stopped. Its date is the only sign.
7303 - if ( $last_scan && $this->settings->is_module_enabled( 'file_integrity' ) && Vigilante_File_Integrity::is_scan_overdue( $last_scan, $options['scan_frequency'] ?? 'daily' ) ) :
7304 - ?>
7305 - <div class="notice notice-warning inline">
7306 - <p><strong><?php esc_html_e( 'Scans are scheduled, and none has finished since the date below.', 'vigilante' ); ?></strong> <?php esc_html_e( 'Either WordPress is not running its scheduled tasks, or the server stops the scan before it ends, and a scan that is stopped stores no result. What you see here is old. Run a scan now: if it finishes, the scheduled tasks are what is failing. If it does not, the site is too large for the time the server gives a request, and adding large folders that do not need checking to Excluded Paths leaves more time for the rest.', 'vigilante' ); ?></p>
7307 - </div>
7308 - <?php endif; ?>
7309 7237 <?php if ( $last_scan ) : ?>
7310 7238 <p>
7311 7239 <?php
7312 7240 // Build the "X files scanned" hint inline with the date so it doesn't
@@ -7389,112 +7317,12 @@
7389 7317 </div>
7390 7318 <?php endif; ?>
7391 7319 </div>
7392 7320
7393 - <?php
7394 - // A scan that could not finish, or could not get the official
7395 - // copy to compare with, checked less than it seems. Until now
7396 - // its errors were stored and never shown, and the tab could
7397 - // say that every file had passed.
7398 - $vg_scan_errors = ( $last_results && ! empty( $last_results['errors'] ) && is_array( $last_results['errors'] ) ) ? $last_results['errors'] : array();
7399 - $vg_scan_partial = ! empty( $vg_scan_errors ) || ( $last_results && ! empty( $last_results['incomplete'] ) );
7400 -
7401 - // Files of the official copies that are not on the server. Core
7402 - // files under wp-content are left out: results stored before
7403 - // the bundled themes and plugins got their own turn list
7404 - // there the ones people delete on purpose.
7405 - $vg_missing_core = array();
7406 - if ( $last_results && ! empty( $last_results['missing'] ) && is_array( $last_results['missing'] ) ) {
7407 - foreach ( $last_results['missing'] as $item ) {
7408 - if ( ! is_array( $item ) || ! isset( $item['file'] ) ) {
7409 - continue;
7410 - }
7411 -
7412 - $vg_missing_type = (string) ( $item['type'] ?? '' );
7413 -
7414 - if ( in_array( $vg_missing_type, array( 'plugin', 'theme' ), true )
7415 - || ( 'core' === $vg_missing_type && 0 !== strpos( (string) $item['file'], 'wp-content/' ) ) ) {
7416 - $vg_missing_core[] = (string) $item['file'];
7417 - }
7418 - }
7419 - }
7420 - ?>
7421 -
7422 - <?php if ( $last_results && ! empty( $last_results['unverified'] ) && is_array( $last_results['unverified'] ) ) : ?>
7423 - <p class="description">
7424 - <?php
7425 - printf(
7426 - /* translators: %s: Comma separated list of plugin and theme names */
7427 - esc_html__( 'No official copy to compare with, so only searched for hidden code: %s.', 'vigilante' ),
7428 - esc_html( implode( ', ', array_unique( array_map( 'strval', $last_results['unverified'] ) ) ) )
7429 - );
7430 - ?>
7431 - </p>
7432 - <?php endif; ?>
7433 -
7434 - <?php
7435 - // What the scan did not get to, by name. A scan starts from
7436 - // the beginning every time, so on a site too large for it
7437 - // these are the same on every scan, and whoever reads the
7438 - // result has to know that nothing here was looked at.
7439 - $vg_scan_notes = array_merge( $vg_scan_errors, Vigilante_File_Integrity::not_checked_lines( $last_results ) );
7440 - ?>
7441 - <?php if ( $vg_scan_partial ) : ?>
7442 - <div class="notice notice-warning inline">
7443 - <p><strong><?php esc_html_e( 'The last scan could not check everything, so its result is partial.', 'vigilante' ); ?></strong></p>
7444 - <?php if ( ! empty( $vg_scan_notes ) ) : ?>
7445 - <ul style="margin: 0 0 8px 18px; list-style: disc;">
7446 - <?php foreach ( $vg_scan_notes as $vg_scan_note ) : ?>
7447 - <li><?php echo esc_html( (string) $vg_scan_note ); ?></li>
7448 - <?php endforeach; ?>
7449 - </ul>
7450 - <?php endif; ?>
7451 - <p>
7452 - <?php
7453 - printf(
7454 - /* translators: %d: Seconds a scan runs for at most */
7455 - esc_html__( 'Run the scan again: a second scan is faster, because what it downloads from WordPress.org is kept for a while. If the result is still partial, either the server cannot reach WordPress.org or the site is larger than a scan can check in its %d seconds, and then every scan leaves the same part unchecked. Adding large folders that do not need checking to Excluded Paths leaves more time for the rest.', 'vigilante' ),
7456 - (int) Vigilante_File_Integrity::MAX_SCAN_SECONDS
7457 - );
7458 - ?>
7459 - </p>
7460 - <?php if ( ! empty( $vg_folders_to_skip ) ) : ?>
7461 - <p><strong><?php esc_html_e( 'To check what was left out:', 'vigilante' ); ?></strong></p>
7462 - <ol style="margin: 0 0 8px 18px;">
7463 - <li><?php esc_html_e( 'Deal first with what this scan found in the plugins and themes it did check: the next result will not list it. Then add the lines below, which are their folders, to Excluded Paths, higher up on this page, and save.', 'vigilante' ); ?></li>
7464 - <li><?php esc_html_e( 'Press Run Scan Now. The scan spends its time on the rest. If it comes out partial again, repeat with the lines it gives then.', 'vigilante' ); ?></li>
7465 - <li><?php esc_html_e( 'Take those lines out of Excluded Paths. While they are there no scan looks inside those folders, the scheduled one included.', 'vigilante' ); ?></li>
7466 - </ol>
7467 - <textarea id="vigilante-fi-folders-to-exclude" readonly rows="<?php echo (int) min( 12, max( 3, count( $vg_folders_to_skip ) ) ); ?>" class="large-text code" style="margin-bottom: 8px;"><?php echo esc_textarea( implode( "\n", $vg_folders_to_skip ) ); ?></textarea>
7468 - <?php endif; ?>
7469 - </div>
7470 - <?php endif; ?>
7471 -
7472 - <?php if ( ! empty( $vg_missing_core ) ) : ?>
7473 - <div class="vigilante-file-list">
7474 - <h3><?php esc_html_e( 'Missing Files', 'vigilante' ); ?></h3>
7475 - <p class="description"><?php esc_html_e( 'These files are in the official copy and not on the server. Reinstall what they belong to (WordPress from Dashboard > Updates, a plugin or a theme from its own screen) and scan again.', 'vigilante' ); ?></p>
7476 - <ul style="margin: 8px 0 12px 18px; list-style: disc;">
7477 - <?php foreach ( array_slice( $vg_missing_core, 0, 20 ) as $vg_missing_file ) : ?>
7478 - <li><code><?php echo esc_html( $vg_missing_file ); ?></code></li>
7479 - <?php endforeach; ?>
7480 - </ul>
7481 - <?php if ( count( $vg_missing_core ) > 20 ) : ?>
7482 - <p class="description">
7483 - <?php
7484 - /* translators: %d: Number of additional files */
7485 - printf( esc_html__( '... and %d more', 'vigilante' ), (int) ( count( $vg_missing_core ) - 20 ) );
7486 - ?>
7487 - </p>
7488 - <?php endif; ?>
7489 - </div>
7490 - <?php endif; ?>
7491 -
7492 7321 <?php if ( ! empty( $last_results['suspicious'] ) ) : ?>
7493 7322 <div class="vigilante-file-list vigilante-suspicious-files vigilante-paginated-section" data-bulk-mode="ignore">
7494 7323 <h3 style="color: #d63638;"><?php esc_html_e( 'Suspicious Files', 'vigilante' ); ?></h3>
7495 - <p class="description" style="color: #d63638;"><?php esc_html_e( '&#9888; Files that can run code where none is expected, or that contain code written the way malware hides itself. Real infections show up here, and so do harmless files that plugins generate. Check the path and the reason before acting.', 'vigilante' ); ?></p>
7496 - <?php $this->render_fi_guidance( $last_results['suspicious'] ); ?>
7324 + <p class="description" style="color: #d63638;"><?php esc_html_e( '&#9888; Warning: These files may contain malicious code or are in unexpected locations. Review immediately!', 'vigilante' ); ?></p>
7497 7325 <div class="vigilante-fi-bulk-bar">
7498 7326 <button type="button" class="button vigilante-bulk-ignore" disabled><?php esc_html_e( 'Ignore selected', 'vigilante' ); ?></button>
7499 7327 <span class="vigilante-fi-bulk-count" aria-live="polite"></span>
7500 7328 </div>
@@ -7530,11 +7358,8 @@
7530 7358 $file_path = (string) $item;
7531 7359 }
7532 7360 if ( 'vigilante_self' === $file_type ) {
7533 7361 $file_type = __( 'Vigilant (self)', 'vigilante' );
7534 - } else {
7535 - // A name a person can read, instead of the internal slug.
7536 - $file_type = Vigilante_File_Integrity::finding_guidance( $file_type )['label'];
7537 7362 }
7538 7363 ?>
7539 7364 <tr>
7540 7365 <th scope="row" class="check-column"><input type="checkbox" class="vigilante-fi-cb" value="<?php echo esc_attr( $file_path ); ?>"></th>
@@ -7553,10 +7378,9 @@
7553 7378
7554 7379 <?php if ( ! empty( $last_results['extra'] ) ) : ?>
7555 7380 <div class="vigilante-file-list vigilante-extra-files vigilante-paginated-section" data-bulk-mode="ignore">
7556 7381 <h3 style="color: #b32d2e;"><?php esc_html_e( 'Extra Files', 'vigilante' ); ?></h3>
7557 - <p class="description"><?php esc_html_e( 'Files that are not part of WordPress, or of the plugin or theme they sit in. Many are legitimate, and an injected file looks the same from here, so confirm where each one comes from.', 'vigilante' ); ?></p>
7558 - <?php $this->render_fi_guidance( $last_results['extra'] ); ?>
7382 + <p class="description"><?php esc_html_e( 'PHP files found in plugins or themes that are not part of the original distribution from WordPress.org. May be legitimate customizations or injected backdoors.', 'vigilante' ); ?></p>
7559 7383 <div class="vigilante-fi-bulk-bar">
7560 7384 <button type="button" class="button vigilante-bulk-ignore" disabled><?php esc_html_e( 'Ignore selected', 'vigilante' ); ?></button>
7561 7385 <span class="vigilante-fi-bulk-count" aria-live="polite"></span>
7562 7386 </div>
@@ -7578,11 +7402,8 @@
7578 7402 $file_reason = is_array( $item ) ? ( $item['reason'] ?? __( 'Unknown', 'vigilante' ) ) : __( 'Unknown', 'vigilante' );
7579 7403 $file_type = is_array( $item ) ? ( $item['type'] ?? 'unknown' ) : 'unknown';
7580 7404 if ( 'vigilante_self' === $file_type ) {
7581 7405 $file_type = __( 'Vigilant (self)', 'vigilante' );
7582 - } else {
7583 - // A name a person can read, instead of the internal slug.
7584 - $file_type = Vigilante_File_Integrity::finding_guidance( $file_type )['label'];
7585 7406 }
7586 7407 ?>
7587 7408 <tr>
7588 7409 <th scope="row" class="check-column"><input type="checkbox" class="vigilante-fi-cb" value="<?php echo esc_attr( $file_path ); ?>"></th>
@@ -7631,9 +7452,9 @@
7631 7452 <?php if ( ! empty( $critical_modified ) ) : ?>
7632 7453 <div class="vigilante-file-list vigilante-critical-config-files">
7633 7454 <h3 style="color: #e36210;"><?php esc_html_e( 'Critical config files modified', 'vigilante' ); ?></h3>
7634 7455 <p class="description">
7635 - <?php esc_html_e( 'These files changed since you last approved them. They are a common target for code injection, and they are also rewritten by cache, security and redirection plugins, often on every update. Review the changes and approve them if they belong to something you use: approving records the current content as the reference and does not touch the file. Vigilant\'s own blocks are excluded from this check, and Vigilant never restores these files by itself.', 'vigilante' ); ?>
7456 + <?php esc_html_e( 'These files are common targets for code injection. Review the changes and approve if they are legitimate. Vigilant\'s own blocks are excluded from this check.', 'vigilante' ); ?>
7636 7457 </p>
7637 7458 <table class="wp-list-table widefat fixed striped">
7638 7459 <thead>
7639 7460 <tr>
@@ -7794,10 +7615,9 @@
7794 7615
7795 7616 <?php if ( ! empty( $regular_modified ) ) : ?>
7796 7617 <div class="vigilante-file-list vigilante-paginated-section" data-bulk-mode="ignore">
7797 7618 <h3><?php esc_html_e( 'Modified Files', 'vigilante' ); ?></h3>
7798 - <p class="description"><?php esc_html_e( 'These files do not match the copy WordPress.org publishes for the installed version.', 'vigilante' ); ?></p>
7799 - <?php $this->render_fi_guidance( $regular_modified ); ?>
7619 + <p class="description"><?php esc_html_e( 'These files (apparently) differ from the original WordPress or plugin versions.', 'vigilante' ); ?></p>
7800 7620 <div class="vigilante-fi-bulk-bar">
7801 7621 <button type="button" class="button vigilante-bulk-ignore" disabled><?php esc_html_e( 'Ignore selected', 'vigilante' ); ?></button>
7802 7622 <span class="vigilante-fi-bulk-count" aria-live="polite"></span>
7803 7623 </div>
@@ -7828,11 +7648,8 @@
7828 7648 $file_path = (string) $item;
7829 7649 }
7830 7650 if ( 'vigilante_self' === $file_type ) {
7831 7651 $file_type = __( 'Vigilant (self)', 'vigilante' );
7832 - } else {
7833 - // A name a person can read, instead of the internal slug.
7834 - $file_type = Vigilante_File_Integrity::finding_guidance( $file_type )['label'];
7835 7652 }
7836 7653 ?>
7837 7654 <tr>
7838 7655 <th scope="row" class="check-column"><input type="checkbox" class="vigilante-fi-cb" value="<?php echo esc_attr( $file_path ); ?>"></th>
@@ -7854,11 +7671,11 @@
7854 7671 // above, this line contradicted it (its findings no longer
7855 7672 // travel in the tables below).
7856 7673 $vg_self_alarm = in_array( $this->self_integrity_summary( $options )['tone'], array( 'critical', 'off', 'warning' ), true );
7857 7674 ?>
7858 - <?php if ( $last_results && ! $vg_self_alarm && empty( $critical_modified ) && empty( $regular_modified ) && empty( $last_results['suspicious'] ) && empty( $last_results['extra'] ) && ! $has_closed && ! $vg_scan_partial && empty( $vg_missing_core ) ) : ?>
7675 + <?php if ( $last_results && ! $vg_self_alarm && empty( $critical_modified ) && empty( $regular_modified ) && empty( $last_results['suspicious'] ) && empty( $last_results['extra'] ) && ! $has_closed ) : ?>
7859 7676 <p class="vigilante-all-clear" style="color: #00a32a; font-weight: bold;">
7860 - <?php esc_html_e( 'Good job! Nothing to report in the files that were checked.', 'vigilante' ); ?>
7677 + <?php esc_html_e( 'Good Job! All files passed integrity check. No issues found.', 'vigilante' ); ?>
7861 7678 </p>
7862 7679 <?php endif; ?>
7863 7680 <?php endif; ?>
7864 7681 </div>
@@ -7907,9 +7724,9 @@
7907 7724
7908 7725 <?php if ( ! empty( $ignored_files ) ) : ?>
7909 7726 <div id="vigilante-section-fi-ignored" class="vigilante-settings-section">
7910 7727 <h2><?php esc_html_e( 'Ignored Files', 'vigilante' ); ?></h2>
7911 - <p class="description"><?php esc_html_e( 'These files are excluded from scan results and email notifications. They will still be scanned but any findings will be hidden. To leave a whole folder out, add it to Excluded Paths instead.', 'vigilante' ); ?></p>
7728 + <p class="description"><?php esc_html_e( 'These files are excluded from scan results and email notifications. They will still be scanned but any findings will be hidden.', 'vigilante' ); ?></p>
7912 7729 <div class="vigilante-paginated-section" data-bulk-mode="unignore">
7913 7730 <div class="vigilante-fi-bulk-bar">
7914 7731 <button type="button" class="button vigilante-bulk-unignore" disabled><?php esc_html_e( 'Stop ignoring selected', 'vigilante' ); ?></button>
7915 7732 <span class="vigilante-fi-bulk-count" aria-live="polite"></span>
@@ -9142,12 +8959,8 @@
9142 8959 $scanned_at = get_option( 'vigilante_last_integrity_scan' );
9143 8960
9144 8961 delete_option( 'vigilante_last_integrity_results' );
9145 8962 delete_option( 'vigilante_last_integrity_scan' );
9146 -
9147 - // Starting over also means being told again: the next scan emails
9148 - // whatever it finds, as if nothing had been reported before.
9149 - delete_option( Vigilante_File_Integrity::NOTIFIED_OPTION );
9150 8963
9151 8964 /*
9152 8965 * A pending change to wp-config.php or the root .htaccess is closed by
9153 8966 * approving it, which takes the network. Clearing the results was one