WordPress Security for Business Directory Websites
Directory websites allow user submissions which creates security risks. Learn how to protect your directory from spam, fake listings, and malicious content.
Business directories and listing websites face unique security challenges because they accept user-submitted content. This opens the door to spam, malicious content, and abuse. Proper security ensures your directory remains trustworthy and safe.
Directory Security Challenges
- User submissions - Uncontrolled content input
- Spam listings - Fake or promotional entries
- Malicious content - XSS, links to malware
- Duplicate listings - SEO manipulation
- Payment fraud - For paid listings
Secure Listing Submissions
Input Validation and Sanitization
// Comprehensive listing validation
function validate_directory_listing($data) {
$errors = new WP_Error();
// Required fields
$required = array('business_name', 'email', 'category');
foreach ($required as $field) {
if (empty($data[$field])) {
$errors->add($field . '_required', ucfirst($field) . ' is required.');
}
}
// Sanitize all fields
$clean = array(
'business_name' => sanitize_text_field($data['business_name']),
'description' => wp_kses_post($data['description']),
'email' => sanitize_email($data['email']),
'phone' => preg_replace('/[^0-9+-s]/', '', $data['phone']),
'website' => esc_url_raw($data['website']),
'address' => sanitize_textarea_field($data['address']),
'category' => absint($data['category'])
);
// Validate email format
if (!is_email($clean['email'])) {
$errors->add('invalid_email', 'Please provide a valid email address.');
}
// Validate URL if provided
if (!empty($clean['website']) && !filter_var($clean['website'], FILTER_VALIDATE_URL)) {
$errors->add('invalid_url', 'Please provide a valid website URL.');
}
// Check for spam patterns
$spam_check = check_for_spam_content($clean);
if ($spam_check) {
$errors->add('spam_detected', 'Submission rejected.');
}
if ($errors->has_errors()) {
return $errors;
}
return $clean;
}
// Check content for spam patterns
function check_for_spam_content($data) {
$spam_patterns = array(
'/(viagra|cialis|casino|poker|payday|loan)/i',
'/(http[s]?://){2,}/', // Multiple URLs
'/(.)1{10,}/', // Repeated characters
'/[А-Яа-яЁё]/', // Cyrillic (if not expected)
);
$text = implode(' ', $data);
foreach ($spam_patterns as $pattern) {
if (preg_match($pattern, $text)) {
return true;
}
}
return false;
}
Rate Limiting Submissions
// Prevent submission abuse
function rate_limit_submissions() {
$ip = wpfs_get_client_ip();
// Check IP-based limit
$ip_key = 'listing_submit_' . md5($ip);
$ip_count = get_transient($ip_key) ?: 0;
if ($ip_count >= 3) { // 3 submissions per hour
return new WP_Error('rate_limited',
'Too many submissions. Please try again later.');
}
set_transient($ip_key, $ip_count + 1, HOUR_IN_SECONDS);
// Check email-based limit
if (is_user_logged_in()) {
$user_key = 'listing_submit_user_' . get_current_user_id();
$user_count = get_transient($user_key) ?: 0;
if ($user_count >= 5) { // 5 per hour for logged in users
return new WP_Error('rate_limited',
'Submission limit reached. Please try again later.');
}
set_transient($user_key, $user_count + 1, HOUR_IN_SECONDS);
}
return true;
}
Moderation Queue
// All submissions require approval
function submit_listing_for_review($listing_data) {
// Create listing as pending
$listing_id = wp_insert_post(array(
'post_title' => $listing_data['business_name'],
'post_content' => $listing_data['description'],
'post_type' => 'directory_listing',
'post_status' => 'pending' // Always pending for review
));
// Store metadata
foreach ($listing_data as $key => $value) {
update_post_meta($listing_id, '_listing_' . $key, $value);
}
// Flag for spam check
$spam_score = calculate_spam_score($listing_data);
update_post_meta($listing_id, '_spam_score', $spam_score);
if ($spam_score > 70) {
update_post_meta($listing_id, '_flagged_for_spam', true);
}
// Notify moderators
notify_moderators_new_listing($listing_id);
return $listing_id;
}
// Spam score calculation
function calculate_spam_score($data) {
$score = 0;
// All caps title
if ($data['business_name'] === strtoupper($data['business_name'])) {
$score += 20;
}
// Excessive URLs in description
$url_count = preg_match_all('/https?:///', $data['description']);
$score += min($url_count * 10, 30);
// Phone numbers in description
if (preg_match('/d{3}[-.s]?d{3}[-.s]?d{4}/', $data['description'])) {
$score += 10;
}
// Disposable email domain
if (is_disposable_email($data['email'])) {
$score += 40;
}
return $score;
}
Image Upload Security
// Secure listing image uploads
function secure_listing_image_upload($file) {
// Allowed types
$allowed = array('image/jpeg', 'image/png', 'image/webp');
if (!in_array($file['type'], $allowed)) {
$file['error'] = 'Only JPEG, PNG, and WebP images are allowed.';
return $file;
}
// Max file size (2MB)
if ($file['size'] > 2 * 1024 * 1024) {
$file['error'] = 'Image must be smaller than 2MB.';
return $file;
}
// Verify it's actually an image
$image_info = getimagesize($file['tmp_name']);
if ($image_info === false) {
$file['error'] = 'Invalid image file.';
return $file;
}
// Strip EXIF data for privacy
$file = strip_exif_data($file);
return $file;
}
add_filter('wp_handle_upload_prefilter', 'secure_listing_image_upload');
Claim/Verification System
// Business claim verification
function process_business_claim($listing_id, $claimant_data) {
// Generate verification code
$verification_code = wp_generate_password(20, false);
// Store claim request
$claim = array(
'listing_id' => $listing_id,
'claimant_email' => sanitize_email($claimant_data['email']),
'claimant_name' => sanitize_text_field($claimant_data['name']),
'verification_code' => wp_hash($verification_code),
'status' => 'pending',
'submitted_at' => current_time('mysql')
);
global $wpdb;
$wpdb->insert($wpdb->prefix . 'listing_claims', $claim);
// Send verification email
wp_mail(
$claimant_data['email'],
'Verify Your Business Claim',
'Your verification code: ' . $verification_code
);
return true;
}
Conclusion
Directory websites require robust input validation, moderation systems, and spam prevention. Always sanitize user input, require approval for submissions, and implement comprehensive spam detection.
Written by Sarah Chen
WP Folder Shield Team