This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
1 | <?php |
||||
2 | /** |
||||
3 | * GetPaid Anonymization Logs Admin |
||||
4 | * |
||||
5 | * @package GetPaid |
||||
6 | * @subpackage Admin |
||||
7 | * @since 2.8.22 |
||||
8 | */ |
||||
9 | |||||
10 | defined( 'ABSPATH' ) || exit; |
||||
11 | |||||
12 | /** |
||||
13 | * GetPaid_Anonymization_Logs Class |
||||
14 | */ |
||||
15 | class GetPaid_Anonymization_Logs { |
||||
16 | |||||
17 | /** |
||||
18 | * Anonymization logs page |
||||
19 | */ |
||||
20 | public function display_logs() { |
||||
21 | // Check user capabilities |
||||
22 | if ( ! current_user_can( 'manage_options' ) ) { |
||||
23 | return; |
||||
24 | } |
||||
25 | |||||
26 | // Get current page number |
||||
27 | $page = isset( $_GET['paged'] ) ? absint( $_GET['paged'] ) : 1; |
||||
28 | $per_page = 20; |
||||
29 | |||||
30 | // Fetch logs |
||||
31 | $logs = $this->get_logs( $page, $per_page ); |
||||
32 | $total_logs = $this->get_total_logs(); |
||||
33 | |||||
34 | // Prepare pagination |
||||
35 | $pagination = paginate_links( |
||||
36 | array( |
||||
0 ignored issues
–
show
|
|||||
37 | 'base' => add_query_arg( 'paged', '%#%' ), |
||||
38 | 'format' => '', |
||||
39 | 'prev_text' => __( '«', 'invoicing' ), |
||||
40 | 'next_text' => __( '»', 'invoicing' ), |
||||
41 | 'total' => ceil( $total_logs / $per_page ), |
||||
42 | 'current' => $page, |
||||
43 | ) |
||||
44 | ); |
||||
45 | |||||
46 | ?> |
||||
47 | <div class="wrap getpaid-anonymization-logs"> |
||||
48 | <h1><?php echo esc_html( get_admin_page_title() ); ?></h1> |
||||
49 | <div class="tablenav top"> |
||||
50 | <div class="alignleft actions"> |
||||
51 | <form method="get"> |
||||
52 | <input type="hidden" name="page" value="wpinv-anonymization-logs"> |
||||
53 | <label for="filter-by-date" class="screen-reader-text"><?php _e( 'Filter by date', 'invoicing' ); ?></label> |
||||
54 | <select name="m" id="filter-by-date"> |
||||
55 | <option value="0"><?php _e( 'All dates', 'invoicing' ); ?></option> |
||||
56 | <?php |
||||
57 | $months = $this->get_log_months(); |
||||
58 | foreach ( $months as $month ) { |
||||
59 | $selected = ( isset( $_GET['m'] ) && $_GET['m'] == $month->month ) ? ' selected="selected"' : ''; |
||||
60 | echo '<option value="' . esc_attr( $month->month ) . '"' . $selected . '>' . esc_html( $month->month_name . ' ' . $month->year ) . '</option>'; |
||||
61 | } |
||||
62 | ?> |
||||
63 | </select> |
||||
64 | <?php submit_button( __( 'Filter', 'invoicing' ), '', 'filter_action', false ); ?> |
||||
65 | </form> |
||||
66 | </div> |
||||
67 | </div> |
||||
68 | <table class="wp-list-table widefat fixed striped"> |
||||
69 | <thead> |
||||
70 | <tr> |
||||
71 | <th><?php _e( 'Log ID', 'invoicing' ); ?></th> |
||||
72 | <th><?php _e( 'User', 'invoicing' ); ?></th> |
||||
73 | <th><?php _e( 'Action', 'invoicing' ); ?></th> |
||||
74 | <th><?php _e( 'Date', 'invoicing' ); ?></th> |
||||
75 | <th><?php _e( 'Details', 'invoicing' ); ?></th> |
||||
76 | </tr> |
||||
77 | </thead> |
||||
78 | <tbody> |
||||
79 | <?php if ( empty( $logs ) ) : ?> |
||||
80 | <tr> |
||||
81 | <td colspan="5"><?php _e( 'No anonymization logs found.', 'invoicing' ); ?></td> |
||||
82 | </tr> |
||||
83 | <?php else : ?> |
||||
84 | <?php |
||||
85 | foreach ( $logs as $log ) : |
||||
86 | $additional_info = json_decode( $log->additional_info, true ); |
||||
87 | ?> |
||||
88 | <tr> |
||||
89 | <td><?php echo esc_html( $log->log_id ); ?></td> |
||||
90 | <td> |
||||
91 | <?php |
||||
92 | $user_edit_link = get_edit_user_link( $log->user_id ); |
||||
93 | if ( $user_edit_link ) { |
||||
94 | echo '<a href="' . esc_url( $user_edit_link ) . '">' . esc_html( $log->user_id ) . '</a>'; |
||||
95 | } else { |
||||
96 | echo esc_html( $log->user_id ); |
||||
97 | } |
||||
98 | ?> |
||||
99 | </td> |
||||
100 | <td><?php echo esc_html( ucfirst( $log->action ) ); ?></td> |
||||
101 | <td><?php echo esc_html( get_date_from_gmt( $log->timestamp, 'F j, Y g:i a' ) ); ?></td> |
||||
102 | <td> |
||||
103 | <button class="button-link toggle-details" type="button" aria-expanded="false"> |
||||
104 | <span class="screen-reader-text"><?php _e( 'Show more details', 'invoicing' ); ?></span> |
||||
105 | <span class="dashicons dashicons-arrow-down-alt2"></span> |
||||
106 | </button> |
||||
107 | </td> |
||||
108 | </tr> |
||||
109 | <tr class="log-details" style="display:none;"> |
||||
110 | <td colspan="5"> |
||||
111 | <div class="log-details-content"> |
||||
112 | <table class="widefat fixed"> |
||||
113 | <tbody> |
||||
114 | <tr> |
||||
115 | <th><?php _e( 'Data Type', 'invoicing' ); ?></th> |
||||
116 | <td><?php echo esc_html( $log->data_type ); ?></td> |
||||
117 | </tr> |
||||
118 | <?php if ( is_array( $additional_info ) ) : ?> |
||||
119 | <tr> |
||||
120 | <th><?php _e( 'Additional Information', 'invoicing' ); ?></th> |
||||
121 | <td> |
||||
122 | <table class="widefat fixed"> |
||||
123 | <tbody> |
||||
124 | <?php foreach ( $additional_info as $key => $value ) : ?> |
||||
125 | <tr> |
||||
126 | <th><?php echo esc_html( $key ); ?></th> |
||||
127 | <td><?php echo esc_html( $value ); ?></td> |
||||
128 | </tr> |
||||
129 | <?php endforeach; ?> |
||||
130 | </tbody> |
||||
131 | </table> |
||||
132 | </td> |
||||
133 | </tr> |
||||
134 | <?php endif; ?> |
||||
135 | </tbody> |
||||
136 | </table> |
||||
137 | </div> |
||||
138 | </td> |
||||
139 | </tr> |
||||
140 | <?php endforeach; ?> |
||||
141 | <?php endif; ?> |
||||
142 | </tbody> |
||||
143 | </table> |
||||
144 | <?php if ( $pagination ) : ?> |
||||
145 | <div class="tablenav bottom"> |
||||
146 | <div class="tablenav-pages"> |
||||
147 | <?php echo $pagination; ?> |
||||
0 ignored issues
–
show
Are you sure
$pagination of type string|string[] can be used in echo ?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() Security
Cross-Site Scripting
introduced
by
$pagination can contain request data and is used in output context(s) leading to a potential security vulnerability.
2 paths for user data to reach this point
1. Path:
Read tainted data from array, and
$_SERVER['REQUEST_URI'] is assigned to $uri
in wordpress/wp-includes/functions.php on line 1132
2. Path:
Read tainted data from array, and
$_SERVER['REQUEST_URI'] is assigned to $uri
in wordpress/wp-includes/functions.php on line 1138
Preventing Cross-Site-Scripting AttacksCross-Site-Scripting allows an attacker to inject malicious code into your website - in particular Javascript code, and have that code executed with the privileges of a visiting user. This can be used to obtain data, or perform actions on behalf of that visiting user. In order to prevent this, make sure to escape all user-provided data:
// for HTML
$sanitized = htmlentities($tainted, ENT_QUOTES);
// for URLs
$sanitized = urlencode($tainted);
General Strategies to prevent injectionIn general, it is advisable to prevent any user-data to reach this point. This can be done by white-listing certain values:
if ( ! in_array($value, array('this-is-allowed', 'and-this-too'), true)) {
throw new \InvalidArgumentException('This input is not allowed.');
}
For numeric data, we recommend to explicitly cast the data: $sanitized = (integer) $tainted;
![]() |
|||||
148 | </div> |
||||
149 | </div> |
||||
150 | <?php endif; ?> |
||||
151 | </div> |
||||
152 | <?php |
||||
153 | } |
||||
154 | |||||
155 | /** |
||||
156 | * Get logs from the database |
||||
157 | * |
||||
158 | * @param int $page Current page number |
||||
159 | * @param int $per_page Number of logs per page |
||||
160 | * @return array |
||||
161 | */ |
||||
162 | private function get_logs( $page, $per_page ) { |
||||
163 | global $wpdb; |
||||
164 | $table_name = $wpdb->prefix . 'getpaid_anonymization_logs'; |
||||
165 | $offset = ( $page - 1 ) * $per_page; |
||||
166 | |||||
167 | $query = $wpdb->prepare( |
||||
168 | "SELECT * FROM $table_name ORDER BY timestamp DESC LIMIT %d OFFSET %d", |
||||
169 | $per_page, |
||||
170 | $offset |
||||
171 | ); |
||||
172 | |||||
173 | return $wpdb->get_results( $query ); |
||||
174 | } |
||||
175 | |||||
176 | /** |
||||
177 | * Get total number of logs |
||||
178 | * |
||||
179 | * @return int |
||||
180 | */ |
||||
181 | private function get_total_logs() { |
||||
182 | global $wpdb; |
||||
183 | $table_name = $wpdb->prefix . 'getpaid_anonymization_logs'; |
||||
184 | return $wpdb->get_var( "SELECT COUNT(*) FROM $table_name" ); |
||||
185 | } |
||||
186 | |||||
187 | /** |
||||
188 | * Get log months for filtering |
||||
189 | * |
||||
190 | * @return array |
||||
191 | */ |
||||
192 | private function get_log_months() { |
||||
193 | global $wpdb; |
||||
194 | $table_name = $wpdb->prefix . 'getpaid_anonymization_logs'; |
||||
195 | |||||
196 | $months = $wpdb->get_results( |
||||
197 | "SELECT DISTINCT YEAR(timestamp) AS year, MONTH(timestamp) AS month, |
||||
198 | DATE_FORMAT(timestamp, '%M') AS month_name, |
||||
199 | DATE_FORMAT(timestamp, '%Y%m') AS month |
||||
200 | FROM $table_name |
||||
201 | ORDER BY year DESC, month DESC" |
||||
202 | ); |
||||
203 | |||||
204 | return $months; |
||||
205 | } |
||||
206 | } |
array('base' => add_quer...e), 'current' => $page)
can contain request data and is used in variable name context(s) leading to a potential security vulnerability.2 paths for user data to reach this point
$_SERVER['REQUEST_URI']
is assigned to$uri
in wordpress/wp-includes/functions.php on line 1132$_SERVER['REQUEST_URI']
is assigned to$uri
in wordpress/wp-includes/functions.php on line 1132
$uri . '?'
is assigned to$base
in wordpress/wp-includes/functions.php on line 1165
$protocol . $base . $ret . $frag
is assigned to$ret
in wordpress/wp-includes/functions.php on line 1191
rtrim()
, andrtrim($ret, '?')
is assigned to$ret
in wordpress/wp-includes/functions.php on line 1192
str_replace()
, andstr_replace('?#', '#', $ret)
is assigned to$ret
in wordpress/wp-includes/functions.php on line 1193
$ret
is returnedin wordpress/wp-includes/functions.php on line 1194
$_SERVER['REQUEST_URI']
is assigned to$uri
in wordpress/wp-includes/functions.php on line 1138$_SERVER['REQUEST_URI']
is assigned to$uri
in wordpress/wp-includes/functions.php on line 1138
$uri . '?'
is assigned to$base
in wordpress/wp-includes/functions.php on line 1165
$protocol . $base . $ret . $frag
is assigned to$ret
in wordpress/wp-includes/functions.php on line 1191
rtrim()
, andrtrim($ret, '?')
is assigned to$ret
in wordpress/wp-includes/functions.php on line 1192
str_replace()
, andstr_replace('?#', '#', $ret)
is assigned to$ret
in wordpress/wp-includes/functions.php on line 1193
$ret
is returnedin wordpress/wp-includes/functions.php on line 1194
Used in variable context
paginate_links()
is calledin includes/admin/class-getpaid-anonymization-logs.php on line 36
$args
in wordpress/wp-includes/general-template.php on line 4469
wp_parse_args()
is calledin wordpress/wp-includes/general-template.php on line 4506
$args
in wordpress/wp-includes/functions.php on line 4821
wp_parse_str()
is calledin wordpress/wp-includes/functions.php on line 4827
$input_string
in wordpress/wp-includes/formatting.php on line 5148
parse_str()
is calledin wordpress/wp-includes/formatting.php on line 5149
General Strategies to prevent injection
In general, it is advisable to prevent any user-data to reach this point. This can be done by white-listing certain values:
For numeric data, we recommend to explicitly cast the data: