Skip to content

Security: daimpad/OpenDataWizard

SECURITY.md

Security Policy — Open Data Wizard

🔐 Security Audit Report

Audit Date: June 27, 2026
Status: ✅ SECURE
Scope: Full codebase review (PHP, JavaScript, REST API) — incl. v2.1.5 hardening pass


Executive Summary

The Open Data Wizard WordPress plugin follows WordPress security best practices consistently. No critical vulnerabilities detected. The codebase demonstrates proper:

  • Input sanitization and validation
  • Output escaping
  • Capability and nonce verification
  • Secure file handling
  • Query parameter protection

Test Coverage: 92 PHPUnit tests (all passing)
Code Standards: PHPCS compliant
Static Analysis: PHPStan Level 6 passing


✅ Security Strengths

Input Sanitization & Validation

  • All REST API parameters properly sanitized (sanitize_text_field(), absint())
  • URL validation with scheme whitelist — blocks javascript:, data:, and other dangerous protocols
  • Carbon Fields integration doesn't bypass sanitization
  • JSON input properly decoded and validated before use

Output Escaping

  • All user-facing content properly escaped (esc_html(), esc_attr(), esc_url_raw())
  • Admin notices securely rendered
  • JSON-LD output sanitized before REST API response
  • No unescaped dynamic content in HTML

Capability & Permission Checks

  • File upload operations verify current_user_can('edit_post', $post_id)
  • Settings page restricted to manage_options capability
  • Custom capability manage_open_data for dataset operations
  • Automatic removal of capabilities on plugin deinstallation

Nonce Verification

  • File upload handler: wp_verify_nonce() on all POST operations (line 432-437, class-admin.php)
  • Settings updates: WordPress Settings API nonce protection
  • Recalculate quality action: Protected with admin nonce (line 108, class-settings.php)

REST API Security

  • Pagination limits enforced (max 100 items per page)
  • ISO 8601 datetime validation for delta endpoint
  • Query parameters validated before WP_Query construction
  • Public endpoints only expose published datasets
  • No information disclosure for draft/private content

Publishing Validation

  • Validation blocks publish until all required fields present
  • Prevents incomplete datasets from being public
  • Validation errors stored safely in transients (300s TTL)
  • Users cannot bypass validation

File Handling

  • WordPress Media Library integration (wp.media) for uploads
  • File paths validated with get_attached_file() and file_exists()
  • File size calculated server-side (not from user input)
  • No arbitrary file access

⚠️ Recommendations (Low Priority)

1. Transient Cache Invalidation

Location: includes/class-rest-api.php lines 50-51
Current: Cache invalidates on save_post_odw_dataset and trashed_post
Recommendation: Also invalidate on delete_post for completeness

// Add: allow deleted datasets to clear cache immediately
add_action( 'delete_post_odw_dataset', array( self::class, 'invalidate_cache' ) );

2. Database Query Optimization

Location: config/phpcs.xml lines 18-21
Current: Meta key queries intentionally excluded from slowness warnings
Recommendation: For datasets >10K posts, consider adding database indexes on _odw_* meta keys

-- Optional optimization for large installations
ALTER TABLE wp_postmeta ADD INDEX ( `meta_key` );
ALTER TABLE wp_postmeta ADD INDEX ( `post_id`, `meta_key` );

3. Rate Limiting (Optional)

For high-traffic REST API usage:

  • Consider implementing rate limiting on /catalog and /delta endpoints
  • Current transient caching (5 min TTL) already provides good DDoS protection
  • Not necessary for typical usage

Reporting Security Vulnerabilities

If you discover a security vulnerability, please do NOT open a public GitHub issue.

Instead:

  1. Email: security@example.com (or use GitHub Security Advisory feature)

  2. Include:

    • Detailed description of the vulnerability
    • Steps to reproduce
    • Potential impact
    • Your name and contact information (optional)
  3. Response Time: We'll acknowledge receipt within 48 hours and work on a fix


Security Standards & Compliance

WordPress Security Practices

  • ✅ Follows WordPress Plugin Handbook Security Guidelines
  • ✅ Uses WordPress APIs (not raw PHP functions for security operations)
  • ✅ Proper use of nonces, capabilities, and sanitization functions
  • ✅ No use of deprecated security functions

OWASP Top 10 Protection

Vulnerability Status Notes
SQL Injection ✅ Safe Uses WP_Query, properly parameterized
Broken Authentication ✅ Safe WordPress native auth, capability checks
Sensitive Data Exposure ✅ Safe No sensitive data in responses, HTTPS recommended
XML External Entities (XXE) ✅ Safe No XML parsing
Broken Access Control ✅ Safe Proper capability and nonce verification
Security Misconfiguration ✅ Safe Follows WordPress standards
XSS ✅ Safe All output properly escaped
Insecure Deserialization ✅ Safe serialize() only used for cache keys (non-user data)
Using Components with Known Vulns ✅ Monitor Composer dependencies regularly updated
Insufficient Logging & Monitoring ✅ Safe Uses WordPress native logging

PHP Version Support

  • Minimum: PHP 8.1+
  • Tested: PHP 8.1, 8.2, 8.3 (via GitHub Actions CI)
  • Type Safety: Strict types enabled (declare(strict_types=1))
  • Type Hints: All public methods have return types

Dependency Security

All dependencies managed via Composer:

# Check for known vulnerabilities
composer audit

Version History

Version Audit Date Status Notes
2.1.5 June 27, 2026 ✅ Secure Hardening pass: batch-import XSS fix, CSV/formula-injection neutralization, JSON-LD @id URL sanitization, upload validation by real extension, 2000-record import cap
2.1.4 May 27, 2026 ✅ Secure Full security audit completed

Questions?

  • Security Issues: See "Reporting Security Vulnerabilities" above
  • General Questions: Open a GitHub Discussion
  • Code Review: See CLAUDE.md for architecture and development guidelines

Last Updated: June 27, 2026
Maintained By: Open Data Wizard Team
License: GPL-2.0-or-later

There aren't any published security advisories