SEO Forge follows WordPress security best practices. This section documents the security model for developers building integrations.
REST API Authentication
All REST endpoints require edit_posts capability. This is enforced via the permission_callback on each route registration:
php
// SEO Forge registers routes like this internally:
register_rest_route( 'seoforge/v1', '/analyze/(?P<id>d+)', [
'methods' => 'GET',
'callback' => [ $this, 'analyze' ],
'permission_callback' => function () {
return current_user_can( 'edit_posts' );
},
] );Input Sanitization
All meta field writes go through sanitize_text_field() or wp_kses_post():
php
// SEO Forge sanitizes meta before saving
$title = sanitize_text_field( $_POST['seoforge_meta_title'] ?? '' );
$desc = sanitize_text_field( $_POST['seoforge_meta_description'] ?? '' );
$keyword = sanitize_text_field( $_POST['seoforge_focus_keyword'] ?? '' );Nonce Verification
The metabox save handler verifies a nonce before processing any data:
php
// When saving custom meta alongside SEO Forge, always verify your own nonce
add_action( 'save_post', function ( $post_id ) {
if ( ! isset( $_POST['my_addon_nonce'] ) || ! wp_verify_nonce( $_POST['my_addon_nonce'], 'my_addon_save' ) ) {
return;
}
// Safe to process
}, 25 );Manual Schema Sanitization
When writing manual JSON-LD schema, always sanitize:
php
// Sanitize manual schema JSON before storing
$json = wp_unslash( $_POST['manual_schema'] ?? '' );
$decoded = json_decode( $json, true );
if ( json_last_error() !== JSON_ERROR_NONE ) {
// Invalid JSON -- reject
return;
}
// Re-encode to normalize (removes any extra whitespace or formatting)
$clean = wp_json_encode( $decoded, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE );
update_post_meta( $post_id, '_seoforge_manual_schema', $clean );Capability Checks for Redirects
Redirect management requires manage_options capability (administrators only):
php
if ( ! current_user_can( 'manage_options' ) ) {
wp_die( 'Unauthorized' );
}
$redirects = SEOFORGE_Redirects::instance();
$redirects->add( 'old-url', 'https://example.com/new-url/', 301, false );—