Changeset 3763398
- Timestamp:
- 10/24/2026 02:43:36 PM (21 hours ago)
- Location:
- mega-ai
- Files:
-
- 6 added
- 4 edited
- 1 copied
-
tags/2.19.0 (copied) (copied from mega-ai/trunk )
-
tags/2.19.0/auth-v2-canonical.php (added)
-
tags/2.19.0/auth-v2-keys.php (added)
-
tags/2.19.0/auth-v2.php (added)
-
tags/2.19.0/mega.php (modified) (12 diffs)
-
tags/2.19.0/readme.txt (modified) (2 diffs)
-
trunk/auth-v2-canonical.php (added)
-
trunk/auth-v2-keys.php (added)
-
trunk/auth-v2.php (added)
-
trunk/mega.php (modified) (12 diffs)
-
trunk/readme.txt (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
mega-ai/tags/2.19.0/mega.php
r3763355 r3763398 3 3 Plugin Name: MEGA AI 4 4 Description: Connect your WordPress website to MEGA for automated SEO optimization and content management. 5 Version: 2.1 7.25 Version: 2.19.0 6 6 Author: MEGA 7 7 Author URI: https://gomega.ai … … 36 36 require_once(__DIR__ . '/phone-replace.php'); 37 37 require_once(__DIR__ . '/page-cache-purge.php'); 38 // Request authentication, signature v2 (see AGENTS.md, "Signature v2"). Loads its own helpers. 39 require_once(__DIR__ . '/auth-v2.php'); 38 40 39 41 use WP_REST_Server; … … 44 46 class MegaPlugin { 45 47 private static $namespace = 'mega'; 46 private static $version = '2.1 7.2';48 private static $version = '2.19.0'; 47 49 48 50 // Editor (widget) endpoints. … … 161 163 162 164 // Default settings 163 private static $default_public_key_endpoint = 'https://cdn.gomega.ai/keys/wp-public.key';165 private static $default_public_key_endpoint = MegaSigKeyPin::DEFAULT_ENDPOINT; 164 166 private static $default_change_log_endpoint = 'https://app.gomega.ai/api/agents/cms/change-log'; 165 167 private static $change_log_max_queue_events = 100; … … 179 181 /** The single plugin instance, for static callers outside the class. */ 180 182 private static $instance; 183 private $auth_v2 = null; 181 184 182 185 public function __construct() { … … 243 246 \MegaIntentRunner::register(); 244 247 MegaSandbox::register_hooks(); 248 MegaAuthV2::register_hooks(); 245 249 } 246 250 … … 662 666 $response->header('Pragma', 'no-cache'); 663 667 $response->header('Expires', '0'); 668 $auth_result = MegaAuthV2::response_header_value(); 669 if ($auth_result !== null) { 670 $response->header('X-Mega-Auth-Result', $auth_result); 671 } 664 672 } 665 673 … … 680 688 681 689 /** 682 * Authenticate requests using signature verification 690 * Authenticate requests: signature v2 when the request carries v2 headers or the site is locked to 691 * v2, otherwise the legacy v1 check below. See MegaAuthV2. 683 692 */ 684 693 private function authenticate($request) { 694 if ($this->auth_v2 === null) { 695 $this->auth_v2 = new MegaAuthV2(); 696 } 697 return $this->auth_v2->authenticate($request, array($this, 'authenticate_v1')); 698 } 699 700 /** 701 * Legacy (v1) authentication: RSA signature over the site identifier. Public only because 702 * MegaAuthV2 calls it back; never call it directly. 703 */ 704 public function authenticate_v1($request) { 685 705 $signature = $request->get_header('Signature'); 686 706 … … 792 812 } 793 813 814 // MEGA's own endpoint: the key must be one we ship a fingerprint for. A customer-set custom 815 // endpoint keeps its legacy unpinned behaviour (v2 never reads that setting). 816 if ($public_key_endpoint === self::$default_public_key_endpoint) { 817 $pin = MegaSigKeyPin::check_pem($public_key); 818 if (!$pin['ok']) { 819 return new \WP_Error( 820 'mega_auth_key_pin_mismatch', 821 'Authentication failed: the public key served by the key endpoint is not one this plugin trusts.', 822 array('status' => 500, 'key_error' => $pin['error']) 823 ); 824 } 825 // Verify against exactly the key that passed the pin, not the raw response body. 826 $public_key = $pin['pem']; 827 } 828 794 829 // Verify signature 795 830 $decoded_signature = base64_decode($signature, true); … … 1531 1566 } 1532 1567 1533 $response = array( 1534 'seo_plugin' => $this->detect_seo_plugin(), 1535 'change_log_secret' => $this->ensure_change_log_secret(), 1536 'active_plugins' => $active_plugins, 1537 'inactive_plugins' => $inactive_plugins 1538 ); 1568 // The secret leaves the site only to a v1-authenticated request on a site that has not locked 1569 // to v2: under v2 it is provisioned through the identifier rotation, never over this route. 1570 $response = array('seo_plugin' => $this->detect_seo_plugin()); 1571 if (MegaAuthV2::authenticated_by_v1_on_unlocked_site()) { 1572 $response['change_log_secret'] = $this->ensure_change_log_secret(); 1573 } 1574 $response['active_plugins'] = $active_plugins; 1575 $response['inactive_plugins'] = $inactive_plugins; 1539 1576 // Omit (rather than send a fake {}/[]) when either check couldn't be 1540 1577 // taken, so the platform can tell "clean" from "unknown". … … 7231 7268 </form> 7232 7269 <?php 7270 MegaAuthV2::render_admin_panel(); 7233 7271 } 7234 7272 … … 10563 10601 // Without this the hourly sweep stays scheduled with no listener after deactivation. 10564 10602 MegaSandbox::register_lifecycle(__FILE__); 10603 MegaAuthV2::register_lifecycle(__FILE__); -
mega-ai/tags/2.19.0/readme.txt
r3763355 r3763398 4 4 Requires at least: 4.4 5 5 Tested up to: 6.8 6 Stable tag: 2.1 7.26 Stable tag: 2.19.0 7 7 Requires PHP: 7.2 8 8 License: GPLv2 or later … … 139 139 140 140 == Changelog == 141 = 2.19.0 = 142 * Security: stronger request authentication. The plugin can now verify requests that carry a per-request signature over the method, address, query, body and a single-use nonce, so a captured request is of little use to anyone else. MEGA turns this on for a site; until then requests are authenticated with the older signature format as before. Once a site has accepted its first such request it stops accepting the older signature format. 143 * Security: MEGA's public key is checked against fingerprints built into the plugin before it is used to verify a signature (the older format too, when the default key address is in use), and the verified key is cached for an hour. 144 * Change: `GET /mega/v1/plugins` returns `change_log_secret` only to an older-format request on a site that has not switched. 145 * Feature: if MEGA cannot connect after a server or proxy change, an administrator can reset request authentication from Settings > MEGA, or with `wp mega auth-reset`. Nothing can reset it remotely. 146 * Change: replay records for the new signatures are kept in the options table and removed hourly. 147 141 148 = 2.17.2 = 142 149 * Packaging: the WordPress.org release no longer includes development and test files. -
mega-ai/trunk/mega.php
r3763355 r3763398 3 3 Plugin Name: MEGA AI 4 4 Description: Connect your WordPress website to MEGA for automated SEO optimization and content management. 5 Version: 2.1 7.25 Version: 2.19.0 6 6 Author: MEGA 7 7 Author URI: https://gomega.ai … … 36 36 require_once(__DIR__ . '/phone-replace.php'); 37 37 require_once(__DIR__ . '/page-cache-purge.php'); 38 // Request authentication, signature v2 (see AGENTS.md, "Signature v2"). Loads its own helpers. 39 require_once(__DIR__ . '/auth-v2.php'); 38 40 39 41 use WP_REST_Server; … … 44 46 class MegaPlugin { 45 47 private static $namespace = 'mega'; 46 private static $version = '2.1 7.2';48 private static $version = '2.19.0'; 47 49 48 50 // Editor (widget) endpoints. … … 161 163 162 164 // Default settings 163 private static $default_public_key_endpoint = 'https://cdn.gomega.ai/keys/wp-public.key';165 private static $default_public_key_endpoint = MegaSigKeyPin::DEFAULT_ENDPOINT; 164 166 private static $default_change_log_endpoint = 'https://app.gomega.ai/api/agents/cms/change-log'; 165 167 private static $change_log_max_queue_events = 100; … … 179 181 /** The single plugin instance, for static callers outside the class. */ 180 182 private static $instance; 183 private $auth_v2 = null; 181 184 182 185 public function __construct() { … … 243 246 \MegaIntentRunner::register(); 244 247 MegaSandbox::register_hooks(); 248 MegaAuthV2::register_hooks(); 245 249 } 246 250 … … 662 666 $response->header('Pragma', 'no-cache'); 663 667 $response->header('Expires', '0'); 668 $auth_result = MegaAuthV2::response_header_value(); 669 if ($auth_result !== null) { 670 $response->header('X-Mega-Auth-Result', $auth_result); 671 } 664 672 } 665 673 … … 680 688 681 689 /** 682 * Authenticate requests using signature verification 690 * Authenticate requests: signature v2 when the request carries v2 headers or the site is locked to 691 * v2, otherwise the legacy v1 check below. See MegaAuthV2. 683 692 */ 684 693 private function authenticate($request) { 694 if ($this->auth_v2 === null) { 695 $this->auth_v2 = new MegaAuthV2(); 696 } 697 return $this->auth_v2->authenticate($request, array($this, 'authenticate_v1')); 698 } 699 700 /** 701 * Legacy (v1) authentication: RSA signature over the site identifier. Public only because 702 * MegaAuthV2 calls it back; never call it directly. 703 */ 704 public function authenticate_v1($request) { 685 705 $signature = $request->get_header('Signature'); 686 706 … … 792 812 } 793 813 814 // MEGA's own endpoint: the key must be one we ship a fingerprint for. A customer-set custom 815 // endpoint keeps its legacy unpinned behaviour (v2 never reads that setting). 816 if ($public_key_endpoint === self::$default_public_key_endpoint) { 817 $pin = MegaSigKeyPin::check_pem($public_key); 818 if (!$pin['ok']) { 819 return new \WP_Error( 820 'mega_auth_key_pin_mismatch', 821 'Authentication failed: the public key served by the key endpoint is not one this plugin trusts.', 822 array('status' => 500, 'key_error' => $pin['error']) 823 ); 824 } 825 // Verify against exactly the key that passed the pin, not the raw response body. 826 $public_key = $pin['pem']; 827 } 828 794 829 // Verify signature 795 830 $decoded_signature = base64_decode($signature, true); … … 1531 1566 } 1532 1567 1533 $response = array( 1534 'seo_plugin' => $this->detect_seo_plugin(), 1535 'change_log_secret' => $this->ensure_change_log_secret(), 1536 'active_plugins' => $active_plugins, 1537 'inactive_plugins' => $inactive_plugins 1538 ); 1568 // The secret leaves the site only to a v1-authenticated request on a site that has not locked 1569 // to v2: under v2 it is provisioned through the identifier rotation, never over this route. 1570 $response = array('seo_plugin' => $this->detect_seo_plugin()); 1571 if (MegaAuthV2::authenticated_by_v1_on_unlocked_site()) { 1572 $response['change_log_secret'] = $this->ensure_change_log_secret(); 1573 } 1574 $response['active_plugins'] = $active_plugins; 1575 $response['inactive_plugins'] = $inactive_plugins; 1539 1576 // Omit (rather than send a fake {}/[]) when either check couldn't be 1540 1577 // taken, so the platform can tell "clean" from "unknown". … … 7231 7268 </form> 7232 7269 <?php 7270 MegaAuthV2::render_admin_panel(); 7233 7271 } 7234 7272 … … 10563 10601 // Without this the hourly sweep stays scheduled with no listener after deactivation. 10564 10602 MegaSandbox::register_lifecycle(__FILE__); 10603 MegaAuthV2::register_lifecycle(__FILE__); -
mega-ai/trunk/readme.txt
r3763355 r3763398 4 4 Requires at least: 4.4 5 5 Tested up to: 6.8 6 Stable tag: 2.1 7.26 Stable tag: 2.19.0 7 7 Requires PHP: 7.2 8 8 License: GPLv2 or later … … 139 139 140 140 == Changelog == 141 = 2.19.0 = 142 * Security: stronger request authentication. The plugin can now verify requests that carry a per-request signature over the method, address, query, body and a single-use nonce, so a captured request is of little use to anyone else. MEGA turns this on for a site; until then requests are authenticated with the older signature format as before. Once a site has accepted its first such request it stops accepting the older signature format. 143 * Security: MEGA's public key is checked against fingerprints built into the plugin before it is used to verify a signature (the older format too, when the default key address is in use), and the verified key is cached for an hour. 144 * Change: `GET /mega/v1/plugins` returns `change_log_secret` only to an older-format request on a site that has not switched. 145 * Feature: if MEGA cannot connect after a server or proxy change, an administrator can reset request authentication from Settings > MEGA, or with `wp mega auth-reset`. Nothing can reset it remotely. 146 * Change: replay records for the new signatures are kept in the options table and removed hourly. 147 141 148 = 2.17.2 = 142 149 * Packaging: the WordPress.org release no longer includes development and test files.
Note:
See TracChangeset
for help on using the changeset viewer.
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)