Session Fixation is a security vulnerability where an attacker “fixes” a user’s session ID before the user even logs in. If the application doesn’t change the session ID upon authentication, the attacker can use that pre-set ID to hijack the user’s account. Attacker visits target website and obtains valid session ID. Attacker traps victim to login with that session ID. http://example.com/?PHPSESSID=123. Because the server did not issue a new session ID after login, the old ID (123) is now associated with the victim’s authenticated account. Modern WordPress (version 4.0 and later) has moved away from standard PHP native sessions (PHPSESSID) and implemented a much more robust system that specifically defends against fixation. WordPress uses a custom session manager. When a user logs in, WordPress generates a brand-new, random Session Token. Even if an attacker managed to plant a cookie on a user’s browser beforehand, that cookie is ignored or overwritten during the wp_signon() process. Session token stored in wp_usermeta table for that user. WordPress then sends that token to your browser wrapped inside a cookie (typically named wordpress_logged_in_[hash]). Primitive Capabilities: These are “hard” permissions stored in the database for a specific role (e.g., edit_posts, manage_options). They are a simple “Yes” or “No.” Meta Capabilities: These are “contextual” permissions that depend on a specific object, usually a Post ID (e.g., edit_post, delete_post).**** When you call current_user_can('edit_post', 123), WordPress runs map_meta_cap. If Post 123 belongs to the current user, it maps the request to the primitive edit_posts. If Post 123 belongs to someone else, it maps it to edit_others_posts. /** * Custom Permission Logic: * Allow users to edit a post if they are the "Project Lead" * via a custom meta field. */ add_filter( 'map_meta_cap', 'my_custom_project_permissions', 10, 4 ); function my_custom_project_permissions( $caps, $cap, $user_id, $args ) { // 1. Target the specific meta capability if ( 'edit_post' === $cap || 'delete_post' === $cap ) { $post_id = $args[0]; // The ID of the post being checked $post_type = get_post_type( $post_id ); // 2. Only apply logic to our 'project' post type if ( 'project' === $post_type ) { // Fetch the assigned "Lead" from post meta $project_lead_id = get_post_meta( $post_id, '_project_lead_id', true ); // 3. If the current user is the Lead, give them the 'exist' capability // 'exist' is a primitive cap everyone has, effectively granting permission. if ( (int) $project_lead_id === (int) $user_id ) { return array( 'exist' ); } } } // Return the original capabilities for all other cases return $caps; } Never return an empty array if you want to deny access. If you return an empty array, WordPress assumes no primitive capabilities are required, and the check will pass! To deny access, you should return a capability that you know the user doesn’t have, such as 'do_not_allow'.
...