Issues (850)

Security Analysis    4 potential vulnerabilities

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

  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.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  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.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  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.
  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.
  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.
  Code Injection (1)
Code Injection enables an attacker to execute arbitrary code on the server.
  Variable Injection (2)
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
  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.
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  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.
  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.
  Cross-Site Scripting (1)
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.
  Header Injection
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.

includes/admin/class-getpaid-metaboxes.php (3 issues)

Labels
1
<?php
2
/**
3
 * Metaboxes Admin.
4
 *
5
 */
6
7
defined( 'ABSPATH' ) || exit;
8
9
/**
10
 * Metaboxes Admin Class
11
 *
12
 */
13
class GetPaid_Metaboxes {
14
15
	/**
16
	 * Only save metaboxes once.
17
	 *
18
	 * @var boolean
19
	 */
20
	private static $saved_meta_boxes = false;
21
22
    /**
23
	 * Hook in methods.
24
	 */
25
	public static function init() {
26
27
		// Register metaboxes.
28
		add_action( 'add_meta_boxes', 'GetPaid_Metaboxes::add_meta_boxes', 50, 2 );
29
30
		// Remove metaboxes.
31
		add_action( 'add_meta_boxes', 'GetPaid_Metaboxes::remove_meta_boxes', 30 );
32
33
		// Rename metaboxes.
34
		add_action( 'add_meta_boxes', 'GetPaid_Metaboxes::rename_meta_boxes', 45 );
35
36
		// Save metaboxes.
37
		add_action( 'save_post', 'GetPaid_Metaboxes::save_meta_boxes', 1, 2 );
38
	}
39
40
	/**
41
	 * Register core metaboxes.
42
	 */
43
	public static function add_meta_boxes( $post_type, $post ) {
44
45
		// For invoices.
46
		self::add_invoice_meta_boxes( $post_type, $post );
47
48
		// For payment forms.
49
		self::add_payment_form_meta_boxes( $post_type, $post );
50
51
		// For invoice items.
52
		self::add_item_meta_boxes( $post_type );
53
54
		// For invoice discounts.
55
		if ( 'wpi_discount' === $post_type ) {
56
			add_meta_box( 'wpinv_discount_details', __( 'Discount Details', 'invoicing' ), 'GetPaid_Meta_Box_Discount_Details::output', 'wpi_discount', 'normal', 'high' );
57
		}
58
59
	}
60
61
	/**
62
	 * Register core metaboxes.
63
	 */
64
	protected static function add_payment_form_meta_boxes( $post_type, $post ) {
65
66
		// For payment forms.
67
		if ( 'wpi_payment_form' === $post_type ) {
68
69
			// Design payment form.
70
			add_meta_box( 'wpinv-payment-form-design', __( 'Payment Form', 'invoicing' ), 'GetPaid_Meta_Box_Payment_Form::output', 'wpi_payment_form', 'normal' );
71
72
			// Payment form information.
73
			if ( wpinv_get_default_payment_form() !== $post->ID ) {
74
				add_meta_box( 'wpinv-payment-form-info', __( 'Details', 'invoicing' ), 'GetPaid_Meta_Box_Payment_Form_Info::output', 'wpi_payment_form', 'side' );
75
			}
76
}
77
78
	}
79
80
	/**
81
	 * Register core metaboxes.
82
	 */
83
	protected static function add_item_meta_boxes( $post_type ) {
84
85
		if ( 'wpi_item' === $post_type ) {
86
87
			// Item details.
88
			add_meta_box( 'wpinv_item_details', __( 'Item Details', 'invoicing' ), 'GetPaid_Meta_Box_Item_Details::output', 'wpi_item', 'normal', 'high' );
89
90
			// If taxes are enabled, register the tax metabox.
91
			if ( wpinv_use_taxes() ) {
92
				add_meta_box( 'wpinv_item_vat', __( 'Tax', 'invoicing' ), 'GetPaid_Meta_Box_Item_VAT::output', 'wpi_item', 'normal', 'high' );
93
			}
94
95
			// Item info.
96
			add_meta_box( 'wpinv_field_item_info', __( 'Item info', 'invoicing' ), 'GetPaid_Meta_Box_Item_Info::output', 'wpi_item', 'side', 'core' );
97
98
			// Item description.
99
			add_meta_box( 'postexcerpt', __( 'Item Description', 'invoicing' ), 'GetPaid_Meta_Box_Description::output', 'wpi_item', 'normal' );
100
		}
101
102
	}
103
104
	/**
105
	 * Register invoice metaboxes.
106
	 */
107
	protected static function add_invoice_meta_boxes( $post_type, $post ) {
108
109
		// For invoices...
110
		if ( getpaid_is_invoice_post_type( $post_type ) ) {
111
			$invoice = new WPInv_Invoice( $post );
112
113
			// Resend invoice.
114
			if ( ! $invoice->is_draft() ) {
115
116
				add_meta_box(
117
					'wpinv-mb-resend-invoice',
118
					sprintf(
119
						// translators: %s is the invoice type.
120
						__( 'Resend %s', 'invoicing' ),
121
						ucfirst( $invoice->get_invoice_quote_type() )
122
					),
123
					'GetPaid_Meta_Box_Resend_Invoice::output',
124
					$post_type,
125
					'side',
126
					'low'
127
				);
128
129
			}
130
131
			// Subscriptions.
132
			$subscriptions = getpaid_get_invoice_subscriptions( $invoice );
133
			if ( ! empty( $subscriptions ) ) {
134
135
				if ( is_array( $subscriptions ) ) {
0 ignored issues
show
The condition is_array($subscriptions) is always false.
Loading history...
136
					add_meta_box( 'wpinv-mb-subscriptions', __( 'Related Subscriptions', 'invoicing' ), 'GetPaid_Meta_Box_Invoice_Subscription::output_related', $post_type, 'advanced' );
137
				} else {
138
					add_meta_box( 'wpinv-mb-subscriptions', __( 'Subscription Details', 'invoicing' ), 'GetPaid_Meta_Box_Invoice_Subscription::output', $post_type, 'advanced' );
139
				}
140
141
				if ( getpaid_count_subscription_invoices( $invoice->is_renewal() ? $invoice->get_parent_id() : $invoice->get_id() ) > 1 ) {
142
					add_meta_box( 'wpinv-mb-subscription-invoices', __( 'Related Payments', 'invoicing' ), 'GetPaid_Meta_Box_Invoice_Subscription::output_invoices', $post_type, 'advanced' );
143
				}
144
}
145
146
			// Invoice details.
147
			add_meta_box(
148
				'wpinv-details',
149
				sprintf(
150
					// translators: %s is the invoice type.
151
					__( '%s Details', 'invoicing' ),
152
					ucfirst( $invoice->get_invoice_quote_type() )
153
				),
154
				'GetPaid_Meta_Box_Invoice_Details::output',
155
				$post_type,
156
				'side'
157
			);
158
159
			// Payment details.
160
			add_meta_box( 'wpinv-payment-meta', __( 'Payment Meta', 'invoicing' ), 'GetPaid_Meta_Box_Invoice_Payment_Meta::output', $post_type, 'side', 'default' );
161
162
			// Billing details.
163
			add_meta_box( 'wpinv-address', __( 'Billing Details', 'invoicing' ), 'GetPaid_Meta_Box_Invoice_Address::output', $post_type, 'normal', 'high' );
164
165
			// Invoice items.
166
			add_meta_box(
167
				'wpinv-items',
168
				sprintf(
169
					// translators: %s is the invoice type.
170
					__( '%s Items', 'invoicing' ),
171
					ucfirst( $invoice->get_invoice_quote_type() )
172
				),
173
				'GetPaid_Meta_Box_Invoice_Items::output',
174
				$post_type,
175
				'normal',
176
				'high'
177
			);
178
179
			// Invoice notes.
180
			add_meta_box(
181
				'wpinv-notes',
182
				sprintf(
183
					// translators: %s is the invoice type.
184
					__( '%s Notes', 'invoicing' ),
185
					ucfirst( $invoice->get_invoice_quote_type() )
186
				),
187
				'WPInv_Meta_Box_Notes::output',
188
				$post_type,
189
				'side',
190
				'low'
191
			);
192
193
			// Shipping Address.
194
			if ( get_post_meta( $invoice->get_id(), 'shipping_address', true ) ) {
195
				add_meta_box( 'wpinv-invoice-shipping-details', __( 'Shipping Address', 'invoicing' ), 'GetPaid_Meta_Box_Invoice_Shipping_Address::output', $post_type, 'side', 'high' );
196
			}
197
198
			// Payment form information.
199
			if ( get_post_meta( $invoice->get_id(), 'payment_form_data', true ) ) {
200
				add_meta_box( 'wpinv-invoice-payment-form-details', __( 'Payment Form Details', 'invoicing' ), 'WPInv_Meta_Box_Payment_Form::output_details', $post_type, 'side', 'high' );
201
			}
202
}
203
204
	}
205
206
	/**
207
	 * Remove some metaboxes.
208
	 */
209
	public static function remove_meta_boxes() {
210
		remove_meta_box( 'wpseo_meta', 'wpi_invoice', 'normal' );
211
		remove_meta_box( 'postexcerpt', 'wpi_item', 'normal' );
212
	}
213
214
	/**
215
	 * Rename other metaboxes.
216
	 */
217
	public static function rename_meta_boxes() {
218
219
	}
220
221
	/**
222
	 * Check if we're saving, then trigger an action based on the post type.
223
	 *
224
	 * @param  int    $post_id Post ID.
225
	 * @param  object $post Post object.
226
	 */
227
	public static function save_meta_boxes( $post_id, $post ) {
228
		$post_id = absint( $post_id );
229
		$data    = wp_kses_post_deep( wp_unslash( $_POST ) );
230
231
		// Do not save for ajax requests.
232
		if ( ( defined( 'DOING_AJAX' ) && DOING_AJAX ) || isset( $_REQUEST['bulk_edit'] ) ) {
233
			return;
234
		}
235
236
		// $post_id and $post are required
237
		if ( empty( $post_id ) || empty( $post ) || self::$saved_meta_boxes ) {
238
			return;
239
		}
240
241
		// Dont' save meta boxes for revisions or autosaves.
242
		if ( ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) || is_int( wp_is_post_revision( $post ) ) || is_int( wp_is_post_autosave( $post ) ) ) {
243
			return;
244
		}
245
246
		// Check the nonce.
247
		if ( empty( $data['getpaid_meta_nonce'] ) || ! wp_verify_nonce( $data['getpaid_meta_nonce'], 'getpaid_meta_nonce' ) ) {
248
			return;
249
		}
250
251
		// Check the post being saved == the $post_id to prevent triggering this call for other save_post events.
252
		if ( empty( $data['post_ID'] ) || absint( $data['post_ID'] ) !== $post_id ) {
253
			return;
254
		}
255
256
		// Check user has permission to edit.
257
		if ( ! current_user_can( 'edit_post', $post_id ) ) {
258
			return;
259
		}
260
261
		if ( getpaid_is_invoice_post_type( $post->post_type ) ) {
262
263
			// We need this save event to run once to avoid potential endless loops.
264
			self::$saved_meta_boxes = true;
265
266
			return GetPaid_Meta_Box_Invoice_Address::save( $post_id, wp_kses_post_deep( $_POST ) );
0 ignored issues
show
Are you sure the usage of GetPaid_Meta_Box_Invoice...kses_post_deep($_POST)) targeting GetPaid_Meta_Box_Invoice_Address::save() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
It seems like wp_kses_post_deep($_POST) can also be of type object; however, parameter $posted of GetPaid_Meta_Box_Invoice_Address::save() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

266
			return GetPaid_Meta_Box_Invoice_Address::save( $post_id, /** @scrutinizer ignore-type */ wp_kses_post_deep( $_POST ) );
Loading history...
267
268
		}
269
270
		// Ensure this is our post type.
271
		$post_types_map = array(
272
			'wpi_item'         => 'GetPaid_Meta_Box_Item_Details',
273
			'wpi_payment_form' => 'GetPaid_Meta_Box_Payment_Form',
274
			'wpi_discount'     => 'GetPaid_Meta_Box_Discount_Details',
275
		);
276
277
		// Is this our post type?
278
		if ( ! isset( $post_types_map[ $post->post_type ] ) ) {
279
			return;
280
		}
281
282
		// We need this save event to run once to avoid potential endless loops.
283
		self::$saved_meta_boxes = true;
284
285
		// Save the post.
286
		$class = $post_types_map[ $post->post_type ];
287
		$class::save( $post_id, wp_kses_post_deep( $_POST ), $post );
288
289
	}
290
291
}
292