You've already forked wp-prometheus
security: Fix XSS, insecure token generation, and harden import/export (v0.4.9)
Security audit findings addressed: - Replace jQuery .html() with safe .text() DOM construction (XSS prevention) - Use crypto.getRandomValues() instead of Math.random() for token generation - Add 1MB import size limit to prevent DoS via large JSON payloads - Remove site_url from metric exports (information disclosure) - Add import mode allowlist validation Refactoring: - Extract shared wp_prometheus_authenticate_request() function (DRY) - Extract showNotice() helper in admin.js (DRY) - Extract is_hpos_enabled() helper in Collector (DRY) Performance: - Optimize WooCommerce product counting with paginate COUNT query Housekeeping: - Add missing options to Installer::uninstall() cleanup Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -235,31 +235,19 @@
|
||||
$spinner.removeClass('is-active');
|
||||
|
||||
if (response.success) {
|
||||
$message
|
||||
.removeClass('notice-error')
|
||||
.addClass('notice notice-success')
|
||||
.html('<p>' + response.data.message + '</p>')
|
||||
.show();
|
||||
showNotice($message, response.data.message, 'success');
|
||||
|
||||
// Reload page after successful validation/activation.
|
||||
setTimeout(function() {
|
||||
location.reload();
|
||||
}, 1500);
|
||||
} else {
|
||||
$message
|
||||
.removeClass('notice-success')
|
||||
.addClass('notice notice-error')
|
||||
.html('<p>' + (response.data.message || 'An error occurred.') + '</p>')
|
||||
.show();
|
||||
showNotice($message, response.data.message || 'An error occurred.', 'error');
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
$spinner.removeClass('is-active');
|
||||
$message
|
||||
.removeClass('notice-success')
|
||||
.addClass('notice notice-error')
|
||||
.html('<p>Connection error. Please try again.</p>')
|
||||
.show();
|
||||
showNotice($message, 'Connection error. Please try again.', 'error');
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -287,30 +275,18 @@
|
||||
$spinner.removeClass('is-active');
|
||||
|
||||
if (response.success) {
|
||||
$message
|
||||
.removeClass('notice-error')
|
||||
.addClass('notice notice-success')
|
||||
.html('<p>' + response.data.message + '</p>')
|
||||
.show();
|
||||
showNotice($message, response.data.message, 'success');
|
||||
|
||||
setTimeout(function() {
|
||||
window.location.href = window.location.pathname + '?page=wp-prometheus&tab=custom';
|
||||
}, 1000);
|
||||
} else {
|
||||
$message
|
||||
.removeClass('notice-success')
|
||||
.addClass('notice notice-error')
|
||||
.html('<p>' + (response.data.message || 'An error occurred.') + '</p>')
|
||||
.show();
|
||||
showNotice($message, response.data.message || 'An error occurred.', 'error');
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
$spinner.removeClass('is-active');
|
||||
$message
|
||||
.removeClass('notice-success')
|
||||
.addClass('notice notice-error')
|
||||
.html('<p>Connection error. Please try again.</p>')
|
||||
.show();
|
||||
showNotice($message, 'Connection error. Please try again.', 'error');
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -398,11 +374,7 @@
|
||||
$spinner.removeClass('is-active');
|
||||
|
||||
if (response.success) {
|
||||
$message
|
||||
.removeClass('notice-error')
|
||||
.addClass('notice notice-success')
|
||||
.html('<p>' + response.data.message + '</p>')
|
||||
.show();
|
||||
showNotice($message, response.data.message, 'success');
|
||||
|
||||
$('#import-options').slideUp();
|
||||
$('#import-metrics-file').val('');
|
||||
@@ -412,20 +384,12 @@
|
||||
location.reload();
|
||||
}, 1500);
|
||||
} else {
|
||||
$message
|
||||
.removeClass('notice-success')
|
||||
.addClass('notice notice-error')
|
||||
.html('<p>' + (response.data.message || 'An error occurred.') + '</p>')
|
||||
.show();
|
||||
showNotice($message, response.data.message || 'An error occurred.', 'error');
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
$spinner.removeClass('is-active');
|
||||
$message
|
||||
.removeClass('notice-success')
|
||||
.addClass('notice notice-error')
|
||||
.html('<p>Connection error. Please try again.</p>')
|
||||
.show();
|
||||
showNotice($message, 'Connection error. Please try again.', 'error');
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -478,26 +442,14 @@
|
||||
$spinner.removeClass('is-active');
|
||||
|
||||
if (response.success) {
|
||||
$message
|
||||
.removeClass('notice-error')
|
||||
.addClass('notice notice-success')
|
||||
.html('<p>' + response.data.message + '</p>')
|
||||
.show();
|
||||
showNotice($message, response.data.message, 'success');
|
||||
} else {
|
||||
$message
|
||||
.removeClass('notice-success')
|
||||
.addClass('notice notice-error')
|
||||
.html('<p>' + (response.data.message || 'An error occurred.') + '</p>')
|
||||
.show();
|
||||
showNotice($message, response.data.message || 'An error occurred.', 'error');
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
$spinner.removeClass('is-active');
|
||||
$message
|
||||
.removeClass('notice-success')
|
||||
.addClass('notice notice-error')
|
||||
.html('<p>Connection error. Please try again.</p>')
|
||||
.show();
|
||||
showNotice($message, 'Connection error. Please try again.', 'error');
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -546,15 +498,30 @@
|
||||
// Remove all inputs except the value and button.
|
||||
$row.find('input').remove();
|
||||
|
||||
// Re-add label inputs.
|
||||
// Re-add label inputs using safe DOM construction.
|
||||
for (var i = 0; i < labelCount; i++) {
|
||||
var val = currentValues[i] || '';
|
||||
$row.prepend('<input type="text" name="label_values[' + rowIndex + '][]" class="small-text" placeholder="' + (labels[i] || 'value') + '" value="' + val + '">');
|
||||
var $input = $('<input>', {
|
||||
type: 'text',
|
||||
name: 'label_values[' + rowIndex + '][]',
|
||||
'class': 'small-text',
|
||||
placeholder: labels[i] || 'value',
|
||||
value: val
|
||||
});
|
||||
$row.prepend($input);
|
||||
}
|
||||
|
||||
// Re-add value input.
|
||||
// Re-add value input using safe DOM construction.
|
||||
var metricVal = currentValues[currentValues.length - 1] || '';
|
||||
$row.find('.remove-value-row').before('<input type="number" name="label_values[' + rowIndex + '][]" class="small-text" step="any" placeholder="Value" value="' + metricVal + '">');
|
||||
var $valueInput = $('<input>', {
|
||||
type: 'number',
|
||||
name: 'label_values[' + rowIndex + '][]',
|
||||
'class': 'small-text',
|
||||
step: 'any',
|
||||
placeholder: 'Value',
|
||||
value: metricVal
|
||||
});
|
||||
$row.find('.remove-value-row').before($valueInput);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -584,7 +551,7 @@
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a random token.
|
||||
* Generate a cryptographically secure random token.
|
||||
*
|
||||
* @param {number} length Token length.
|
||||
* @return {string} Generated token.
|
||||
@@ -592,12 +559,31 @@
|
||||
function generateToken(length) {
|
||||
var charset = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
|
||||
var token = '';
|
||||
var randomValues = new Uint32Array(length);
|
||||
window.crypto.getRandomValues(randomValues);
|
||||
for (var i = 0; i < length; i++) {
|
||||
token += charset.charAt(Math.floor(Math.random() * charset.length));
|
||||
token += charset.charAt(randomValues[i] % charset.length);
|
||||
}
|
||||
return token;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a notice message safely (XSS-safe).
|
||||
*
|
||||
* @param {jQuery} $element The message container element.
|
||||
* @param {string} message The message text.
|
||||
* @param {string} type Notice type: 'success', 'error', or 'warning'.
|
||||
*/
|
||||
function showNotice($element, message, type) {
|
||||
var removeClasses = 'notice-error notice-success notice-warning';
|
||||
$element
|
||||
.removeClass(removeClasses)
|
||||
.addClass('notice notice-' + type)
|
||||
.empty()
|
||||
.append($('<p>').text(message))
|
||||
.show();
|
||||
}
|
||||
|
||||
/**
|
||||
* Download a file.
|
||||
*
|
||||
@@ -666,12 +652,8 @@
|
||||
$spinner.removeClass('is-active');
|
||||
|
||||
if (response.success) {
|
||||
var noticeClass = response.data.warning ? 'notice-warning' : 'notice-success';
|
||||
$message
|
||||
.removeClass('notice-error notice-success notice-warning')
|
||||
.addClass('notice ' + noticeClass)
|
||||
.html('<p>' + response.data.message + '</p>')
|
||||
.show();
|
||||
var type = response.data.warning ? 'warning' : 'success';
|
||||
showNotice($message, response.data.message, type);
|
||||
|
||||
if (!response.data.warning) {
|
||||
setTimeout(function() {
|
||||
@@ -679,20 +661,12 @@
|
||||
}, 1500);
|
||||
}
|
||||
} else {
|
||||
$message
|
||||
.removeClass('notice-success notice-warning')
|
||||
.addClass('notice notice-error')
|
||||
.html('<p>' + (response.data.message || 'An error occurred.') + '</p>')
|
||||
.show();
|
||||
showNotice($message, response.data.message || 'An error occurred.', 'error');
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
$spinner.removeClass('is-active');
|
||||
$message
|
||||
.removeClass('notice-success notice-warning')
|
||||
.addClass('notice notice-error')
|
||||
.html('<p>Connection error. Please try again.</p>')
|
||||
.show();
|
||||
showNotice($message, 'Connection error. Please try again.', 'error');
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -720,26 +694,14 @@
|
||||
$spinner.removeClass('is-active');
|
||||
|
||||
if (response.success) {
|
||||
$message
|
||||
.removeClass('notice-error notice-warning')
|
||||
.addClass('notice notice-success')
|
||||
.html('<p>' + response.data.message + '</p>')
|
||||
.show();
|
||||
showNotice($message, response.data.message, 'success');
|
||||
} else {
|
||||
$message
|
||||
.removeClass('notice-success notice-warning')
|
||||
.addClass('notice notice-error')
|
||||
.html('<p>' + (response.data.message || 'Connection test failed.') + '</p>')
|
||||
.show();
|
||||
showNotice($message, response.data.message || 'Connection test failed.', 'error');
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
$spinner.removeClass('is-active');
|
||||
$message
|
||||
.removeClass('notice-success notice-warning')
|
||||
.addClass('notice notice-error')
|
||||
.html('<p>Connection error. Please try again.</p>')
|
||||
.show();
|
||||
showNotice($message, 'Connection error. Please try again.', 'error');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user