From bbdbafb3f91cc91b7acfe8191117de3a3d5c3e20 Mon Sep 17 00:00:00 2001 From: deepakpathania <68396823+deepakpathania@users.noreply.github.com> Date: Fri, 7 Jun 2024 18:25:01 +0530 Subject: [PATCH] Validate route params before making request (#8901) --- changelog/update-route-param-validation | 4 +++ ...est-payments-authorizations-controller.php | 2 +- ...ss-wc-rest-payments-charges-controller.php | 4 +-- ...s-wc-rest-payments-customer-controller.php | 2 +- ...s-wc-rest-payments-deposits-controller.php | 2 +- ...s-wc-rest-payments-disputes-controller.php | 6 ++--- ...lass-wc-rest-payments-files-controller.php | 6 ++--- ...est-payments-fraud-outcomes-controller.php | 2 +- ...ass-wc-rest-payments-orders-controller.php | 8 +++--- ...st-payments-payment-intents-controller.php | 2 +- ...ass-wc-rest-payments-reader-controller.php | 4 +-- ...payments-terminal-locations-controller.php | 6 ++--- ...s-wc-rest-payments-timeline-controller.php | 2 +- ...-rest-payments-transactions-controller.php | 2 +- ...ents-reports-authorizations-controller.php | 2 +- ...yments-reports-transactions-controller.php | 2 +- .../class-wc-payments-api-client.php | 26 +++++++++++++++++++ 17 files changed, 56 insertions(+), 26 deletions(-) create mode 100644 changelog/update-route-param-validation diff --git a/changelog/update-route-param-validation b/changelog/update-route-param-validation new file mode 100644 index 00000000000..4e92f0c3a2b --- /dev/null +++ b/changelog/update-route-param-validation @@ -0,0 +1,4 @@ +Significance: patch +Type: dev + +Add validation for path variables. diff --git a/includes/admin/class-wc-rest-payments-authorizations-controller.php b/includes/admin/class-wc-rest-payments-authorizations-controller.php index 1b2993e3c71..a35f3fc85e3 100644 --- a/includes/admin/class-wc-rest-payments-authorizations-controller.php +++ b/includes/admin/class-wc-rest-payments-authorizations-controller.php @@ -46,7 +46,7 @@ public function register_routes() { ); register_rest_route( $this->namespace, - '/' . $this->rest_base . '/(?P\w+)', + '/' . $this->rest_base . '/(?P(ch|pi|py)_[A-Za-z0-9]+)', [ 'methods' => WP_REST_Server::READABLE, 'callback' => [ $this, 'get_authorization' ], diff --git a/includes/admin/class-wc-rest-payments-charges-controller.php b/includes/admin/class-wc-rest-payments-charges-controller.php index 34422cac647..2297e3bd13a 100644 --- a/includes/admin/class-wc-rest-payments-charges-controller.php +++ b/includes/admin/class-wc-rest-payments-charges-controller.php @@ -28,7 +28,7 @@ class WC_REST_Payments_Charges_Controller extends WC_Payments_REST_Controller { public function register_routes() { register_rest_route( $this->namespace, - '/' . $this->rest_base . '/(?P\w+)', + '/' . $this->rest_base . '/(?Pch_[A-Za-z0-9]+)', [ 'methods' => WP_REST_Server::READABLE, 'callback' => [ $this, 'get_charge' ], @@ -37,7 +37,7 @@ public function register_routes() { ); register_rest_route( $this->namespace, - '/' . $this->rest_base . '/order/(?P\w+)', + '/' . $this->rest_base . '/order/(?P[A-Za-z0-9_\-]+)', [ 'methods' => WP_REST_Server::READABLE, 'callback' => [ $this, 'generate_charge_from_order' ], diff --git a/includes/admin/class-wc-rest-payments-customer-controller.php b/includes/admin/class-wc-rest-payments-customer-controller.php index c0f43a97003..5ccce5c99d6 100644 --- a/includes/admin/class-wc-rest-payments-customer-controller.php +++ b/includes/admin/class-wc-rest-payments-customer-controller.php @@ -49,7 +49,7 @@ public function __construct( public function register_routes() { register_rest_route( $this->namespace, - '/' . $this->rest_base . '/(?P\w+)/payment_methods', + '/' . $this->rest_base . '/(?P[A-Za-z0-9_\-]+)/payment_methods', [ [ 'methods' => WP_REST_Server::READABLE, diff --git a/includes/admin/class-wc-rest-payments-deposits-controller.php b/includes/admin/class-wc-rest-payments-deposits-controller.php index 1b5c808a314..da3b3c1afbc 100644 --- a/includes/admin/class-wc-rest-payments-deposits-controller.php +++ b/includes/admin/class-wc-rest-payments-deposits-controller.php @@ -55,7 +55,7 @@ public function register_routes() { ); register_rest_route( $this->namespace, - '/' . $this->rest_base . '/(?P\w+)', + '/' . $this->rest_base . '/(?P[A-Za-z0-9_\-]+)', [ 'methods' => WP_REST_Server::READABLE, 'callback' => [ $this, 'get_deposit' ], diff --git a/includes/admin/class-wc-rest-payments-disputes-controller.php b/includes/admin/class-wc-rest-payments-disputes-controller.php index 64e1e478a21..4dacf45ee5c 100644 --- a/includes/admin/class-wc-rest-payments-disputes-controller.php +++ b/includes/admin/class-wc-rest-payments-disputes-controller.php @@ -54,7 +54,7 @@ public function register_routes() { ); register_rest_route( $this->namespace, - '/' . $this->rest_base . '/(?P\w+)', + '/' . $this->rest_base . '/(?P(dp|dispute)_[A-Za-z0-9]+)', [ 'methods' => WP_REST_Server::READABLE, 'callback' => [ $this, 'get_dispute' ], @@ -63,7 +63,7 @@ public function register_routes() { ); register_rest_route( $this->namespace, - '/' . $this->rest_base . '/(?P\w+)', + '/' . $this->rest_base . '/(?P(dp|dispute)_[A-Za-z0-9]+)', [ 'methods' => WP_REST_Server::CREATABLE, 'callback' => [ $this, 'update_dispute' ], @@ -72,7 +72,7 @@ public function register_routes() { ); register_rest_route( $this->namespace, - '/' . $this->rest_base . '/(?P\w+)/close', + '/' . $this->rest_base . '/(?P(dp|dispute)_[A-Za-z0-9]+)/close', [ 'methods' => WP_REST_Server::CREATABLE, 'callback' => [ $this, 'close_dispute' ], diff --git a/includes/admin/class-wc-rest-payments-files-controller.php b/includes/admin/class-wc-rest-payments-files-controller.php index e66eedefffd..6720b52b959 100644 --- a/includes/admin/class-wc-rest-payments-files-controller.php +++ b/includes/admin/class-wc-rest-payments-files-controller.php @@ -35,7 +35,7 @@ public function register_routes() { register_rest_route( $this->namespace, - '/' . $this->rest_base . '/(?P\w+)/details', + '/' . $this->rest_base . '/(?P[A-Za-z0-9_\-]+)/details', [ 'methods' => WP_REST_Server::READABLE, 'callback' => [ $this, 'get_file_detail' ], @@ -45,7 +45,7 @@ public function register_routes() { register_rest_route( $this->namespace, - '/' . $this->rest_base . '/(?P\w+)/content', + '/' . $this->rest_base . '/(?P[A-Za-z0-9_\-]+)/content', [ 'methods' => WP_REST_Server::READABLE, 'callback' => [ $this, 'get_file_content' ], @@ -55,7 +55,7 @@ public function register_routes() { register_rest_route( $this->namespace, - '/' . $this->rest_base . '/(?P\w+)', + '/' . $this->rest_base . '/(?P[A-Za-z0-9_\-]+)', [ 'methods' => WP_REST_Server::READABLE, 'callback' => [ $this, 'get_file' ], diff --git a/includes/admin/class-wc-rest-payments-fraud-outcomes-controller.php b/includes/admin/class-wc-rest-payments-fraud-outcomes-controller.php index 7d0feb06024..199e62255cf 100644 --- a/includes/admin/class-wc-rest-payments-fraud-outcomes-controller.php +++ b/includes/admin/class-wc-rest-payments-fraud-outcomes-controller.php @@ -25,7 +25,7 @@ class WC_REST_Payments_Fraud_Outcomes_Controller extends WC_Payments_REST_Contro public function register_routes() { register_rest_route( $this->namespace, - '/' . $this->rest_base . '/(?P\w+)/latest', + '/' . $this->rest_base . '/(?P[A-Za-z0-9_\-]+)/latest', [ 'methods' => WP_REST_Server::READABLE, 'callback' => [ $this, 'get_latest_fraud_outcome' ], diff --git a/includes/admin/class-wc-rest-payments-orders-controller.php b/includes/admin/class-wc-rest-payments-orders-controller.php index 04c86f54197..f79e0a5fcfd 100644 --- a/includes/admin/class-wc-rest-payments-orders-controller.php +++ b/includes/admin/class-wc-rest-payments-orders-controller.php @@ -68,7 +68,7 @@ public function __construct( WC_Payments_API_Client $api_client, WC_Payment_Gate public function register_routes() { register_rest_route( $this->namespace, - $this->rest_base . '/(?P\w+)/capture_terminal_payment', + $this->rest_base . '/(?P[A-Za-z0-9_\-]+)/capture_terminal_payment', [ 'methods' => WP_REST_Server::CREATABLE, 'callback' => [ $this, 'capture_terminal_payment' ], @@ -82,7 +82,7 @@ public function register_routes() { ); register_rest_route( $this->namespace, - $this->rest_base . '/(?P\w+)/capture_authorization', + $this->rest_base . '/(?P[A-Za-z0-9_\-]+)/capture_authorization', [ 'methods' => WP_REST_Server::CREATABLE, 'callback' => [ $this, 'capture_authorization' ], @@ -96,7 +96,7 @@ public function register_routes() { ); register_rest_route( $this->namespace, - $this->rest_base . '/(?P\w+)/cancel_authorization', + $this->rest_base . '/(?P[A-Za-z0-9_\-]+)/cancel_authorization', [ 'methods' => WP_REST_Server::CREATABLE, 'callback' => [ $this, 'cancel_authorization' ], @@ -110,7 +110,7 @@ public function register_routes() { ); register_rest_route( $this->namespace, - $this->rest_base . '/(?P\w+)/create_terminal_intent', + $this->rest_base . '/(?P[A-Za-z0-9_\-]+)/create_terminal_intent', [ 'methods' => WP_REST_Server::CREATABLE, 'callback' => [ $this, 'create_terminal_intent' ], diff --git a/includes/admin/class-wc-rest-payments-payment-intents-controller.php b/includes/admin/class-wc-rest-payments-payment-intents-controller.php index 670d15a3089..9ba1a39fa67 100644 --- a/includes/admin/class-wc-rest-payments-payment-intents-controller.php +++ b/includes/admin/class-wc-rest-payments-payment-intents-controller.php @@ -32,7 +32,7 @@ class WC_REST_Payments_Payment_Intents_Controller extends WC_Payments_REST_Contr public function register_routes() { register_rest_route( $this->namespace, - '/' . $this->rest_base . '/(?P\w+)', + '/' . $this->rest_base . '/(?P(ch|pi|py)_[A-Za-z0-9]+)', [ 'methods' => WP_REST_Server::READABLE, 'callback' => [ $this, 'get_payment_intent' ], diff --git a/includes/admin/class-wc-rest-payments-reader-controller.php b/includes/admin/class-wc-rest-payments-reader-controller.php index fa6fa5192e0..569e49bc9ed 100644 --- a/includes/admin/class-wc-rest-payments-reader-controller.php +++ b/includes/admin/class-wc-rest-payments-reader-controller.php @@ -114,7 +114,7 @@ public function register_routes() { register_rest_route( $this->namespace, - '/' . $this->rest_base . '/charges/(?P\w+)', + '/' . $this->rest_base . '/charges/(?P[A-Za-z0-9_\-]+)', [ 'methods' => WP_REST_Server::READABLE, 'callback' => [ $this, 'get_summary' ], @@ -132,7 +132,7 @@ public function register_routes() { ); register_rest_route( $this->namespace, - '/' . $this->rest_base . '/receipts/(?P\w+)', + '/' . $this->rest_base . '/receipts/(?P(ch|pi|py)_[A-Za-z0-9]+)', [ 'methods' => WP_REST_Server::READABLE, 'callback' => [ $this, 'generate_print_receipt' ], diff --git a/includes/admin/class-wc-rest-payments-terminal-locations-controller.php b/includes/admin/class-wc-rest-payments-terminal-locations-controller.php index c0f0f7754ee..90062ef3b8c 100644 --- a/includes/admin/class-wc-rest-payments-terminal-locations-controller.php +++ b/includes/admin/class-wc-rest-payments-terminal-locations-controller.php @@ -38,7 +38,7 @@ public function register_routes() { ); register_rest_route( $this->namespace, - '/' . $this->rest_base . '/(?P\w+)', + '/' . $this->rest_base . '/(?P[A-Za-z0-9_\-]+)', [ 'methods' => WP_REST_Server::DELETABLE, 'callback' => [ $this, 'delete_location' ], @@ -47,7 +47,7 @@ public function register_routes() { ); register_rest_route( $this->namespace, - '/' . $this->rest_base . '/(?P\w+)', + '/' . $this->rest_base . '/(?P[A-Za-z0-9_\-]+)', [ 'methods' => WP_REST_Server::CREATABLE, 'callback' => [ $this, 'update_location' ], @@ -66,7 +66,7 @@ public function register_routes() { ); register_rest_route( $this->namespace, - '/' . $this->rest_base . '/(?P\w+)', + '/' . $this->rest_base . '/(?P[A-Za-z0-9_\-]+)', [ 'methods' => WP_REST_Server::READABLE, 'callback' => [ $this, 'get_location' ], diff --git a/includes/admin/class-wc-rest-payments-timeline-controller.php b/includes/admin/class-wc-rest-payments-timeline-controller.php index c2c0f5ac87a..23a1c4136d1 100644 --- a/includes/admin/class-wc-rest-payments-timeline-controller.php +++ b/includes/admin/class-wc-rest-payments-timeline-controller.php @@ -24,7 +24,7 @@ class WC_REST_Payments_Timeline_Controller extends WC_Payments_REST_Controller { public function register_routes() { register_rest_route( $this->namespace, - '/' . $this->rest_base . '/(?P\w+)', + '/' . $this->rest_base . '/(?P(ch|pi|py)_[A-Za-z0-9]+)', [ 'methods' => WP_REST_Server::READABLE, 'callback' => [ $this, 'get_timeline' ], diff --git a/includes/admin/class-wc-rest-payments-transactions-controller.php b/includes/admin/class-wc-rest-payments-transactions-controller.php index c3a783943b8..5c72a32ed0e 100644 --- a/includes/admin/class-wc-rest-payments-transactions-controller.php +++ b/includes/admin/class-wc-rest-payments-transactions-controller.php @@ -100,7 +100,7 @@ public function register_routes() { ); register_rest_route( $this->namespace, - '/' . $this->rest_base . '/(?P\w+)', + '/' . $this->rest_base . '/(?P[A-Za-z0-9_\-]+)', [ 'methods' => WP_REST_Server::READABLE, 'callback' => [ $this, 'get_transaction' ], diff --git a/includes/reports/class-wc-rest-payments-reports-authorizations-controller.php b/includes/reports/class-wc-rest-payments-reports-authorizations-controller.php index 0834d078eeb..20cba8bc6cf 100644 --- a/includes/reports/class-wc-rest-payments-reports-authorizations-controller.php +++ b/includes/reports/class-wc-rest-payments-reports-authorizations-controller.php @@ -40,7 +40,7 @@ public function register_routes() { ); register_rest_route( $this->namespace, - '/' . $this->rest_base . '/(?P\w+)', + '/' . $this->rest_base . '/(?P[A-Za-z0-9_\-]+)', [ [ 'methods' => WP_REST_Server::READABLE, diff --git a/includes/reports/class-wc-rest-payments-reports-transactions-controller.php b/includes/reports/class-wc-rest-payments-reports-transactions-controller.php index 1e38d6cd746..6e130400af2 100644 --- a/includes/reports/class-wc-rest-payments-reports-transactions-controller.php +++ b/includes/reports/class-wc-rest-payments-reports-transactions-controller.php @@ -39,7 +39,7 @@ public function register_routes() { ); register_rest_route( $this->namespace, - '/' . $this->rest_base . '/(?P\w+)', + '/' . $this->rest_base . '/(?P[A-Za-z0-9_\-]+)', [ [ 'methods' => WP_REST_Server::READABLE, diff --git a/includes/wc-payment-api/class-wc-payments-api-client.php b/includes/wc-payment-api/class-wc-payments-api-client.php index 8c3e6c29ba9..41e8c35cad5 100644 --- a/includes/wc-payment-api/class-wc-payments-api-client.php +++ b/includes/wc-payment-api/class-wc-payments-api-client.php @@ -518,8 +518,17 @@ public function get_disputes( array $filters = [] ) { * * @param string $dispute_id id of requested dispute. * @return array dispute object. + * @throws API_Exception - Exception thrown in case route validation fails. */ public function get_dispute( $dispute_id ) { + if ( ! preg_match( '/(dp|dispute)_[A-Za-z0-9]+/', $dispute_id ) ) { + throw new API_Exception( + __( 'Route param validation failed.', 'woocommerce-payments' ), + 'wcpay_route_validation_failure', + 400 + ); + } + $dispute = $this->request( [], self::DISPUTES_API . '/' . $dispute_id, self::GET ); if ( is_wp_error( $dispute ) ) { @@ -726,8 +735,17 @@ public function create_token( $request ) { * @return array * * @throws Exception - Exception thrown on request failure. + * @throws API_Exception - Exception thrown in case route validation fails. */ public function get_timeline( $id ) { + if ( ! preg_match( '/(ch|pi|py)_[A-Za-z0-9]+/', $id ) ) { + throw new API_Exception( + __( 'Route param validation failed.', 'woocommerce-payments' ), + 'wcpay_route_validation_failure', + 400 + ); + } + $timeline = $this->request( [], self::TIMELINE_API . '/' . $id, self::GET ); $has_fraud_outcome_event = false; @@ -1199,6 +1217,14 @@ public function update_charge( string $charge_id, array $data = [] ) { * @throws API_Exception */ public function get_charge( string $charge_id ) { + if ( ! preg_match( '/(ch|pi|py)_[A-Za-z0-9]+/', $charge_id ) ) { + throw new API_Exception( + __( 'Route param validation failed.', 'woocommerce-payments' ), + 'wcpay_route_validation_failure', + 400 + ); + } + return $this->request( [], self::CHARGES_API . '/' . $charge_id,