Fix unauthenticated SQL injection on the push REST endpoint (CVE-2026-15162) - #572
Merged
jonathanstegall merged 1 commit intoAug 17, 2026
Conversation
…-15162) The `/wp-json/object-sync-for-salesforce/push` route's permission callback (`Object_Sync_Sf_Rest::can_process()`) only validates the HTTP method, so the endpoint is reachable by unauthenticated callers. The `wordpress_object_type` body parameter then flows unsanitized through `process()` -> `manual_push()` -> `get_wordpress_object_data()` -> `get_wordpress_table_structure()`, where for post / attachment / custom-post-type objects it is concatenated directly into the `post_type` WHERE clause. That clause is later executed without `$wpdb->prepare()` in `object_fields()`, allowing blind SQL injection and data exfiltration with only a valid `wordpress_id`. Fix: - Bind the object type via `$wpdb->prepare( ... %s )` in all three post-type WHERE clauses in `get_wordpress_table_structure()` (root cause). - Reject object types that are not registered WordPress objects at the REST boundary in `Object_Sync_Sf_Rest::process()` before they reach the database layer (defense in depth for the unauthenticated endpoint). Refs: CVE-2026-15162, MinnPost#571
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #571.
The vulnerability (CVE-2026-15162)
The
/wp-json/object-sync-for-salesforce/pushREST route is exploitable by unauthenticated callers. Its permission callback,Object_Sync_Sf_Rest::can_process(), only checks the HTTP method for thepush(andpull) classes — no capability or nonce check:The
wordpress_object_typebody parameter then flows, unsanitized, through:process()→Object_Sync_Sf_Salesforce_Push::manual_push()→Object_Sync_Sf_WordPress::get_wordpress_object_data()→get_wordpress_table_structure()where, for
post/attachment/ custom-post-type objects, it is concatenated directly into thepost_typeWHERE clause:That
wherestring is later executed without$wpdb->prepare()inobject_fields():Result: an unauthenticated request with a crafted
wordpress_object_typeand any validwordpress_idyields blind SQL injection / data exfiltration.The fix
%sparameter via$wpdb->prepare()in all three post-type WHERE clauses inget_wordpress_table_structure(). The user-controlled value can no longer break out of the string literal.wordpress_object_typethat is not a registered WordPress object type (get_object_types()) at the REST boundary inprocess(), returning400, so untrusted input never reaches the database layer on this unauthenticated endpoint.Legitimate callers are unaffected: real object types (
user,post, registered CPTs, etc.) pass the allow-list, and$wpdb->prepare()produces the same query for valid post-type names.Verification
php -lclean on both changed files.$wpdb->prepare( 'AND ' . $wpdb->prefix . 'posts.post_type = %s', 'cpt" OR 1=1 -- -' )producesAND wp_posts.post_type = 'cpt\" OR 1=1 -- -'— the payload is an inert quoted literal.POST /wp-json/object-sync-for-salesforce/pushcarrying an injection string aswordpress_object_typereturns400 Invalid WordPress object typeinstead of executing SQL.Happy to add a
changelog.md/ readme entry or adjust the approach (e.g. tighteningcan_process()instead of / in addition to the allow-list) if you'd prefer.