[
  {
    "id": "VULN-AUTH-01",
    "name": "Authentication Bypass (is_admin Fallacy)",
    "section": "3.1",
    "severity": "Critical",
    "description": "Relying solely on is_admin() for authorization checks on sensitive actions.",
    "detection_logic": {
      "pattern": "Logic gate uses is_admin() as the ONLY check before sensitive actions (DB writes, file mods).",
      "false_positive_check": "Ignore if current_user_can() is present in the same block."
    },
    "remediation": "Replace or augment is_admin() with current_user_can('capability').",
    "status": "complete",
    "findings": []
  },
  {
    "id": "VULN-AUTH-02",
    "name": "Privilege Escalation (Missing Capabilities)",
    "section": "3.2",
    "severity": "Critical",
    "description": "AJAX hooks (wp_ajax_*) that execute logic without checking user capabilities.",
    "detection_logic": {
      "context": ["add_action('wp_ajax_...)", "add_action('admin_post_...)"],
      "pattern": "Function body lacks a call to current_user_can()."
    },
    "remediation": "Add current_user_can('manage_options') (or appropriate cap) at start of function.",
    "status": "complete",
    "findings": []
  },
  {
    "id": "VULN-AUTH-03",
    "name": "Insecure AJAX Registration (nopriv)",
    "section": "3.2",
    "severity": "High",
    "description": "Sensitive actions registered to wp_ajax_nopriv_ (unauthenticated users).",
    "detection_logic": {
      "pattern": "add_action('wp_ajax_nopriv_...)"
    },
    "remediation": "Remove nopriv hook if the action requires authentication. If public, ensure strict validation.",
    "status": "complete",
    "findings": [
      {
        "file": "includes/Comments/Actions.php",
        "line": 28,
        "snippet": "add_action('wp_ajax_nopriv_presszone_comments_submit', [$this, 'handle_comment_submit']);",
        "context": "Allows unauthenticated comment submission (by design, follows WP comment_registration option)",
        "risk": "Low - WordPress core comment system already handles unauthenticated comments"
      },
      {
        "file": "includes/Comments/Actions.php",
        "line": 32,
        "snippet": "add_action('wp_ajax_nopriv_presszone_comments_report', [$this, 'handle_report_submit']);",
        "context": "Allows anonymous reporting with rate limiting",
        "risk": "Low - Rate limited and sanitized"
      }
    ]
  },
  {
    "id": "VULN-CSRF-01",
    "name": "Missing CSRF Protection (Nonce Verification)",
    "section": "3.3",
    "severity": "High",
    "description": "Processing form data or AJAX requests without verifying a nonce.",
    "detection_logic": {
      "context": ["$_POST processing", "wp_ajax_ hooks"],
      "pattern": "Missing wp_verify_nonce(), check_admin_referer(), or check_ajax_referer()."
    },
    "remediation": "Add wp_verify_nonce( $_REQUEST['_wpnonce'], 'action_name' ).",
    "status": "complete",
    "findings": []
  },
  {
    "id": "VULN-CSRF-02",
    "name": "Weak Nonce (Replay Attack)",
    "section": "3.3",
    "severity": "Medium",
    "description": "Using a generic or static string for nonce action, allowing replay attacks.",
    "detection_logic": {
      "pattern": "wp_verify_nonce($n, 'generic_string') or wp_create_nonce('generic_string')."
    },
    "remediation": "Use specific action strings like 'delete_post_' . $post_id.",
    "status": "complete",
    "findings": []
  },
  {
    "id": "VULN-REST-01",
    "name": "Open REST API Endpoint",
    "section": "3.4",
    "severity": "Critical",
    "description": "REST routes registered without a permission callback or with __return_true.",
    "detection_logic": {
      "context": ["register_rest_route"],
      "pattern": "permission_callback is missing OR set to '__return_true'."
    },
    "remediation": "Define a custom permission_callback that checks current_user_can().",
    "status": "complete",
    "findings": []
  },
  {
    "id": "VULN-IDOR-01",
    "name": "Insecure Direct Object Reference (IDOR)",
    "section": "3.5",
    "severity": "High",
    "description": "Using user-supplied IDs (post_id, user_id) to modify data without ownership checks.",
    "detection_logic": {
      "sources": ["$_GET['id']", "$_POST['id']"],
      "sinks": ["update_user_meta", "wp_update_post", "wp_delete_post"],
      "pattern": "No check comparing input ID to get_current_user_id()."
    },
    "remediation": "Verify ownership: if ($id == get_current_user_id()) or check 'edit_others' cap.",
    "status": "complete",
    "findings": []
  },
  {
    "id": "VULN-VAL-01",
    "name": "Missing Data Validation",
    "section": "4.1",
    "severity": "Low",
    "description": "Using raw input without validating its type (email, int).",
    "detection_logic": {
      "pattern": "Usage of $_POST['email'] without is_email(), or ID without is_numeric()/absint()."
    },
    "remediation": "Wrap input in is_email(), is_int(), etc. before processing.",
    "status": "complete",
    "findings": []
  },
  {
    "id": "VULN-VAL-02",
    "name": "Incorrect validate_file Usage",
    "section": "4.1",
    "severity": "Medium",
    "description": "Misinterpreting validate_file() return value (0 means success/safe).",
    "detection_logic": {
      "pattern": "if ( validate_file($path) ) { // treat as success }"
    },
    "remediation": "Correct logic: if ( validate_file($path) !== 0 ) { // error }.",
    "status": "complete",
    "findings": []
  },
  {
    "id": "VULN-SAN-01",
    "name": "Missing Sanitization",
    "section": "4.2",
    "severity": "Medium",
    "description": "Saving data to DB without sanitization functions.",
    "detection_logic": {
      "sinks": ["update_option", "update_post_meta"],
      "pattern": "Raw input passed to storage functions without sanitize_text_field, sanitize_key, etc."
    },
    "remediation": "Apply sanitize_text_field(), sanitize_textarea_field(), etc.",
    "status": "complete",
    "findings": []
  },
  {
    "id": "VULN-XSS-01",
    "name": "Reflected XSS (Output Escaping)",
    "section": "4.3",
    "severity": "High",
    "description": "Outputting user input without escaping.",
    "detection_logic": {
      "sinks": ["echo", "print", "printf"],
      "pattern": "Variable from Source reaches Sink without esc_html, esc_attr, esc_url."
    },
    "remediation": "Use esc_html(), esc_attr(), esc_url() at the point of output.",
    "status": "complete",
    "findings": []
  },
  {
    "id": "VULN-XSS-02",
    "name": "Stored XSS",
    "section": "4.3",
    "severity": "High",
    "description": "Outputting database content without escaping.",
    "detection_logic": {
      "sources": ["get_option", "get_post_meta"],
      "sinks": ["echo", "print"],
      "pattern": "DB data output without late escaping."
    },
    "remediation": "Always escape on output, even if sanitized on save.",
    "status": "complete",
    "findings": []
  },
  {
    "id": "VULN-XSS-03",
    "name": "DOM-Based XSS",
    "section": "8.1",
    "severity": "High",
    "description": "Unsafe JavaScript DOM manipulation using user input.",
    "detection_logic": {
      "file_types": [".js"],
      "sources": ["location.hash", "location.search"],
      "sinks": ["innerHTML", "document.write"],
      "pattern": "Assigning location sources directly to innerHTML."
    },
    "remediation": "Use textContent instead of innerHTML, or sanitize using DOMPurify.",
    "status": "complete",
    "findings": []
  },
  {
    "id": "VULN-XSS-04",
    "name": "Unsafe Termination Output",
    "section": "2.3",
    "severity": "Medium",
    "description": "Using die() or exit() to output unsanitized variables.",
    "detection_logic": {
      "sinks": ["die", "exit"],
      "pattern": "die($variable) where variable is unsanitized input."
    },
    "remediation": "Use die(esc_html($variable)).",
    "status": "complete",
    "findings": []
  },
  {
    "id": "VULN-I18N-01",
    "name": "Translation XSS",
    "section": "4.3",
    "severity": "Medium",
    "description": "Using _e() for strings containing variable data instead of escaping functions.",
    "detection_logic": {
      "sinks": ["_e", "__"],
      "pattern": "Using _e($var) or _e('text' . $var) instead of esc_html_e()."
    },
    "remediation": "Use esc_html_e(), esc_attr_e(), or wp_kses() on the translated string.",
    "status": "complete",
    "findings": []
  },
  {
    "id": "VULN-SQL-01",
    "name": "SQL Injection (Raw Query)",
    "section": "5.1",
    "severity": "Critical",
    "description": "Direct concatenation of variables into SQL queries.",
    "detection_logic": {
      "sinks": ["$wpdb->query", "$wpdb->get_results"],
      "pattern": "Query string contains '.' concatenation or variable interpolation ($var)."
    },
    "remediation": "Use $wpdb->prepare() with placeholders (%s, %d).",
    "status": "complete",
    "findings": []
  },
  {
    "id": "VULN-SQL-02",
    "name": "SQL Injection (Improper Prepare)",
    "section": "5.1",
    "severity": "High",
    "description": "Passing a variable as the first argument to prepare().",
    "detection_logic": {
      "sinks": ["$wpdb->prepare"],
      "pattern": "First argument is a variable ($sql) instead of a string literal."
    },
    "remediation": "Ensure first argument is a string literal: $wpdb->prepare(\"SELECT... %s\", $var).",
    "status": "complete",
    "findings": []
  },
  {
    "id": "VULN-SQL-03",
    "name": "SQL Injection (ORDER BY)",
    "section": "5.2",
    "severity": "High",
    "description": "Dynamic ORDER BY clause without whitelisting.",
    "detection_logic": {
      "pattern": "ORDER BY $variable (prepare() %s quotes this, breaking SQL, so devs often remove prepare)."
    },
    "remediation": "Use a strict whitelist array of allowed columns.",
    "status": "complete",
    "findings": [
      {
        "file": "includes/Comments/Query.php",
        "line": 43,
        "snippet": "$allowed_orders = ['newest', 'oldest'];\nif (!in_array($display_order, $allowed_orders, true)) {\n    $display_order = 'newest'; // Safe default fallback\n}",
        "context": "ORDER BY validation with whitelist - SECURE IMPLEMENTATION",
        "risk": "None - properly implemented"
      }
    ]
  },
  {
    "id": "VULN-SQL-04",
    "name": "SQL Injection (LIKE Wildcards)",
    "section": "5.2",
    "severity": "Low",
    "description": "Unescaped wildcards (%) in LIKE clauses causing DoS.",
    "detection_logic": {
      "pattern": "LIKE %s used in prepare without pre-processing input."
    },
    "remediation": "Use $wpdb->esc_like() on the input variable.",
    "status": "complete",
    "findings": []
  },
  {
    "id": "VULN-SQL-05",
    "name": "SQL Injection (IN Clause)",
    "section": "5.2",
    "severity": "High",
    "description": "Using variables directly in IN (...) clauses.",
    "detection_logic": {
      "pattern": "IN ($ids) where $ids is not prepared."
    },
    "remediation": "Use implode(',', array_map('intval', $ids)) or similar strict formatting.",
    "status": "complete",
    "findings": []
  },
  {
    "id": "VULN-SQL-06",
    "name": "Insecure DB Configuration",
    "section": "5.3",
    "severity": "Medium",
    "description": "Changing DB charset or SQL modes.",
    "detection_logic": {
      "pattern": "Altering DB_CHARSET or disabling STRICT_TRANS_TABLES."
    },
    "remediation": "Do not alter global database configurations.",
    "status": "complete",
    "findings": []
  },
  {
    "id": "VULN-POI-01",
    "name": "PHP Object Injection",
    "section": "6.1",
    "severity": "Critical",
    "description": "Deserializing untrusted data.",
    "detection_logic": {
      "sinks": ["unserialize"],
      "pattern": "Any usage of unserialize() on variables."
    },
    "remediation": "Use json_decode() or allowed_classes option in PHP 7+.",
    "status": "complete",
    "findings": []
  },
  {
    "id": "VULN-PHAR-01",
    "name": "Phar Deserialization",
    "section": "6.2",
    "severity": "Critical",
    "description": "File operations on user-controlled paths triggering Phar deserialization.",
    "detection_logic": {
      "sinks": ["file_exists", "fopen", "file_get_contents", "is_dir", "unlink"],
      "pattern": "Path argument is user-controlled (could be 'phar://...')."
    },
    "remediation": "Validate path to ensure it does not start with phar:// or use strict whitelisting.",
    "status": "complete",
    "findings": []
  },
  {
    "id": "VULN-TYPE-01",
    "name": "PHP Type Juggling (Auth Bypass)",
    "section": "6.3",
    "severity": "High",
    "description": "Loose comparison (==) on sensitive hashes or tokens.",
    "detection_logic": {
      "pattern": "Comparison of sensitive vars (token, hash, password) using == or !=."
    },
    "remediation": "Use strict comparison (===) or hash_equals().",
    "status": "complete",
    "findings": []
  },
  {
    "id": "VULN-FILE-01",
    "name": "Unrestricted File Upload",
    "section": "7.1",
    "severity": "Critical",
    "description": "Using raw move_uploaded_file instead of WP handlers.",
    "detection_logic": {
      "sinks": ["move_uploaded_file"],
      "pattern": "Usage of raw PHP upload function."
    },
    "remediation": "Use wp_handle_upload() or wp_handle_sideload().",
    "status": "complete",
    "findings": []
  },
  {
    "id": "VULN-FILE-02",
    "name": "Weak MIME Validation",
    "section": "7.1",
    "severity": "High",
    "description": "Allowing arbitrary file types in upload handlers.",
    "detection_logic": {
      "context": ["wp_handle_upload"],
      "pattern": "'mimes' parameter is missing or set to allow all."
    },
    "remediation": "Strictly define allowed MIME types in the 'mimes' array.",
    "status": "complete",
    "findings": []
  },
  {
    "id": "VULN-FILE-03",
    "name": "Arbitrary File Write",
    "section": "2.3",
    "severity": "Critical",
    "description": "Writing to file system with user-controlled path/content.",
    "detection_logic": {
      "sinks": ["file_put_contents", "fwrite"],
      "pattern": "Path or Content derived from user input."
    },
    "remediation": "Use WP_Filesystem API and validate paths strictly.",
    "status": "complete",
    "findings": [
      {
        "file": "includes/Design/CSS_Generator.php",
        "line": 117,
        "snippet": "return $wp_filesystem->put_contents($css_file, $css, FS_CHMOD_FILE);",
        "context": "CSS file write using WP_Filesystem API with hardcoded path",
        "risk": "None - uses WP_Filesystem, directory is hardcoded, content is generated internally"
      }
    ]
  },
  {
    "id": "VULN-FILE-04",
    "name": "Arbitrary File Deletion",
    "section": "2.3",
    "severity": "Critical",
    "description": "Deleting files based on user input.",
    "detection_logic": {
      "sinks": ["unlink"],
      "pattern": "Path argument is user-controlled."
    },
    "remediation": "Strictly whitelist allowed paths for deletion.",
    "status": "complete",
    "findings": []
  },
  {
    "id": "VULN-LFI-01",
    "name": "Local File Inclusion (LFI)",
    "section": "7.2",
    "severity": "Critical",
    "description": "Including files based on user input.",
    "detection_logic": {
      "sinks": ["include", "require", "include_once", "require_once"],
      "pattern": "Path argument contains user input variables."
    },
    "remediation": "Strict whitelist of allowed files/paths.",
    "status": "complete",
    "findings": [
      {
        "file": "includes/Core/Plugin.php",
        "line": 229,
        "snippet": "include PRESSZONE_COMMENTS_PATH . 'templates/comments-list.php';",
        "context": "Hardcoded path inclusion - SECURE",
        "risk": "None - path is hardcoded, no user input"
      },
      {
        "file": "includes/Comments/Actions.php",
        "line": 102,
        "snippet": "include PRESSZONE_COMMENTS_PATH . 'templates/partials/comment-item.php';",
        "context": "Hardcoded path inclusion - SECURE",
        "risk": "None - path is hardcoded, no user input"
      },
      {
        "file": "templates/comments-list.php",
        "line": 74,
        "snippet": "include PRESSZONE_COMMENTS_PATH . 'templates/partials/comment-item.php';",
        "context": "Hardcoded path inclusion - SECURE",
        "risk": "None - path is hardcoded, no user input"
      },
      {
        "file": "templates/partials/comment-item.php",
        "line": 204,
        "snippet": "include PRESSZONE_COMMENTS_PATH . 'templates/partials/comment-item.php';",
        "context": "Recursive include with hardcoded path - SECURE",
        "risk": "None - path is hardcoded, no user input"
      },
      {
        "file": "templates/admin/design-preview.php",
        "line": 177,
        "snippet": "include PRESSZONE_COMMENTS_PATH . 'templates/comments-list.php';",
        "context": "Hardcoded path inclusion - SECURE",
        "risk": "None - path is hardcoded, no user input"
      }
    ]
  },
  {
    "id": "VULN-ZIP-01",
    "name": "Insecure Archive Extraction (Zip Slip)",
    "section": "7.2",
    "severity": "Critical",
    "description": "Using insecure unzip_file() or native ZipArchive without traversal checks.",
    "detection_logic": {
      "sinks": ["unzip_file", "ZipArchive::extractTo"],
      "pattern": "Extraction without validating filenames inside the zip for '../'."
    },
    "remediation": "Use WP_Filesystem::unzip_file() (modern versions) or validate destination paths.",
    "status": "complete",
    "findings": []
  },
  {
    "id": "VULN-REACT-01",
    "name": "React/Gutenberg Dangerous HTML",
    "section": "8.2",
    "severity": "High",
    "description": "Unsafe injection of HTML in React components.",
    "detection_logic": {
      "file_types": [".js", ".jsx", ".ts", ".tsx"],
      "pattern": "usage of dangerouslySetInnerHTML"
    },
    "remediation": "Sanitize HTML using DOMPurify or wp.sce.trustAsHtml.",
    "status": "complete",
    "findings": []
  },
  {
    "id": "VULN-REACT-02",
    "name": "React Attribute Injection",
    "section": "8.2",
    "severity": "Medium",
    "description": "Allowing javascript: URIs in React attributes.",
    "detection_logic": {
      "file_types": [".js", ".jsx"],
      "pattern": "href={...} or src={...} where variable is not sanitized."
    },
    "remediation": "Validate URL protocol to ensure it is http/https/mailto.",
    "status": "complete",
    "findings": []
  },
  {
    "id": "VULN-REDIR-01",
    "name": "Open Redirect",
    "section": "8.3",
    "severity": "Medium",
    "description": "Redirecting users to arbitrary URLs.",
    "detection_logic": {
      "sinks": ["wp_redirect"],
      "pattern": "Argument is user-controlled."
    },
    "remediation": "Use wp_safe_redirect() which enforces local domain or allowed whitelist.",
    "status": "complete",
    "findings": []
  },
  {
    "id": "VULN-SSRF-01",
    "name": "Server-Side Request Forgery",
    "section": "9.1",
    "severity": "Medium",
    "description": "Making HTTP requests to user-supplied URLs.",
    "detection_logic": {
      "sinks": ["wp_remote_get", "wp_remote_post", "curl_exec"],
      "pattern": "URL argument is user-controlled."
    },
    "remediation": "Use wp_safe_remote_get().",
    "status": "complete",
    "findings": [
      {
        "file": "includes/Comments/Moderation.php",
        "line": 159,
        "snippet": "$response = wp_remote_post('https://www.google.com/recaptcha/api/siteverify', [...]",
        "context": "Hardcoded URL to Google reCAPTCHA API - SECURE",
        "risk": "None - URL is hardcoded, not user-controlled"
      }
    ]
  },
  {
    "id": "VULN-RCE-01",
    "name": "Remote Code Execution (Callback)",
    "section": "2.3",
    "severity": "Critical",
    "description": "Executing arbitrary functions via user input.",
    "detection_logic": {
      "sinks": ["call_user_func", "call_user_func_array"],
      "pattern": "First argument is user-controlled input."
    },
    "remediation": "Allow only a strict whitelist of function names.",
    "status": "complete",
    "findings": []
  },
  {
    "id": "VULN-INFO-01",
    "name": "Sensitive Info Exposure (Debug)",
    "section": "10.2",
    "severity": "Low",
    "description": "Debug functions left in production code.",
    "detection_logic": {
      "pattern": "Usage of print_r(), var_dump(), or error_log() printing full objects."
    },
    "remediation": "Remove debug code.",
    "status": "complete",
    "findings": [
      {
        "file": "includes/Api/RestAdmin.php",
        "line": 130,
        "snippet": "error_log('[RestAdmin] Received params: ' . print_r($params, true));",
        "context": "Debug logging inside WP_DEBUG conditional block",
        "risk": "Low - wrapped in WP_DEBUG check, but should be removed for production"
      },
      {
        "file": "includes/Api/RestAdmin.php",
        "line": 138,
        "snippet": "error_log('[RestAdmin] Sanitized params: ' . print_r($sanitized_params, true));",
        "context": "Debug logging inside WP_DEBUG conditional block",
        "risk": "Low - wrapped in WP_DEBUG check, but should be removed for production"
      },
      {
        "file": "includes/Settings/Settings.php",
        "line": 55,
        "snippet": "error_log('[Settings] Sanitizing input: ' . print_r($input, true));",
        "context": "Debug logging inside WP_DEBUG conditional block",
        "risk": "Low - wrapped in WP_DEBUG check, but should be removed for production"
      },
      {
        "file": "includes/Settings/Settings.php",
        "line": 96,
        "snippet": "error_log('[Settings] Sanitized output: ' . print_r($output, true));",
        "context": "Debug logging inside WP_DEBUG conditional block",
        "risk": "Low - wrapped in WP_DEBUG check, but should be removed for production"
      }
    ]
  },
  {
    "id": "VULN-CODE-01",
    "name": "Commented-Out Security Checks",
    "section": "10.2",
    "severity": "Medium",
    "description": "Security logic (like current_user_can) that has been commented out.",
    "detection_logic": {
      "pattern": "//.*current_user_can|/*.*current_user_can"
    },
    "remediation": "Uncomment security checks or remove dead code.",
    "status": "complete",
    "findings": []
  },
  {
    "id": "VULN-DEP-01",
    "name": "Vulnerable Dependencies",
    "section": "10.2",
    "severity": "Medium",
    "description": "Outdated libraries in composer.lock.",
    "detection_logic": {
      "file": "composer.lock",
      "pattern": "Check package versions against known vulnerability database."
    },
    "remediation": "Run composer update.",
    "status": "complete",
    "findings": []
  }
]
