REPORT / 01
Analysis Report · Folder Analysis cache/custom-fonts_2.1.16 → cache/custom-fonts_2.1.17 — CVE-2025-14351
Shared security patch analysis results
02 ·
Lifecycle actions
cancel · resume · skip · regenerate
03 ·
Share this analysis
copy link · embed report
03 ·
CVE Security Analysis & Writeups
ai-generated · per cve
Comprehensive security analysis generated by AI for each confirmed CVE match. Click on a CVE to view the detailed writeup including vulnerability background, technical details, patch analysis, and PoC guide.
CVE-2025-14351
NVD
AI-Generated Analysis
05 ·
Findings
filter · search · paginate
Showing 0 to 0 of 0 results
includes/class-bcf-google-fonts-compatibility.php
AI: 1 vulnerabilities
1 false positive
CVE-2025-14351
--- cache/custom-fonts_2.1.16/includes/class-bcf-google-fonts-compatibility.php 2026-01-20 00:19:27.877798697 +0000+++ cache/custom-fonts_2.1.17/includes/class-bcf-google-fonts-compatibility.php 2026-01-20 00:24:06.627041898 +0000@@ -86,10 +86,33 @@ * @since 2.0.0 */ public function __construct() {+ add_action( 'admin_init', array( $this, 'maybe_rebuild_fonts' ), 10 );+ }++ /**+ * Handle font rebuild operation with security checks.+ *+ * @return void+ * @since 2.1.17+ */+ public function maybe_rebuild_fonts() { if ( empty( $_GET['page'] ) || BSF_CUSTOM_FONTS_ADMIN_PAGE !== $_GET['page'] ) { //phpcs:ignore WordPress.Security.NonceVerification.Recommended return; } + if ( ! isset( $_GET['bcf_rebuild_fonts'] ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Recommended+ return;+ }++ // Security: Capability and nonce checks.+ if ( ! current_user_can( 'manage_options' ) ) {+ wp_die( esc_html__( 'You do not have permission to perform this action.', 'custom-fonts' ), 403 );+ }++ if ( ! isset( $_GET['bcf_nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET['bcf_nonce'] ) ), 'bcf_google_fonts_rebuild' ) ) {+ wp_die( esc_html__( 'Security check failed. Please try again.', 'custom-fonts' ), 403 );+ }+ $bcf_filesystem = bcf_filesystem(); $fonts_folder_path = $this->get_fonts_folder(); @@ -98,7 +121,18 @@ } self::delete_all_theme_font_family();- add_action( 'admin_init', array( $this, 'update_fse_theme_json' ) );+ $this->update_fse_theme_json();++ $redirect_url = add_query_arg(+ array(+ 'page' => BSF_CUSTOM_FONTS_ADMIN_PAGE,+ 'fonts_rebuilt' => '1',+ ),+ admin_url( 'themes.php' )+ );++ wp_safe_redirect( $redirect_url );+ exit; } /**
AI Analysis
## Security Analysis of Code Diff
**Vulnerability 1: Cross-Site Request Forgery (CSRF) - Incomplete Fix**
Vulnerability Existed: yes
FALSE POSITIVE
CWE-352 - Cross-Site Request Forgery (CSRF) - includes/class-bcf-google-fonts-compatibility.php - Lines 88-135
Old Code:
```php
public function __construct() {
if ( empty( $_GET['page'] ) || BSF_CUSTOM_FONTS_ADMIN_PAGE !== $_GET['page'] ) {
return;
}
$bcf_filesystem = bcf_filesystem();
$fonts_folder_path = $this->get_fonts_folder();
if ( file_exists( $fonts_folder_path ) ) {
$bcf_filesystem->delete( $fonts_folder_path, true, 'd' );
}
self::delete_all_theme_font_family();
add_action( 'admin_init', array( $this, 'update_fse_theme_json' ) );
}
```
Fixed Code:
```php
public function __construct() {
add_action( 'admin_init', array( $this, 'maybe_rebuild_fonts' ), 10 );
}
public function maybe_rebuild_fonts() {
if ( empty( $_GET['page'] ) || BSF_CUSTOM_FONTS_ADMIN_PAGE !== $_GET['page'] ) {
return;
}
if ( ! isset( $_GET['bcf_rebuild_fonts'] ) ) {
return;
}
// Security: Capability and nonce checks.
if ( ! current_user_can( 'manage_options' ) ) {
wp_die( esc_html__( 'You do not have permission to perform this action.', 'custom-fonts' ), 403 );
}
if ( ! isset( $_GET['bcf_nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET['bcf_nonce'] ) ), 'bcf_google_fonts_rebuild' ) ) {
wp_die( esc_html__( 'Security check failed. Please try again.', 'custom-fonts' ), 403 );
}
$bcf_filesystem = bcf_filesystem();
$fonts_folder_path = $this->get_fonts_folder();
if ( file_exists( $fonts_folder_path ) ) {
$bcf_filesystem->delete( $fonts_folder_path, true, 'd' );
}
self::delete_all_theme_font_family();
$this->update_fse_theme_json();
$redirect_url = add_query_arg(
array(
'page' => BSF_CUSTOM_FONTS_ADMIN_PAGE,
'fonts_rebuilt' => '1',
),
admin_url( 'themes.php' )
);
wp_safe_redirect( $redirect_url );
exit;
}
```
Explanation:
The old code was highly vulnerable to CSRF attacks. It executed destructive operations (deleting all fonts folders and theme font families) directly in the constructor without any authentication checks, nonce verification, or permission checks. The fix significantly improves security by:
1. Moving the logic to a dedicated `maybe_rebuild_fonts()` method hooked to `admin_init`
2. Adding a capability check (`current_user_can( 'manage_options' )`)
3. Adding proper nonce verification with `wp_verify_nonce()` and input sanitization
4. Requiring an explicit `bcf_rebuild_fonts` parameter to trigger the operation
5. Redirecting after successful completion using `wp_safe_redirect()`
However, the vulnerability is not completely eliminated because the nonce is still read from `$_GET` (which is visible in logs and history), and the implementation still relies on checking for the parameter's existence rather than requiring the rebuild to be initiated through a proper form POST request. A complete fix would use POST with a proper nonce form submission.
**Vulnerability 2: Potential Unchecked Capability in previous call**
Vulnerability Existed: not sure
CWE-639 - Authorization Through User-Controlled Key - includes/class-bcf-google-fonts-compatibility.php - Lines 88-102
Old Code:
```php
public function __construct() {
if ( empty( $_GET['page'] ) || BSF_CUSTOM_FONTS_ADMIN_PAGE !== $_GET['page'] ) {
return;
}
// No capability check before executing destructive operations
```
Fixed Code:
```python
public function maybe_rebuild_fonts() {
if ( empty( $_GET['page'] ) || BSF_CUSTOM_FONTS_ADMIN_PAGE !== $_GET['page'] ) {
return;
}
if ( ! isset( $_GET['bcf_rebuild_fonts'] ) ) {
return;
}
// Security: Capability and nonce checks.
if ( ! current_user_can( 'manage_options' ) ) {
wp_die( esc_html__( 'You do not have permission to perform this action.', 'custom-fonts' ), 403 );
}
```
Explanation:
The original code lacked explicit privilege escalation checks. While it may have relied on WordPress admin page access, without explicit `current_user_can()` checks, there was potential for authorization bypass. The fix adds explicit capability verification requiring `manage_options` capability, which properly enforces authorization before executing the destructive operations.
CVE Analysis Results:
CVE-2025-14351: Yes
View CVE Description
The Custom Fonts – Host Your Fonts Locally plugin for WordPress is vulnerable to unauthorized loss of data due to a missing capability check on the 'BCF_Google_Fonts_Compatibility' class constructor function in all versions up to, and including, 2.1.16. This makes it possible for unauthenticated attackers to delete font directory and rewrite theme.json file.
Showing 1 to 1 of 1 results