security: apply 11 audit findings (2 critical, 4 high, 5 medium/low)
SEC-001 CRITICAL: Remove spoofable X-Forwarded-For/X-Real-IP from IP detection; trust only CF-Connecting-IP + REMOTE_ADDR SEC-004 HIGH: Add peptide name input validation with character whitelist and prompt injection blocking SEC-006 HIGH: Add missing return after wp_send_json_success in handle_pending_retry max-retries block SEC-007 MEDIUM: KB articles now respect auto_publish setting instead of always publishing SEC-009 MEDIUM: Replace hardcoded page ID 73 with configurable kb_page_id setting SEC-010 MEDIUM: Fix cache invalidation — add underscore prefix to transient name pattern SEC-011 MEDIUM: Skip sleep() during WP-Cron to avoid blocking PHP workers on rate limit retry SEC-012 MEDIUM: Add global daily generation cap (50/day) to prevent cost overruns SEC-013 LOW: Add @deprecated notice to unused PSA_Error class SEC-015 LOW: Convert uninstall.php from space to tab indentation (WPCS) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -39,8 +39,8 @@ class PSA_Search {
|
||||
// phpcs:ignore WordPress.DB.DirectDatabaseQuery
|
||||
$wpdb->query(
|
||||
"DELETE FROM {$wpdb->options}
|
||||
WHERE option_name LIKE 'transient_psa_search_%'
|
||||
OR option_name LIKE 'transient_timeout_psa_search_%'"
|
||||
WHERE option_name LIKE '_transient_psa_search_%'
|
||||
OR option_name LIKE '_transient_timeout_psa_search_%'"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -236,6 +236,7 @@ class PSA_Search {
|
||||
'message' => 'We were unable to generate content for this peptide. Please try again later.',
|
||||
)
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Retry generation.
|
||||
@@ -273,6 +274,19 @@ class PSA_Search {
|
||||
* @return void Exits with wp_send_json_* responses.
|
||||
*/
|
||||
private static function handle_new_generation( $query ) {
|
||||
// Global daily generation cap to prevent cost overruns.
|
||||
$daily_key = 'psa_daily_gen_' . gmdate( 'Y-m-d' );
|
||||
$daily_count = (int) get_transient( $daily_key );
|
||||
if ( $daily_count >= PSA_Config::DAILY_GENERATION_CAP ) {
|
||||
wp_send_json_success(
|
||||
array(
|
||||
'status' => 'rate_limited',
|
||||
'message' => 'Our system has reached its daily limit for adding new peptides. Please try again tomorrow.',
|
||||
)
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Validate peptide name via AI.
|
||||
$validation = PSA_AI_Generator::validate_peptide_name( $query );
|
||||
|
||||
@@ -308,6 +322,11 @@ class PSA_Search {
|
||||
wp_send_json_error( 'Failed to create peptide entry. Please try again.' );
|
||||
}
|
||||
|
||||
// Increment global daily generation counter.
|
||||
$daily_key = 'psa_daily_gen_' . gmdate( 'Y-m-d' );
|
||||
$daily_count = (int) get_transient( $daily_key );
|
||||
set_transient( $daily_key, $daily_count + 1, DAY_IN_SECONDS );
|
||||
|
||||
// Schedule async background generation.
|
||||
error_log( 'PSA: Scheduling async generation for "' . $canonical_name . '" (post ' . $placeholder_id . ')' );
|
||||
self::schedule_background_generation( $placeholder_id, $canonical_name );
|
||||
|
||||
Reference in New Issue
Block a user