xploitscan-shared-rules 1.11.1 → 1.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1482,6 +1482,41 @@ var sqlInjection = {
1482
1482
  matches.push(m);
1483
1483
  }
1484
1484
  }
1485
+ if (/\.\s*(?:query|execute|raw|queryRawUnsafe|executeRawUnsafe|\$queryRawUnsafe|\$executeRawUnsafe)\s*\(/.test(content)) {
1486
+ const ctx = tryParse(content, filePath);
1487
+ if (ctx) {
1488
+ const { parsed, taint } = ctx;
1489
+ const SQL_SINKS = /* @__PURE__ */ new Set([
1490
+ "query",
1491
+ "execute",
1492
+ "raw",
1493
+ "queryRawUnsafe",
1494
+ "executeRawUnsafe",
1495
+ "$queryRawUnsafe",
1496
+ "$executeRawUnsafe"
1497
+ ]);
1498
+ visitCalls(
1499
+ parsed,
1500
+ (callee) => callee.type === "MemberExpression" && callee.property.type === "Identifier" && SQL_SINKS.has(callee.property.name),
1501
+ (call, line) => {
1502
+ const first = call.arguments[0];
1503
+ if (!first || first.type === "SpreadElement") return;
1504
+ if (first.type === "StringLiteral" || first.type === "TemplateLiteral") return;
1505
+ if (!taint.isTainted(first)) return;
1506
+ if (matches.some((m) => m.line === line)) return;
1507
+ matches.push(
1508
+ astMatch(
1509
+ content,
1510
+ filePath,
1511
+ line,
1512
+ sqlInjection,
1513
+ "Use parameterized queries instead of building SQL from user input in a variable. Example: db.query('SELECT * FROM users WHERE login = ?', [req.body.login])"
1514
+ )
1515
+ );
1516
+ }
1517
+ );
1518
+ }
1519
+ }
1485
1520
  return matches;
1486
1521
  }
1487
1522
  };
@@ -2726,12 +2761,12 @@ var ssrfVulnerability = {
2726
2761
  filePath,
2727
2762
  () => "Validate URLs against an allowlist before fetching. Block internal IPs: 127.0.0.1, 10.x, 172.16-31.x, 192.168.x, 169.254.169.254 (cloud metadata). Use: const url = new URL(input); if (!ALLOWED_HOSTS.includes(url.hostname)) throw new Error('Blocked');"
2728
2763
  ));
2729
- if (!/\b(?:fetch|axios|got|request|http\.get|https\.get)\b/.test(content)) return matches;
2764
+ if (!/\b(?:fetch|axios|got|request|needle|superagent|undici|http\.get|https\.get)\b/.test(content)) return matches;
2730
2765
  const ctx = tryParse(content, filePath);
2731
2766
  if (!ctx) return matches;
2732
2767
  const { parsed, taint } = ctx;
2733
- const FETCH_CALLEES = /* @__PURE__ */ new Set(["fetch", "axios", "got", "request"]);
2734
- const FETCH_METHODS = /* @__PURE__ */ new Set(["get", "post", "put", "patch", "delete", "request"]);
2768
+ const FETCH_CALLEES = /* @__PURE__ */ new Set(["fetch", "axios", "got", "request", "needle", "superagent", "undici"]);
2769
+ const FETCH_METHODS = /* @__PURE__ */ new Set(["get", "post", "put", "patch", "delete", "request", "head"]);
2735
2770
  visitCalls(
2736
2771
  parsed,
2737
2772
  (callee) => {
@@ -2740,7 +2775,7 @@ var ssrfVulnerability = {
2740
2775
  if (!FETCH_METHODS.has(callee.property.name)) return false;
2741
2776
  const obj = callee.object;
2742
2777
  if (obj.type === "Identifier") {
2743
- return obj.name === "axios" || obj.name === "got" || obj.name === "http" || obj.name === "https";
2778
+ return obj.name === "axios" || obj.name === "got" || obj.name === "http" || obj.name === "https" || obj.name === "needle" || obj.name === "superagent" || obj.name === "undici";
2744
2779
  }
2745
2780
  }
2746
2781
  return false;