Recommended Free Tools
iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more
Antihost offers managed WordPress hosting with free migration, one-click staging and a 14-day free trial.
Prevent SQL injection in WordPress by avoiding hand-written SQL whenever a native WordPress API can perform the operation. When custom SQL is necessary, normalize input to the type you expect, put every data value in a matching $wpdb->prepare() placeholder, and build identifiers or SQL keywords only from fixed allowlists.
esc_sql() is not a substitute for prepared statements. WordPress also requires version-aware code: the %i identifier placeholder was added in WordPress 6.2.0, while older supported versions require an allowlist for table and column names.
What SQL injection means in a WordPress site
SQL injection occurs when request data is allowed to alter the SQL statement rather than being treated solely as data. A vulnerable plugin, theme, AJAX handler, REST endpoint, or administrative tool may concatenate a query string with values supplied through a URL, form, cookie, or API request. The resulting statement can return unintended rows or modify data, depending on the account and database privileges used by the site.
WordPress does not make custom SQL automatically safe. The $wpdb abstraction gives plugins and themes a consistent database interface, but the developer still has to escape every value correctly and keep untrusted text out of SQL structure. WordPress’s database guidance states: “All data in SQL queries must be SQL-escaped before the SQL query is executed to prevent SQL injection attacks.”
#1 Best Overall
- Powerful Turbo Fan:CAGIWIRU Electric Air Duster have reached speed up to 130000RPM,Can efficient remove dust and debris.With LED light and Three Adjustable Speed to meet with different cleaning tasks.
- With Attached USB C Fasting Charging cable.Charing 3 hours,Enjoy up to 240 minutes of use on the lowest setting, For third speed can use for 25mins.with four charging options to meet with your needs.
- Wide Application:Upgraded attached 5 different nozzles,making it suitable for a variety of scenes, such as car,pet, pc, keyboards, and other electronic devices. It also serves for office and home clean duster.
- Handy Design & Portable:Cordless air duster electric nozzle is Light weight and small size, design and comfortable to hold and space saving, convenient to carry around. You can put it in your room or inside the car without taking up space.
- Warranty & Support: Our Electric air duster comes with 5 years warranty and 24/7 customer service. During this period, if you have any questions,pls kindly feel free to contact us.
The practical rule is simple: let WordPress construct the query when possible; otherwise, prepare it immediately before execution and separate values from the SQL grammar.
1. Use a native WordPress API first
The WordPress Theme Handbook gives the right starting point: “The first rule for hardening your theme against SQL Injection is: when there’s a WordPress function, use it.” Native APIs accept structured arguments and keep query construction inside code that WordPress maintains. They are preferable to reproducing that behavior with a custom SELECT, INSERT, UPDATE, or DELETE statement.
Before writing SQL, check whether the operation can be expressed with an established WordPress API, such as a query object or a function for posts, metadata, users, terms, or options. This also reduces the amount of table-specific code that must be reviewed when WordPress changes.
- Use the native API when it supports the records, filters, ordering, and pagination you need.
- Use
$wpdbonly for a genuinely custom query or a table that the native API does not expose. - Do not switch to custom SQL merely to avoid learning the API’s argument names.
2. Put every SQL value in a typed placeholder
For custom SQL, call $wpdb->prepare() and pass values as separate arguments. Placeholders must remain unquoted; prepare() applies the appropriate quoting and escaping for the placeholder type.
<?php
global $wpdb;
$user_id = absint( $_GET['user_id'] ?? 0 );
$status = sanitize_key( $_GET['status'] ?? 'publish' );
$sql = $wpdb->prepare(
"SELECT ID FROM {$wpdb->posts} WHERE post_author = %d AND post_status = %s",
$user_id,
$status
);
$ids = $wpdb->get_col( $sql );
In this example, $wpdb->posts is a WordPress-provided table reference, while the request values are passed through placeholders. The query is prepared before get_col() executes it.
| Placeholder | Use it for | Important constraint |
|---|---|---|
%s |
String values | Pass the value as an argument; do not put quotes around the placeholder. |
%d |
Integer values | Normalize or cast the input to an integer before building the query. |
%f |
Floating-point values | Use only where a decimal number is actually expected. |
%i |
Identifiers such as table or field names | Available in WordPress 6.2.0 and later; it is not interchangeable with %s. |
%% |
A literal percent sign in the SQL text | Use this when the percent character is part of the query itself rather than a placeholder. |
Never concatenate a request value into a value position and then assume that a later call to prepare() will repair it. The value must be represented by a placeholder from the start.
Free tools Windows power users keep installed
One-click scans. No signup required.
Rank #2
- Screen Cleaner is Your Screen’s New Bestfriend! - EVEO is proud to present a screen cleaner that’s perfectly suited for your TV. Meet your new screen cleaner, computer screen cleaner, laptop cleaner, iPad cleaner, Macbook,tv cleaner or any other electronic device. Our screen cleaner spray and wipe along with the included plush microfiber cloth, easily removes dust, fingerprints & other smudges on the screen’s surface. Clean effectively for a streak-free screen
- Gentle on your Screens - Our screen cleaner spray and wipes is compatible to be used even for the most sensitive LCD, LED, CRT, and OLED screens in proper use. Be at ease knowing that this product is compatible with all the major brands: LG, SONY, Samsung, Sharp, iPad, iPhone, Android screens, Kindle, PC monitors - we’ve got you covered! Can be used as LCD screen cleaner, tv cleaner, smart tv screen cleaner, and more
- Premium Super Soft Plush Microfiber Cloth - Included in this efficient screen cleaning kit. This screen cleaner spray and wipe has our signature plush microfiber cloth specially designed to comply with screens and monitors and leave them streak-free. Has been shown to effectively absorbs stubborn stains, zero streaks, and no fiber shedding. Always use this together with our screen cleaner for the best results
- Easy-to-Use Screen Cleaner Kit + microfiber cleaning cloth - The EVEO Screen Cleaning Kit will easily be your new favorite tool when it comes to taking care of the things you love most, quick and easy solution for a streak-free screen. Simply screw on the sprayer gun on the screen cleaner bottle. Spray the cleaning liquid onto the microfiber cloth, then wipe the screen until desired cleanliness & shine is achieved.
- Quality Screen Care Kit Worth Purchasing - Enjoy a convenient Screen Cleaner anytime, anywhere you need it. Your satisfaction is our top priority. We stand behind the quality of our products and that’s why, you shouldn’t be worrying at all. We manufacture the Best Screen Cleaner. and can be used for laptop cleaning kit, laptop screen cleaner, tv screen cleaner for smart tv. MacBook screen cleaner, monitor cleaner or screen cleaner spray for electronic devices with microfiber cleaning cloth
3. Normalize input before constructing the query
Preparation protects the SQL boundary; input normalization makes sure the value has the shape your application expects. Normalize as soon as the request enters your code, then pass the normalized value to prepare().
- Use
absint()for a non-negative integer such as a post or user ID. - Use a key-oriented normalization function such as
sanitize_key()for a constrained token such as a status code. - Do not rely on a browser control, hidden field, or JavaScript validation to enforce a type.
- Decide what an empty, missing, or invalid value means before querying: reject it, apply a documented default, or return no results.
Normalization is not a replacement for placeholders. A value that looks numeric or contains only letters still belongs in the matching placeholder.
4. Build a safe LIKE search
LIKE has a second escaping concern: the percent and underscore characters have wildcard meaning in the pattern. Escape the user’s search text with $wpdb->esc_like(), add the complete wildcard string to the argument, and then prepare the query.
<?php
global $wpdb;
$search_term = (string) ( $_GET['q'] ?? '' );
$needle = '%' . $wpdb->esc_like( $search_term ) . '%';
$sql = $wpdb->prepare(
"SELECT ID FROM {$wpdb->posts} WHERE post_title LIKE %s",
$needle
);
$ids = $wpdb->get_col( $sql );
The wildcard characters are part of the argument, not part of the SQL string. Do not write LIKE '%s'; placeholders are intended to stand alone, without surrounding quotes.
The Tool Desk
Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →5. Handle dynamic table and column names correctly
Values and identifiers are different categories. A post title is a value, but a table name, column name, sort direction, operator, and SQL keyword change the structure of the statement. A value placeholder such as %s cannot safely represent an identifier.
WordPress 6.2.0 and later: use %i
WordPress documents the %i placeholder for identifiers beginning with version 6.2.0. Use it when the site’s supported WordPress range includes that behavior.
Rank #3
- 【Large size】:Measuring 800 x 300 mm/ 31. 5×12 inches, which is wider and taller than others. Large mouse pad can perfectly fit your keyboard and mouse of any size, and there is also ample space for peripherals such as phones, tablets, etc.
- 【LED backlight mouse pad】:Blade Hawks RGB mouse pad provides 7 static modes and 7 dynamic modes will give you the options you are looking for. Power-off memory function remembers the last lighting mode you selected. The super glow fiber Chroma will give you a colorful gaming setup that you want.
- 【Anti-slip rubber base】:Made from Natural rubber, this gaming mousepad will firmly grip your desktop, allowing you to enjoy the ultimate precision in the games you are most passionate about. It also comes with a texture that enhances this ability even further.
- 【Smooth and waterproof surface】: Micro-textured cloth surface, for extremely precise mouse control and a smooth movement. When liquid splashes on the gaming mouse pad, it forms water droplets and slides down. Will not delay your work or gameplay.
- 【Plug and play】: This mouse and keyboard pad is powered by USB, plug and play, no driver required. One button control light modes. Press one time to change the lighting mode, press twice to change the brightness, press and hold about 3 seconds turn ON/OFF.
<?php
global $wpdb;
$column = 'post_date';
$sql = $wpdb->prepare(
"SELECT ID FROM {$wpdb->posts} ORDER BY %i DESC",
$column
);
$ids = $wpdb->get_col( $sql );
The identifier still should come from an application-controlled choice or an allowlist. %i provides identifier handling; it does not make an arbitrary request value an acceptable column.
When older WordPress versions must be supported
If your plugin or theme supports a version before 6.2.0, map the user’s choice to a fixed set of known names and interpolate only the mapped result. Never insert the raw request string.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
<?php
global $wpdb;
$columns = array(
'newest' => 'post_date',
'title' => 'post_title',
);
$key = sanitize_key( $_GET['sort'] ?? 'newest' );
$column = $columns[ $key ] ?? $columns['newest'];
// Both values are selected from fixed application code.
$sql = $wpdb->prepare(
"SELECT ID FROM {$wpdb->posts} ORDER BY {$column} DESC"
);
This older-version pattern is safe only because $column can contain one of the literal names defined by the application. An allowlist is not the same as checking whether a string merely “looks like” a column name.
6. Treat ORDER BY, directions, and other SQL structure as allowlisted code
Sort direction is a SQL keyword, not a value. Do not pass ASC or DESC through %s and do not concatenate the request value. Map a normalized key to a literal keyword, and append that mapped value only after the choice has been constrained.
<?php
global $wpdb;
$columns = array(
'date' => 'post_date',
'title' => 'post_title',
);
$directions = array(
'asc' => 'ASC',
'desc' => 'DESC',
);
$sort_key = sanitize_key( $_GET['sort'] ?? 'date' );
$direction_key = sanitize_key( $_GET['direction'] ?? 'desc' );
$column = $columns[ $sort_key ] ?? $columns['date'];
$direction = $directions[ $direction_key ] ?? $directions['desc'];
$sql = $wpdb->prepare(
"SELECT ID FROM {$wpdb->posts} ORDER BY %i {$direction}",
$column
);
On WordPress versions that do not support %i, use the same fixed mappings for both the column and direction, then interpolate those mapped literals. Apply the same rule to table names, operators, grouping fragments, and optional clauses: user input may select from a finite set, but it must not write the SQL grammar.
7. Why esc_sql() is not enough
esc_sql() has a limited purpose. Its reference says that $wpdb->prepare() is generally preferred and warns that esc_sql() does not escape unquoted numeric values, field names, or SQL keywords.
Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Fix the driver behind crashes, sound loss and screen glitches3Repair Windows errors before they cause bigger problemsRank #4
- 【Softer and More Comfortable】Vaydeer wrist rest has unique diamond pattern, which is the combination of softness and aesthetics. The materials of wrist rest are improved into higher quality memory foam and covered with silky smooth lycra. The computer wrist rest makes you as comfortable and cushiony as like rest your wrists on clouds.
- 【Ergonomic Wrist Saver】The wrist rests for keyboard and mouse comes with a 17.32×3.15×0.83 inch keyboard wrist pad and a 5.94×3.15×0.83 inch mouse wrist support. Based on ergonomic design, the unique concave shape is the perfect fit for your wrist joints. The wrist rest pad fits most computer keyboards and laptops, improve hand and wrist posture, release your wrist and arm stress.
- 【Non-Slip Rubber Bottom】Featuring an anti-skid silicone base on the bottom, this wrist keyboard support stays firmly in place on your desk, preventing the padding from sliding around, ensuring stable and consistent wrist support during extended computer sessions.
- 【Better Experience & Pain Relief】Our keyboard arm rest is beneficial to alleviate the soreness caused by direct contact and friction between your arm and a hard desk surface, reducing the risk of wrist fatigue or carpal tunnel. The soft texture of memory foam can evenly distribute the pressure around your wrists and provide good support with just enough give.
- 【Helpful in Multiple Scenarios】Whether you're working, studying, writing, typing, gaming, this keyboard and mouse rest combo is an essential accessory to add comfort and support to your hands and wrists. It’s also a great gift for men, women, family, friend, coworker, gamer, teacher, etc.
That limitation matters when developers use one escaping function for every part of a query. A field name or sort direction is not safely handled merely because it passed through esc_sql(). Numeric text that is concatenated without quotes is another gap. Keep value data in typed placeholders, cast or normalize numeric input, and allowlist every identifier or keyword.
If an existing code path uses esc_sql(), review the entire statement rather than replacing one function mechanically. Check where the value is placed, whether it is quoted, whether the SQL fragment is actually an identifier or keyword, and whether the query can be rewritten with prepare().
8. Prepare immediately before execution
WordPress coding standards state: “Escaping should be done as close to the time of the query as possible, preferably by using $wpdb->prepare().” Keep the final SQL construction next to the call that executes it. This makes it easier to verify that every interpolated piece is trusted and that the placeholders still match the arguments.
Avoid storing an unprepared query in a variable, passing it through several helpers, and preparing only part of it later. Such indirection makes concatenation easy to miss during review. A clearer sequence is:
- Read the request or function arguments.
- Normalize values and select allowlisted structural options.
- Call
$wpdb->prepare()with the complete SQL and all value arguments. - Execute the returned statement immediately with the appropriate
$wpdbmethod.
Review every interpolation in the SQL string. A WordPress table property or a literal fragment selected from a fixed map may be valid; raw request text is not.
9. Version support can change the safe implementation
Declare the WordPress versions your plugin or theme supports and choose the implementation accordingly. WordPress documents an unsafe-query issue affecting version 4.8.2 and earlier, and it documents the %i placeholder as added in 6.2.0.
Best Value
- 【No Drill Mounted】Cable management tray can be assembled in as little as 3 minutes or less-simply. Side clips easily clampe the edge of desk, pass through the holes on the sides, and secure excess cables with baskets. Desk cable management supports inward or outward installation to meet your needs in different scenarios, and provides you with great convenience when collecting and organizing wires.
- 【Rubber Pad Protects Desk】Wire organizer under desk built-in soft rubber pads on the clamp protect your desk from scratches, so you will not damage your furniture or office.
- 【Sturdy and Beautiful】Cord management under desk is made of high-quality carbon steel and holds about 15 lbs. The wire basket has 2 holes on each side of the tray to enable your cables to pass freely. Cable baskets are suitable for desk thickness use from 0.4" to 2.4".
- 【Space Saving & Keep Organized】Desk cable management tray holds all your power cords, outlet strips, USB hubs and computer transformers hidden from your feet, and the data cables will not enter the vacuum cleaner to keep your desk clean and tidy. Desk wire organizer is also suitable for use in the kitchen and outdoors.
- 【Reduce Safety Risks】Cable tray under desk keeps all plugs away from your kids, no more worry about tripping. Using 2 holes wire tray saves extra space, helps you easily cabling and wire protection. The mesh design is not easy to accumulate dust, but avoids safety accidents caused by messy wires.
| Support situation | Implementation consequence |
|---|---|
| WordPress 6.2.0 or newer is guaranteed | Use %i for dynamic identifiers, while still restricting choices to known names. |
| A release before 6.2.0 is in the supported range | Use fixed allowlists for table and column names; do not rely on %i. |
| Version 4.8.2 or earlier may run the code | Account for WordPress’s documented unsafe-query issue and set a clear minimum version or compatibility path. |
| Multiple major versions are supported | Test each path and ensure the fallback never interpolates untrusted identifiers. |
Do not describe a query as safe without stating the version assumption behind its identifier handling. A pattern that depends on %i needs a minimum-version requirement or a guarded fallback.
10. Compare the safe and unsafe design choices
| Decision | Safer approach | Risky approach |
|---|---|---|
| Data access | Use a native WordPress API when it performs the required operation. | Re-create core behavior with hand-written SQL without a need. |
| Value handling | Normalize input and pass it to a matching %s, %d, or %f placeholder. |
Concatenate request text into the SQL string. |
| Identifiers | Use %i on WordPress 6.2.0+ or a fixed allowlist on older versions. |
Use a request parameter directly as a table or column name. |
| Sort direction | Map a key to the literal ASC or DESC. |
Insert the supplied direction or pass it as a string value. |
| Pattern matching | Call esc_like(), add wildcards to the argument, then prepare. |
Put wildcards and untrusted text directly inside a quoted SQL fragment. |
| Escaping timing | Prepare immediately before execution and inspect every interpolation. | Escape in an unrelated helper and assume the final query is covered. |
11. A code-review checklist for plugins and themes
- Search for
$wpdbcalls and list every custom query. - Confirm that a native WordPress API cannot perform each operation.
- Mark every value that originates outside the function: request parameters, cookies, form fields, REST data, and values returned from other integrations.
- Verify that each value is normalized to its expected type before query construction.
- Verify that every value appears in a matching
%s,%d, or%fplaceholder. - Check that placeholders are unquoted and that literal percent signs use
%%. - For
LIKE, confirm thatesc_like()runs beforeprepare()and that the full wildcard pattern is an argument. - Identify every dynamic table or column name. Use
%ionly where the supported WordPress version provides it; otherwise use a fixed allowlist. - Identify dynamic keywords and operators, especially
ORDER BYand sort direction. Replace them with mapped literals. - Look for
esc_sql()used as a universal solution. Rework numeric, identifier, and keyword fragments instead of assuming they are escaped. - Check that preparation occurs immediately before the corresponding execution call.
- Run the review against the oldest WordPress version in the support range, including the documented 4.8.2-and-earlier unsafe-query concern.
12. Common mistakes and their fixes
Quoting a placeholder
Problem: writing WHERE post_status = '%s'. Fix: write WHERE post_status = %s and pass the status as an argument. WordPress handles the quoting.
Windows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallCrashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minuteUsing the wrong placeholder category
Problem: treating a column name as %s, or treating a sort direction as a value. Fix: use %i for identifiers on 6.2.0+, use an allowlist for older versions, and map keywords to literals.
Escaping a numeric value but leaving it unquoted
Problem: concatenating a supposedly numeric request value into SQL after calling esc_sql(). Fix: normalize it and pass it through %d or %f.
Putting the wildcard in the SQL text
Problem: combining request text with '%...%' inside the query. Fix: call esc_like(), construct the complete pattern in PHP, and pass it to %s.
Trusting a sanitized key as a column name
Problem: assuming that a key containing only letters is automatically a valid and safe SQL identifier. Fix: use the key to select a value from a finite map, then use %i or the legacy allowlist pattern.
Quick wins for a faster PC:
Scan for outdated or missing drivers - takes under a minuteDriver Scan →Repair Windows errors before they cause bigger problemsFix Now →Preparing too early
Problem: preparing a partial query and appending request-controlled fragments later. Fix: finish normalization and allowlist selection first, then prepare the complete statement immediately before execution.
13. A practical implementation sequence
For a new custom query, use this sequence as a repeatable development pattern:
- Write down the exact records and filters the feature needs.
- Check native WordPress APIs before choosing SQL.
- Define the accepted types and defaults for every input.
- Define finite maps for every selectable identifier, operator, or keyword.
- Normalize request values and reject or default invalid choices.
- Write the SQL with unquoted typed placeholders for all values.
- Escape
LIKEtext withesc_like()before preparing. - Use
%ionly when the minimum supported WordPress version is 6.2.0 or later; otherwise interpolate only names from a fixed allowlist. - Call
$wpdb->prepare()immediately before the matching execution method. - Review the final query for every concatenation and test the oldest supported WordPress version.
This sequence keeps the SQL structure under application control while allowing legitimate user-selected filters and sorting.
Quick Recap
14. What to retain
- WordPress APIs are safer than custom SQL when they cover the operation.
$wpdb->prepare()parameterizes values and applies the matching type placeholder.%iis for identifiers, not ordinary string values.esc_sql()has a limited scope and does not secure unquoted numbers, field names, or SQL keywords.- Dynamic SQL structure must come from a fixed allowlist.
- WordPress version support matters: the documented older unsafe-query issue and the 6.2.0 arrival of
%iaffect implementation choices.
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

