You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用预编译语句仍遭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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 21:53:23