xploitscan-shared-rules 1.10.0 → 1.11.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.js CHANGED
@@ -815,9 +815,12 @@ var SERVER_SIDE_PATH_RE = new RegExp(
815
815
  ].join("|"),
816
816
  "i"
817
817
  );
818
- function isServerSideFile(filePath) {
818
+ var SERVER_SIDE_CONTENT_RE = /\b(?:req|request)\.(?:body|query|params|headers|cookies)\b|\b(?:app|router)\.(?:get|post|put|patch|delete|use|all)\s*\(|\bctx\.request\b|\bevent\.(?:body|queryStringParameters|pathParameters)\b|\(\s*req\s*,\s*res\b/;
819
+ function isServerSideFile(filePath, content) {
819
820
  if (isTestFile(filePath)) return false;
820
- return SERVER_SIDE_PATH_RE.test(filePath);
821
+ if (SERVER_SIDE_PATH_RE.test(filePath)) return true;
822
+ if (content && SERVER_SIDE_CONTENT_RE.test(content)) return true;
823
+ return false;
821
824
  }
822
825
  var CONFIG_FILE_PATTERN = new RegExp(
823
826
  [
@@ -1030,7 +1033,7 @@ var missingAuthMiddleware = {
1030
1033
  category: "Authentication",
1031
1034
  description: "API routes without authentication checks allow unauthorized access.",
1032
1035
  check(content, filePath) {
1033
- if (!isServerSideFile(filePath)) return [];
1036
+ if (!isServerSideFile(filePath, content)) return [];
1034
1037
  const routePatterns = [
1035
1038
  // Express/Hono style
1036
1039
  /\.(get|post|put|patch|delete)\s*\(\s*["'`][^"'`]+["'`]\s*,\s*(?:async\s+)?\(?(?:req|c|ctx)/gi,
@@ -2348,7 +2351,7 @@ var exposedStackTraces = {
2348
2351
  category: "Information Leakage",
2349
2352
  description: "Returning error.stack or detailed error messages in API responses reveals internal code paths, file structure, and dependencies to attackers.",
2350
2353
  check(content, filePath) {
2351
- if (!isServerSideFile(filePath)) return [];
2354
+ if (!isServerSideFile(filePath, content)) return [];
2352
2355
  const matches = [];
2353
2356
  const patterns = [
2354
2357
  // Sending stack trace in response
@@ -2446,7 +2449,7 @@ var ssrfVulnerability = {
2446
2449
  category: "Injection",
2447
2450
  description: "Fetching URLs from user input without validation allows attackers to access internal services, cloud metadata endpoints (169.254.169.254), and private networks.",
2448
2451
  check(content, filePath) {
2449
- if (!isServerSideFile(filePath)) return [];
2452
+ if (!isServerSideFile(filePath, content)) return [];
2450
2453
  const matches = [];
2451
2454
  const hasValidation = /allowedHosts|allowedDomains|allowedUrls|safeDomain|whitelist|urlValidator|new URL.*hostname.*includes|isAllowedUrl|validateUrl|isValidUrl/i.test(content);
2452
2455
  if (hasValidation) return [];
@@ -2503,7 +2506,7 @@ var massAssignment = {
2503
2506
  category: "Authorization",
2504
2507
  description: "Spreading or assigning request body directly into database models allows attackers to set fields they shouldn't (e.g., isAdmin, role, verified).",
2505
2508
  check(content, filePath) {
2506
- if (!isServerSideFile(filePath)) return [];
2509
+ if (!isServerSideFile(filePath, content)) return [];
2507
2510
  const hasSanitization = /pick\(|omit\(|allowedFields|sanitize|whitelist|permit|strong_params/i.test(content);
2508
2511
  if (hasSanitization) return [];
2509
2512
  const matches = [];
@@ -2655,7 +2658,7 @@ var logInjection = {
2655
2658
  category: "Injection",
2656
2659
  description: "Logging unsanitized user input allows attackers to forge log entries, inject malicious content, or exploit log aggregation systems via newlines and special characters.",
2657
2660
  check(content, filePath) {
2658
- if (!isServerSideFile(filePath)) return [];
2661
+ if (!isServerSideFile(filePath, content)) return [];
2659
2662
  const hasSanitization = /replace\s*\(\s*\/\[?\\r\\n\]|sanitizeLog|stripNewlines|sanitizeForLog/i.test(content);
2660
2663
  if (hasSanitization) return [];
2661
2664
  const matches = [];
@@ -2721,7 +2724,7 @@ var weakPasswordRequirements = {
2721
2724
  if (!/(?:password|passwd|pwd)/i.test(content)) return [];
2722
2725
  const isPasswordContext = /(?:register|signup|sign.up|createUser|create.user|changePassword|resetPassword|set.password|validatePassword|validate.password|passwordPolicy|password.policy)/i.test(
2723
2726
  content
2724
- ) || isServerSideFile(filePath);
2727
+ ) || isServerSideFile(filePath, content);
2725
2728
  const matches = [];
2726
2729
  if (isPasswordContext) {
2727
2730
  const weakThresholdPatterns = [
@@ -3875,8 +3878,8 @@ var xxeVulnerability = {
3875
3878
  if (!/xml|parseXml|parseXML|DOMParser|SAXParser|etree|lxml|libxml/i.test(content)) return [];
3876
3879
  const matches = [];
3877
3880
  const patterns = [
3878
- /\.parseXm?l\s*\(/gi,
3879
- // catches parseXml (libxmljs) AND parseXML
3881
+ /\.parseXm?l(?:String)?\s*\(/gi,
3882
+ // parseXml / parseXML / parseXmlString (libxmljs)
3880
3883
  // NOTE: the browser `new DOMParser()` is intentionally NOT flagged.
3881
3884
  // Per the HTML/XML spec, DOMParser.parseFromString does not resolve
3882
3885
  // external entities, so it is not an XXE sink — flagging it produced a
@@ -4062,7 +4065,7 @@ var exposedAdminRoutes = {
4062
4065
  category: "Information Leakage",
4063
4066
  description: "Routes like /admin, /debug, /phpinfo, or /actuator without authentication expose sensitive controls and information to attackers.",
4064
4067
  check(content, filePath) {
4065
- if (!isServerSideFile(filePath)) return [];
4068
+ if (!isServerSideFile(filePath, content)) return [];
4066
4069
  const matches = [];
4067
4070
  const patterns = [
4068
4071
  /[.'"]\s*(?:get|use|all)\s*\(\s*["'`]\/(?:admin|debug|_debug|__debug__|phpinfo|actuator|graphiql|playground|swagger|reset|seed|test|dev|mock)["'`]/gi
@@ -4154,7 +4157,7 @@ var missingContentDisposition = {
4154
4157
  description: "File download endpoints without Content-Disposition headers may render files inline, leading to XSS if the file contains HTML/JS.",
4155
4158
  check(content, filePath) {
4156
4159
  if (!/(?:download|sendFile|send_file|pipe|createReadStream)/i.test(content)) return [];
4157
- if (!isServerSideFile(filePath)) return [];
4160
+ if (!isServerSideFile(filePath, content)) return [];
4158
4161
  if (/Content-Disposition|attachment|download/i.test(content)) return [];
4159
4162
  return findMatches(
4160
4163
  content,
@@ -4251,7 +4254,7 @@ var unprotectedDownload = {
4251
4254
  description: "File download endpoints that accept user-controlled filenames without path validation allow directory traversal to read arbitrary files.",
4252
4255
  check(content, filePath) {
4253
4256
  if (!/(?:download|sendFile|send_file)/i.test(content)) return [];
4254
- if (!isServerSideFile(filePath)) return [];
4257
+ if (!isServerSideFile(filePath, content)) return [];
4255
4258
  const matches = [];
4256
4259
  if (/(?:sendFile|download|send_file)\s*\([^)]*(?:req\.|params\.|query\.|body\.)/i.test(content)) {
4257
4260
  const hasValidation = /path\.resolve|path\.normalize|path\.join.*__dirname|realpath|includes\s*\(\s*["']\.\./i.test(content);
@@ -4280,7 +4283,7 @@ var commandInjection = {
4280
4283
  const matches = [];
4281
4284
  const patterns = [
4282
4285
  // Node.js — require standalone exec/execSync, not db.exec() or conn.exec()
4283
- /(?<![.\w])(?:exec|execSync)\s*\(\s*(?:`[^`]*\$\{|["'][^"']*\+\s*(?:req\.|body\.|input|params|args|user))/gi,
4286
+ /(?<![.\w])(?:exec|execSync)\s*\(\s*(?:`[^`]*\$\{|["'][^"']*["']\s*\+\s*(?:req\.|body\.|input|params|args|user))/gi,
4284
4287
  /child_process.*exec\s*\(\s*(?!["'`])/g,
4285
4288
  // spawn / execFile / exec with shell: true AND a template literal
4286
4289
  // first arg. `shell: true` converts the first argument into a string