Skip to content

Security: daimpad/OpenDataWizard

SECURITY.md

Security Policy β€” Open Data Wizard

πŸ” Security Audit Report

Audit Date: May 27, 2026
Status: βœ… SECURE
Scope: Full codebase review (PHP, JavaScript, REST API)


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: 90 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.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: May 27, 2026
Maintained By: Open Data Wizard Team
License: GPL-2.0-or-later

There aren't any published security advisories