Skip to content

Commit 464d4d7

Browse files
authored
updates
1 parent 4829b37 commit 464d4d7

File tree

2 files changed

+93
-60
lines changed

2 files changed

+93
-60
lines changed

readme.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -99,10 +99,10 @@ No, the plugin has a simple interface where you can toggle features on and off.
9999
== Upgrade Notice ==
100100

101101
= 1.5.7 =
102-
SECURITY UPDATE: This version adds important security enhancements including CSRF protection and enhanced DNS prefetch security. Update recommended for all users.
102+
SECURITY UPDATE: Important security enhancements including CSRF protection and DNS prefetch security. Update recommended.
103103

104104
= 1.5.6 =
105-
Major security and code quality improvements with PHPStan analysis and WordPress best practices compliance.
105+
Major security and code quality improvements with PHPStan analysis and WordPress compliance.
106106

107107
= 1.5.4 =
108108
* Security enhancements and code optimization
@@ -124,7 +124,7 @@ Major security enhancement update with comprehensive OWASP-compliant security im
124124
This update includes significant code quality improvements with comprehensive static analysis fixes and enhanced security scanning. The plugin now passes PHPStan level 5 analysis with zero errors and includes improved WordPress API compliance. Enhanced development workflow with proper WordPress stubs and more reliable testing.
125125

126126
= 1.5.5 =
127-
This update adds compatibility with WordPress 6.8 and fixes text domain issues for better internationalization. The plugin now fully complies with WordPress.org plugin directory standards and passes all WordPress Plugin Check tests.
127+
WordPress 6.8 compatibility and internationalization fixes. Passes all Plugin Check tests.
128128

129129
= 1.5.4 =
130130
This update includes security enhancements and code optimization.

simple-wp-optimizer.php

Lines changed: 90 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -371,9 +371,10 @@ function es_optimizer_render_textarea_option($options, $optionName, $title, $des
371371
*/
372372
function es_optimizer_validate_options($input) {
373373
// Security: Verify nonce for CSRF protection
374-
if (!isset($_POST['es_optimizer_settings_nonce']) ||
375-
!wp_verify_nonce($_POST['es_optimizer_settings_nonce'], 'es_optimizer_settings_action')) {
376-
374+
// WordPress requires unslashing $_POST data before sanitization
375+
$nonce_value = isset($_POST['es_optimizer_settings_nonce']) ? wp_unslash($_POST['es_optimizer_settings_nonce']) : '';
376+
377+
if (empty($nonce_value) || !wp_verify_nonce($nonce_value, 'es_optimizer_settings_action')) {
377378
// Add admin notice for failed nonce verification
378379
add_settings_error(
379380
'es_optimizer_options',
@@ -401,67 +402,99 @@ function es_optimizer_validate_options($input) {
401402

402403
// Validate and sanitize the DNS prefetch domains with enhanced security
403404
if (isset($input['dns_prefetch_domains'])) {
404-
$domains = explode("\n", trim($input['dns_prefetch_domains']));
405-
$sanitizedDomains = array();
406-
$rejectedDomains = array();
405+
$valid['dns_prefetch_domains'] = es_optimizer_validate_dns_domains($input['dns_prefetch_domains']);
406+
}
407+
408+
return $valid;
409+
}
410+
411+
/**
412+
* Validate DNS prefetch domains with enhanced security
413+
*
414+
* @param string $domains_input Raw domain input from user
415+
* @return string Validated and sanitized domains
416+
*/
417+
function es_optimizer_validate_dns_domains($domains_input) {
418+
$domains = explode("\n", trim($domains_input));
419+
$sanitized_domains = array();
420+
$rejected_domains = array();
421+
422+
foreach ($domains as $domain) {
423+
$domain = trim($domain);
424+
if (empty($domain)) {
425+
continue;
426+
}
407427

408-
foreach ($domains as $domain) {
409-
$domain = trim($domain);
410-
if (!empty($domain)) {
411-
// Enhanced URL validation with security checks
412-
if (filter_var($domain, FILTER_VALIDATE_URL)) {
413-
$parsedUrl = parse_url($domain);
414-
415-
// Security: Enforce HTTPS-only domains for DNS prefetch
416-
if (isset($parsedUrl['scheme']) && $parsedUrl['scheme'] === 'https') {
417-
// Additional security checks
418-
if (isset($parsedUrl['host'])) {
419-
$host = $parsedUrl['host'];
420-
421-
// Prevent localhost and private IP ranges for security
422-
if (!in_array($host, array('localhost', '127.0.0.1', '::1')) &&
423-
!filter_var($host, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
424-
425-
// Security: Use esc_url_raw to sanitize URLs before storing in database
426-
// This prevents potential security issues with malformed URLs
427-
$sanitizedDomains[] = esc_url_raw($domain);
428-
} else {
429-
$rejectedDomains[] = $domain . ' (private/local address not allowed)';
430-
}
431-
}
432-
} else {
433-
$rejectedDomains[] = $domain . ' (HTTPS required for security)';
434-
}
435-
} else {
436-
$rejectedDomains[] = $domain . ' (invalid URL format)';
437-
}
438-
}
428+
// Enhanced URL validation with security checks
429+
if (!filter_var($domain, FILTER_VALIDATE_URL)) {
430+
$rejected_domains[] = $domain . ' (invalid URL format)';
431+
continue;
439432
}
440433

441-
// Show admin notice if any domains were rejected for security reasons
442-
if (!empty($rejectedDomains)) {
443-
// Security: Properly escape and limit the rejected domains in error messages
444-
$escapedRejectedDomains = array_map('esc_html', array_slice($rejectedDomains, 0, 3));
445-
$rejectedMessage = implode(', ', $escapedRejectedDomains);
446-
if (count($rejectedDomains) > 3) {
447-
$rejectedMessage .= esc_html__('...', 'Simple-WP-Optimizer');
448-
}
449-
450-
add_settings_error(
451-
'es_optimizer_options',
452-
'dns_prefetch_security',
453-
sprintf(
454-
esc_html__('Some DNS prefetch domains were rejected for security reasons: %s', 'Simple-WP-Optimizer'),
455-
$rejectedMessage
456-
),
457-
'warning'
458-
);
434+
// Use wp_parse_url instead of parse_url for WordPress compatibility
435+
$parsed_url = wp_parse_url($domain);
436+
437+
// Security: Enforce HTTPS-only domains for DNS prefetch
438+
if (!isset($parsed_url['scheme']) || $parsed_url['scheme'] !== 'https') {
439+
$rejected_domains[] = $domain . ' (HTTPS required for security)';
440+
continue;
441+
}
442+
443+
// Additional security checks
444+
if (!isset($parsed_url['host'])) {
445+
$rejected_domains[] = $domain . ' (no host found)';
446+
continue;
459447
}
460448

461-
$valid['dns_prefetch_domains'] = implode("\n", $sanitizedDomains);
449+
$host = $parsed_url['host'];
450+
451+
// Prevent localhost and private IP ranges for security
452+
$is_local = in_array($host, array('localhost', '127.0.0.1', '::1'));
453+
$is_private_ip = filter_var($host, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) !== false;
454+
455+
if ($is_local || !$is_private_ip) {
456+
$rejected_domains[] = $domain . ' (private/local address not allowed)';
457+
continue;
458+
}
459+
460+
// Security: Use esc_url_raw to sanitize URLs before storing in database
461+
$sanitized_domains[] = esc_url_raw($domain);
462462
}
463463

464-
return $valid;
464+
// Show admin notice if any domains were rejected for security reasons
465+
if (!empty($rejected_domains)) {
466+
es_optimizer_show_domain_rejection_notice($rejected_domains);
467+
}
468+
469+
return implode("\n", $sanitized_domains);
470+
}
471+
472+
/**
473+
* Show admin notice for rejected domains
474+
*
475+
* @param array $rejected_domains Array of rejected domain strings
476+
*/
477+
function es_optimizer_show_domain_rejection_notice($rejected_domains) {
478+
// Security: Properly escape and limit the rejected domains in error messages
479+
$escaped_domains = array_map('esc_html', array_slice($rejected_domains, 0, 3));
480+
$rejected_message = implode(', ', $escaped_domains);
481+
482+
if (count($rejected_domains) > 3) {
483+
$rejected_message .= esc_html__('...', 'Simple-WP-Optimizer');
484+
}
485+
486+
// translators: %s is the list of rejected domain names
487+
$message = sprintf(
488+
esc_html__('Some DNS prefetch domains were rejected for security reasons: %s', 'Simple-WP-Optimizer'),
489+
$rejected_message
490+
);
491+
492+
add_settings_error(
493+
'es_optimizer_options',
494+
'dns_prefetch_security',
495+
$message,
496+
'warning'
497+
);
465498
}
466499

467500
/**

0 commit comments

Comments
 (0)