Fix SQL injection, query value handling, and other security issues
- Quote all identifiers and validate operators, order strategies, join types, raw comparisons, and limit/offset/page in the query generator - Treat 0 as a real query value; stop null from leaving unbound placeholders - Return the WHERE clause and its values separately from sqlGenerator so delete/update no longer regex-parse generated SQL - update(): target matched row ids, re-fetch reliably, and return success: false when no rows match - Fix duplicated aliases, [object Object] select fields, AVERAGE -> AVG, escape GROUP_CONCAT separators - Fix OFFSET without LIMIT and OFFSET on count queries - Store boolean false as 0 on insert; call function values once - Verify TLS certificates by default (new ssl_reject_unauthorized option) - Confirm before importing an executable schema from an archive (--yes) - Skip symlinks when reading extracted zip archives - Only trim files matching the backup/export naming pattern - Tighten default HTML sanitizer (no style/id attributes, no button) - Stop typedef generation from mutating parent table schemas - Pass config through DbSQL; handle BigInt values in results Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
@@ -6,6 +6,7 @@ import type {
|
||||
import sqlEqualityParser from "./sql-equality-parser";
|
||||
|
||||
type Params = {
|
||||
/** Already-quoted column reference */
|
||||
fieldName: string;
|
||||
value?: SQLInsertGenValueType;
|
||||
equality?: (typeof ServerQueryEqualities)[number];
|
||||
@@ -15,6 +16,7 @@ type Params = {
|
||||
},
|
||||
string
|
||||
>;
|
||||
/** `value` is an already-quoted column reference, not a parameter */
|
||||
isValueFieldValue?: boolean;
|
||||
};
|
||||
|
||||
@@ -42,9 +44,13 @@ export default function sqlGenOperatorGen({
|
||||
return { str: `${fieldName} IS NOT NULL` };
|
||||
}
|
||||
|
||||
if (value) {
|
||||
// `0` is a real value; only null / undefined / "" count as "no value"
|
||||
const hasValue = value !== undefined && value !== null && value !== "";
|
||||
|
||||
if (hasValue) {
|
||||
const finalValue = isValueFieldValue ? value : "?";
|
||||
const finalParams = isValueFieldValue ? undefined : value;
|
||||
const likeParams = isValueFieldValue ? undefined : `%${value}%`;
|
||||
|
||||
if (equality == "MATCH") {
|
||||
return {
|
||||
@@ -59,7 +65,7 @@ export default function sqlGenOperatorGen({
|
||||
} else if (equality == "LIKE_LOWER") {
|
||||
return {
|
||||
str: `LOWER(${fieldName}) LIKE LOWER(${finalValue})`,
|
||||
param: `%${finalParams}%`,
|
||||
param: likeParams,
|
||||
};
|
||||
} else if (equality == "LIKE_LOWER_RAW") {
|
||||
return {
|
||||
@@ -69,7 +75,7 @@ export default function sqlGenOperatorGen({
|
||||
} else if (equality == "LIKE") {
|
||||
return {
|
||||
str: `${fieldName} LIKE ${finalValue}`,
|
||||
param: `%${finalParams}%`,
|
||||
param: likeParams,
|
||||
};
|
||||
} else if (equality == "LIKE_RAW") {
|
||||
return {
|
||||
@@ -79,7 +85,7 @@ export default function sqlGenOperatorGen({
|
||||
} else if (equality == "NOT_LIKE_LOWER") {
|
||||
return {
|
||||
str: `LOWER(${fieldName}) NOT LIKE LOWER(${finalValue})`,
|
||||
param: `%${finalParams}%`,
|
||||
param: likeParams,
|
||||
};
|
||||
} else if (equality == "NOT_LIKE_LOWER_RAW") {
|
||||
return {
|
||||
@@ -89,7 +95,7 @@ export default function sqlGenOperatorGen({
|
||||
} else if (equality == "NOT LIKE") {
|
||||
return {
|
||||
str: `${fieldName} NOT LIKE ${finalValue}`,
|
||||
param: finalParams,
|
||||
param: likeParams,
|
||||
};
|
||||
} else if (equality == "NOT LIKE_RAW") {
|
||||
return {
|
||||
@@ -137,12 +143,12 @@ export default function sqlGenOperatorGen({
|
||||
} else if (equality) {
|
||||
return {
|
||||
str: `${fieldName} ${sqlEqualityParser(equality)} ?`,
|
||||
param: value,
|
||||
param: value ?? "",
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
str: `${fieldName} = ?`,
|
||||
param: value,
|
||||
param: value ?? "",
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user