Issues (197)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

tests/phpunit/test-wc-stripe-sub-initial.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * These tests assert various things about processing an initial payment for a WooCommerce Subscriptions.
4
 *
5
 * The responses from HTTP requests are mocked using the WP filter `pre_http_request`.
6
 *
7
 * There are a few methods that need to be mocked in the class WC_Stripe_Subs_Compat, which is
8
 * why that class is mocked even though the method under test is part of that class.
9
 *
10
 * @package WooCommerce_Stripe/Classes/WC_Stripe_Subscription_Initial_Test
11
 */
12
13
/**
14
 * WC_Stripe_Subscription_Initial_Test
15
 */
16
class WC_Stripe_Subscription_Initial_Test extends WP_UnitTestCase {
17
	/**
18
	 * System under test, and a mock object with some methods mocked for testing
19
	 *
20
	 * @var PHPUnit_Framework_MockObject_MockObject
21
	 */
22
	private $wc_stripe_subs_compat;
23
24
	/**
25
	 * The statement descriptor we'll use in a test.
26
	 *
27
	 * @var string
28
	 */
29
	private $statement_descriptor;
30
31
	/**
32
	 * Sets up things all tests need.
33
	 */
34
	public function setUp() {
35
		parent::setUp();
36
37
		$this->wc_stripe_subs_compat = $this->getMockBuilder( 'WC_Stripe_Subs_Compat' )
38
			->disableOriginalConstructor()
39
			->setMethods( array( 'prepare_source', 'has_subscription' ) )
40
			->getMock();
41
42
		// Mocked in order to get metadata[payment_type] = recurring in the HTTP request.
43
		$this->statement_descriptor = 'This is a statement descriptor.';
44
		update_option(
45
			'woocommerce_stripe_settings',
46
			array(
47
				'statement_descriptor' => $this->statement_descriptor,
48
			)
49
		);
50
	}
51
52
	/**
53
	 * Tears down the stuff we set up.
54
	 */
55
	public function tearDown() {
56
		parent::tearDown();
57
		delete_option( 'woocommerce_stripe_settings' );
58
	}
59
60
	/**
61
	 * Tests whether the initial payment succeeds and includes the `setup_future_usage` parameter.
62
	 *
63
	 * 1. Several things are set up or mocked.
64
	 * 2. A function that will mock an HTTP response for the payment_intents is created.
65
	 * 3. That same function has some assertions about the things we send to the
66
	 * payments_intents endpoint.
67
	 * 4. The function under test - `process_payment` - is called.
68
	 * 5. More assertions are made.
69
	 */
70
	public function test_initial_intent_parameters() {
71
		$initial_order        = WC_Helper_Order::create_order();
72
		$order_id             = $initial_order->get_id();
73
		$stripe_amount        = WC_Stripe_Helper::get_stripe_amount( $initial_order->get_total() );
74
		$currency             = strtolower( $initial_order->get_currency() );
75
		$customer             = 'cus_123abc';
76
		$source               = 'src_123abc';
77
		$statement_descriptor = WC_Stripe_Helper::clean_statement_descriptor( $this->statement_descriptor );
78
		$intents_api_endpoint = 'https://api.stripe.com/v1/payment_intents';
79
		$urls_used            = array();
80
81
		$initial_order->set_payment_method( 'stripe' );
82
		$initial_order->save();
83
84
		// Arrange: Mock prepare_source() so that we have a customer and source.
85
		$this->wc_stripe_subs_compat
86
			->expects( $this->any() )
87
			->method( 'prepare_source' )
88
			->will(
89
				$this->returnValue(
90
					(object) array(
91
						'token_id'      => false,
92
						'customer'      => $customer,
93
						'source'        => $source,
94
						'source_object' => (object) array(),
95
					)
96
				)
97
			);
98
99
		// Emulate a subscription.
100
		$this->wc_stripe_subs_compat
101
			->expects( $this->any() )
102
			->method( 'has_subscription' )
103
			->will( $this->returnValue( true ) );
104
105
		$pre_http_request_response_callback = function( $preempt, $request_args, $url ) use (
106
			$stripe_amount,
107
			$currency,
108
			$customer,
109
			$source,
110
			$intents_api_endpoint,
111
			$statement_descriptor,
112
			$order_id,
113
			&$urls_used
114
		) {
115
			// Add all urls to array so we can later make assertions about which endpoints were used.
116
			array_push( $urls_used, $url );
117
			// Continue without mocking the request if it's not the endpoint we care about.
118
			if ( 0 !== strpos( $url, $intents_api_endpoint ) ) {
119
				return false;
120
			}
121
122
			// Prepare the response early because it is used for confirmations too.
123
			$response = array(
124
				'headers'  => array(),
125
				// Too bad we aren't dynamically setting things 'cus_123abc' when using this file.
126
				'body'     => file_get_contents( 'tests/phpunit/dummy-data/subscription_signup_response_success.json' ),
127
				'response' => array(
128
					'code'    => 200,
129
					'message' => 'OK',
130
				),
131
				'cookies'  => array(),
132
				'filename' => null,
133
			);
134
135
			// Respond with a successfull intent for confirmations.
136
			if ( $url !== $intents_api_endpoint ) {
137
				$response['body'] = str_replace( 'requires_confirmation', 'succeeded', $response['body'] );
138
				return $response;
139
			}
140
141
			// Assert: the request method is POST.
142
			$this->assertArrayHasKey( 'method', $request_args );
143
			$this->assertSame( 'POST', $request_args['method'] );
144
145
			// Assert: the request has a body.
146
			$this->assertArrayHasKey( 'body', $request_args );
147
148
			// Assert: the request body contains these values.
149
			$expected_request_body_values = array(
150
				'source'               => $source,
151
				'amount'               => $stripe_amount,
152
				'currency'             => $currency,
153
				'statement_descriptor' => $statement_descriptor,
154
				'customer'             => $customer,
155
				'setup_future_usage'   => 'off_session',
156
				'payment_method_types' => array( 'card' ),
157
			);
158 View Code Duplication
			foreach ( $expected_request_body_values as $key => $value ) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
159
				$this->assertArrayHasKey( $key, $request_args['body'] );
160
				$this->assertSame( $value, $request_args['body'][ $key ] );
161
			}
162
163
			// Assert: the request body contains these keys, without checking for their value.
164
			$expected_request_body_keys = array(
165
				'description',
166
				'capture_method',
167
			);
168
			foreach ( $expected_request_body_keys as $key ) {
169
				$this->assertArrayHasKey( $key, $request_args['body'] );
170
			}
171
172
			// Assert: the body metadata contains the order ID.
173
			$this->assertSame( $order_id, absint( $request_args['body']['metadata']['order_id'] ) );
174
175
			// // Assert: the body metadata has these keys, without checking for their value.
176
			$expected_metadata_keys = array(
177
				'customer_name',
178
				'customer_email',
179
			);
180
			foreach ( $expected_metadata_keys as $key ) {
181
				$this->assertArrayHasKey( $key, $request_args['body']['metadata'] );
182
			}
183
184
			// Return dummy content as the response.
185
			return $response;
186
		};
187
		add_filter( 'pre_http_request', $pre_http_request_response_callback, 10, 3 );
188
189
		// Act: call process_subscription_payment().
190
		// We need to use `wc_stripe_subs_compat` here because we mocked this class earlier.
191
		$result = $this->wc_stripe_subs_compat->process_payment( $order_id );
192
193
		// Assert: nothing was returned.
194
		$this->assertEquals( $result['result'], 'success' );
195
		$this->assertArrayHasKey( 'redirect', $result );
196
197
		$order      = wc_get_order( $order_id );
198
		$order_data = $order->get_meta( '_stripe_intent_id' );
199
200
		$this->assertEquals( $order_data, 'pi_123abc' );
201
202
		// Assert: called payment intents.
203
		$this->assertTrue( in_array( $intents_api_endpoint, $urls_used, true ) );
204
205
		// Clean up.
206
		remove_filter( 'pre_http_request', array( $this, 'pre_http_request_response_success' ) );
207
	}
208
}
209