使用预编译语句仍遭SonarQube提示SQL注入风险,如何优化?
已用预编译语句仍被SonarQube提示SQL安全问题,如何改进?
我已经使用了预编译语句和参数化查询,但SonarQube仍提示查询存在安全问题,不清楚哪里不安全。以下是我的代码:
let { keyword } = req.query; const first_query = ` SELECT hs_code, tree_id, CONCAT(hs_code, ' - ', tree_id) AS gabungan FROM referensi.v_btbmi_2022 vb `; const option = keyword.length < 1 ? 'false' : '(tree_id ILIKE :keyword OR hs_code ILIKE :keyword)'; if (keyword.length < 1) { res.status(400).json({ code: "03", message: "data inputan tidak ada", data: [], }); return; } const last_query = await db.query( first_query + ' WHERE LENGTH(hs_code) > 7 AND ' + option, { replacements: { keyword: `%${keyword}%` }, type: db.QueryTypes.SELECT, }, );
问题根源
你当前的代码虽然对keyword用了参数化替换,但通过字符串拼接生成WHERE子句的方式,会被SonarQube判定为不安全风险——这类动态SQL构造行为,工具无法完全确认拼接内容的安全性,哪怕你的option逻辑看起来没问题。
改进方案
1. 直接构造完整参数化查询(最简修复)
去掉字符串拼接逻辑,直接生成完整的参数化SQL:
let { keyword } = req.query; if (keyword.length < 1) { res.status(400).json({ code: "03", message: "data inputan tidak ada", data: [], }); return; } // 直接编写完整的参数化查询语句 const query = ` SELECT hs_code, tree_id, CONCAT(hs_code, ' - ', tree_id) AS gabungan FROM referensi.v_btbmi_2022 vb WHERE LENGTH(hs_code) > 7 AND (tree_id ILIKE :keyword OR hs_code ILIKE :keyword) `; const results = await db.query(query, { replacements: { keyword: `%${keyword}%` }, type: db.QueryTypes.SELECT, });
2. 使用ORM查询构建器(推荐)
如果你的项目用了Sequelize这类ORM,用官方查询构建器构造动态条件,完全避免手动拼接SQL:
let { keyword } = req.query; if (keyword.length < 1) { res.status(400).json({ code: "03", message: "data inputan tidak ada", data: [], }); return; } const results = await db.model('v_btbmi_2022', { tableName: 'referensi.v_btbmi_2022' }).findAll({ attributes: [ 'hs_code', 'tree_id', [db.fn('CONCAT', db.col('hs_code'), ' - ', db.col('tree_id')), 'gabungan'] ], where: { [db.Op.and]: [ db.where(db.fn('LENGTH', db.col('hs_code')), db.Op.gt, 7), { [db.Op.or]: [ { tree_id: { [db.Op.iLike]: `%${keyword}%` } }, { hs_code: { [db.Op.iLike]: `%${keyword}%` } } ] } ] } });
这种方式由ORM负责SQL生成,完全规避手动拼接风险,能轻松通过SonarQube检测。
3. 合并条件到基础查询(退而求其次)
如果必须保留动态逻辑,把条件合并到基础查询中,用参数是否非空控制逻辑,避免字符串拼接:
let { keyword } = req.query; if (keyword.length < 1) { res.status(400).json({ code: "03", message: "data inputan tidak ada", data: [], }); return; } const baseQuery = ` SELECT hs_code, tree_id, CONCAT(hs_code, ' - ', tree_id) AS gabungan FROM referensi.v_btbmi_2022 vb WHERE LENGTH(hs_code) > 7 AND (:keyword IS NOT NULL AND (tree_id ILIKE :keyword OR hs_code ILIKE :keyword)) `; const results = await db.query(baseQuery, { replacements: { keyword: `%${keyword}%` }, type: db.QueryTypes.SELECT, });
核心原则
SonarQube对SQL注入的检测会重点盯防手动拼接SQL字符串的行为,哪怕拼接内容看似安全,工具也会标记风险。所以要尽量:
- 杜绝任何形式的SQL字符串拼接
- 优先使用ORM的查询构建器
- 必须动态生成时,用参数化方式处理所有可变条件
内容的提问来源于stack exchange,提问作者Muhammad Fadhil Akbar
相关产品推荐
相关产品推荐

