@guardrail-ai/rules 0.1.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.
Files changed (122) hide show
  1. package/dist/__tests__/advanced-rules.test.d.ts +2 -0
  2. package/dist/__tests__/advanced-rules.test.d.ts.map +1 -0
  3. package/dist/__tests__/advanced-rules.test.js +59 -0
  4. package/dist/__tests__/advanced-rules.test.js.map +1 -0
  5. package/dist/__tests__/dead-code.test.d.ts +2 -0
  6. package/dist/__tests__/dead-code.test.d.ts.map +1 -0
  7. package/dist/__tests__/dead-code.test.js +66 -0
  8. package/dist/__tests__/dead-code.test.js.map +1 -0
  9. package/dist/__tests__/duplicate-logic.test.d.ts +2 -0
  10. package/dist/__tests__/duplicate-logic.test.d.ts.map +1 -0
  11. package/dist/__tests__/duplicate-logic.test.js +47 -0
  12. package/dist/__tests__/duplicate-logic.test.js.map +1 -0
  13. package/dist/__tests__/hardcoded-api-key.test.d.ts +2 -0
  14. package/dist/__tests__/hardcoded-api-key.test.d.ts.map +1 -0
  15. package/dist/__tests__/hardcoded-api-key.test.js +44 -0
  16. package/dist/__tests__/hardcoded-api-key.test.js.map +1 -0
  17. package/dist/__tests__/inefficient-loop.test.d.ts +2 -0
  18. package/dist/__tests__/inefficient-loop.test.d.ts.map +1 -0
  19. package/dist/__tests__/inefficient-loop.test.js +49 -0
  20. package/dist/__tests__/inefficient-loop.test.js.map +1 -0
  21. package/dist/__tests__/new-rules.test.d.ts +2 -0
  22. package/dist/__tests__/new-rules.test.d.ts.map +1 -0
  23. package/dist/__tests__/new-rules.test.js +193 -0
  24. package/dist/__tests__/new-rules.test.js.map +1 -0
  25. package/dist/__tests__/sql-injection.test.d.ts +2 -0
  26. package/dist/__tests__/sql-injection.test.d.ts.map +1 -0
  27. package/dist/__tests__/sql-injection.test.js +40 -0
  28. package/dist/__tests__/sql-injection.test.js.map +1 -0
  29. package/dist/any-type-abuse.d.ts +4 -0
  30. package/dist/any-type-abuse.d.ts.map +1 -0
  31. package/dist/any-type-abuse.js +37 -0
  32. package/dist/any-type-abuse.js.map +1 -0
  33. package/dist/console-log-spam.d.ts +4 -0
  34. package/dist/console-log-spam.d.ts.map +1 -0
  35. package/dist/console-log-spam.js +60 -0
  36. package/dist/console-log-spam.js.map +1 -0
  37. package/dist/data/hallucinated-packages.json +212 -0
  38. package/dist/dead-code.d.ts +10 -0
  39. package/dist/dead-code.d.ts.map +1 -0
  40. package/dist/dead-code.js +152 -0
  41. package/dist/dead-code.js.map +1 -0
  42. package/dist/duplicate-logic.d.ts +4 -0
  43. package/dist/duplicate-logic.d.ts.map +1 -0
  44. package/dist/duplicate-logic.js +90 -0
  45. package/dist/duplicate-logic.js.map +1 -0
  46. package/dist/env-var-leak.d.ts +4 -0
  47. package/dist/env-var-leak.d.ts.map +1 -0
  48. package/dist/env-var-leak.js +86 -0
  49. package/dist/env-var-leak.js.map +1 -0
  50. package/dist/fetch-without-error-handling.d.ts +4 -0
  51. package/dist/fetch-without-error-handling.d.ts.map +1 -0
  52. package/dist/fetch-without-error-handling.js +62 -0
  53. package/dist/fetch-without-error-handling.js.map +1 -0
  54. package/dist/hallucinated-import.d.ts +4 -0
  55. package/dist/hallucinated-import.d.ts.map +1 -0
  56. package/dist/hallucinated-import.js +75 -0
  57. package/dist/hallucinated-import.js.map +1 -0
  58. package/dist/hardcoded-api-key.d.ts +4 -0
  59. package/dist/hardcoded-api-key.d.ts.map +1 -0
  60. package/dist/hardcoded-api-key.js +129 -0
  61. package/dist/hardcoded-api-key.js.map +1 -0
  62. package/dist/hardcoded-localhost.d.ts +4 -0
  63. package/dist/hardcoded-localhost.d.ts.map +1 -0
  64. package/dist/hardcoded-localhost.js +53 -0
  65. package/dist/hardcoded-localhost.js.map +1 -0
  66. package/dist/index.d.ts +26 -0
  67. package/dist/index.d.ts.map +1 -0
  68. package/dist/index.js +83 -0
  69. package/dist/index.js.map +1 -0
  70. package/dist/inefficient-loop.d.ts +4 -0
  71. package/dist/inefficient-loop.d.ts.map +1 -0
  72. package/dist/inefficient-loop.js +104 -0
  73. package/dist/inefficient-loop.js.map +1 -0
  74. package/dist/insecure-cors.d.ts +4 -0
  75. package/dist/insecure-cors.d.ts.map +1 -0
  76. package/dist/insecure-cors.js +89 -0
  77. package/dist/insecure-cors.js.map +1 -0
  78. package/dist/magic-numbers.d.ts +4 -0
  79. package/dist/magic-numbers.d.ts.map +1 -0
  80. package/dist/magic-numbers.js +53 -0
  81. package/dist/magic-numbers.js.map +1 -0
  82. package/dist/n-plus-one-query.d.ts +4 -0
  83. package/dist/n-plus-one-query.d.ts.map +1 -0
  84. package/dist/n-plus-one-query.js +95 -0
  85. package/dist/n-plus-one-query.js.map +1 -0
  86. package/dist/no-eval.d.ts +4 -0
  87. package/dist/no-eval.d.ts.map +1 -0
  88. package/dist/no-eval.js +53 -0
  89. package/dist/no-eval.js.map +1 -0
  90. package/dist/no-rate-limiting.d.ts +4 -0
  91. package/dist/no-rate-limiting.d.ts.map +1 -0
  92. package/dist/no-rate-limiting.js +72 -0
  93. package/dist/no-rate-limiting.js.map +1 -0
  94. package/dist/no-secrets-in-logs.d.ts +4 -0
  95. package/dist/no-secrets-in-logs.d.ts.map +1 -0
  96. package/dist/no-secrets-in-logs.js +71 -0
  97. package/dist/no-secrets-in-logs.js.map +1 -0
  98. package/dist/overly-broad-catch.d.ts +4 -0
  99. package/dist/overly-broad-catch.d.ts.map +1 -0
  100. package/dist/overly-broad-catch.js +48 -0
  101. package/dist/overly-broad-catch.js.map +1 -0
  102. package/dist/placeholder-code.d.ts +4 -0
  103. package/dist/placeholder-code.d.ts.map +1 -0
  104. package/dist/placeholder-code.js +58 -0
  105. package/dist/placeholder-code.js.map +1 -0
  106. package/dist/promise-without-catch.d.ts +4 -0
  107. package/dist/promise-without-catch.d.ts.map +1 -0
  108. package/dist/promise-without-catch.js +72 -0
  109. package/dist/promise-without-catch.js.map +1 -0
  110. package/dist/sql-injection.d.ts +4 -0
  111. package/dist/sql-injection.d.ts.map +1 -0
  112. package/dist/sql-injection.js +108 -0
  113. package/dist/sql-injection.js.map +1 -0
  114. package/dist/unsafe-regex.d.ts +4 -0
  115. package/dist/unsafe-regex.d.ts.map +1 -0
  116. package/dist/unsafe-regex.js +75 -0
  117. package/dist/unsafe-regex.js.map +1 -0
  118. package/dist/unused-imports.d.ts +4 -0
  119. package/dist/unused-imports.d.ts.map +1 -0
  120. package/dist/unused-imports.js +56 -0
  121. package/dist/unused-imports.js.map +1 -0
  122. package/package.json +32 -0
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=advanced-rules.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"advanced-rules.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/advanced-rules.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const vitest_1 = require("vitest");
7
+ const core_1 = require("@guardrail-ai/core");
8
+ const unsafe_regex_js_1 = __importDefault(require("../unsafe-regex.js"));
9
+ const no_eval_js_1 = __importDefault(require("../no-eval.js"));
10
+ const no_secrets_in_logs_js_1 = __importDefault(require("../no-secrets-in-logs.js"));
11
+ function detect(rule, source, file = 'test.js') {
12
+ const ast = (0, core_1.parseSource)(source, file);
13
+ return rule.detect({ filePath: file, source, ast });
14
+ }
15
+ (0, vitest_1.describe)('security/unsafe-regex', () => {
16
+ (0, vitest_1.it)('detects ReDoS patterns', () => {
17
+ const v = detect(unsafe_regex_js_1.default, 'const re = /(a+)+$/;');
18
+ (0, vitest_1.expect)(v).toHaveLength(1);
19
+ (0, vitest_1.expect)(v[0].ruleId).toBe('security/unsafe-regex');
20
+ });
21
+ (0, vitest_1.it)('detects ReDoS in new RegExp', () => {
22
+ const v = detect(unsafe_regex_js_1.default, 'const re = new RegExp("(a+)+");');
23
+ (0, vitest_1.expect)(v).toHaveLength(1);
24
+ });
25
+ (0, vitest_1.it)('ignores safe regex', () => {
26
+ const v = detect(unsafe_regex_js_1.default, 'const re = /^[a-z]+$/;');
27
+ (0, vitest_1.expect)(v).toHaveLength(0);
28
+ });
29
+ });
30
+ (0, vitest_1.describe)('security/no-eval', () => {
31
+ (0, vitest_1.it)('detects eval()', () => {
32
+ const v = detect(no_eval_js_1.default, 'eval("console.log(1)");');
33
+ (0, vitest_1.expect)(v).toHaveLength(1);
34
+ (0, vitest_1.expect)(v[0].severity).toBe('critical');
35
+ });
36
+ (0, vitest_1.it)('detects new Function()', () => {
37
+ const v = detect(no_eval_js_1.default, 'const fn = new Function("return 1");');
38
+ (0, vitest_1.expect)(v).toHaveLength(1);
39
+ });
40
+ (0, vitest_1.it)('ignores safe code', () => {
41
+ const v = detect(no_eval_js_1.default, 'const x = JSON.parse("{}");');
42
+ (0, vitest_1.expect)(v).toHaveLength(0);
43
+ });
44
+ });
45
+ (0, vitest_1.describe)('security/no-secrets-in-logs', () => {
46
+ (0, vitest_1.it)('detects sensitive variable in console.log', () => {
47
+ const v = detect(no_secrets_in_logs_js_1.default, 'console.log(password);');
48
+ (0, vitest_1.expect)(v).toHaveLength(1);
49
+ });
50
+ (0, vitest_1.it)('detects sensitive property in console.log', () => {
51
+ const v = detect(no_secrets_in_logs_js_1.default, 'console.log(user.secretKey);');
52
+ (0, vitest_1.expect)(v).toHaveLength(1);
53
+ });
54
+ (0, vitest_1.it)('ignores non-sensitive logging', () => {
55
+ const v = detect(no_secrets_in_logs_js_1.default, 'console.log(username);');
56
+ (0, vitest_1.expect)(v).toHaveLength(0);
57
+ });
58
+ });
59
+ //# sourceMappingURL=advanced-rules.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"advanced-rules.test.js","sourceRoot":"","sources":["../../src/__tests__/advanced-rules.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=dead-code.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dead-code.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/dead-code.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const vitest_1 = require("vitest");
7
+ const core_1 = require("@guardrail-ai/core");
8
+ const dead_code_js_1 = __importDefault(require("../dead-code.js"));
9
+ function detect(source) {
10
+ const ast = (0, core_1.parseSource)(source, 'test.js');
11
+ return dead_code_js_1.default.detect({ filePath: 'test.js', source, ast });
12
+ }
13
+ (0, vitest_1.describe)('quality/dead-code', () => {
14
+ (0, vitest_1.it)('detects unreachable code after return', () => {
15
+ const v = detect(`
16
+ function foo() {
17
+ return 1;
18
+ console.log("dead");
19
+ }
20
+ foo();
21
+ `);
22
+ (0, vitest_1.expect)(v.some((x) => x.message.includes('Unreachable'))).toBe(true);
23
+ });
24
+ (0, vitest_1.it)('detects unreachable code after throw', () => {
25
+ const v = detect(`
26
+ function foo() {
27
+ throw new Error("x");
28
+ console.log("dead");
29
+ }
30
+ foo();
31
+ `);
32
+ (0, vitest_1.expect)(v.some((x) => x.message.includes('Unreachable'))).toBe(true);
33
+ });
34
+ (0, vitest_1.it)('detects empty catch block', () => {
35
+ const v = detect(`
36
+ try { x(); } catch (e) {}
37
+ `);
38
+ (0, vitest_1.expect)(v.some((x) => x.message.includes('Empty catch'))).toBe(true);
39
+ });
40
+ (0, vitest_1.it)('allows catch block with comment', () => {
41
+ const v = detect(`
42
+ try { x(); } catch (e) { /* intentionally empty */ }
43
+ `);
44
+ (0, vitest_1.expect)(v.filter((x) => x.message.includes('Empty catch'))).toHaveLength(0);
45
+ });
46
+ (0, vitest_1.it)('detects unused function', () => {
47
+ const v = detect(`
48
+ function unused() { return 1; }
49
+ `);
50
+ (0, vitest_1.expect)(v.some((x) => x.message.includes('never used'))).toBe(true);
51
+ });
52
+ (0, vitest_1.it)('does not flag exported functions', () => {
53
+ const v = detect(`
54
+ export function used() { return 1; }
55
+ `);
56
+ (0, vitest_1.expect)(v.filter((x) => x.message.includes('never used'))).toHaveLength(0);
57
+ });
58
+ (0, vitest_1.it)('does not flag called functions', () => {
59
+ const v = detect(`
60
+ function helper() { return 1; }
61
+ helper();
62
+ `);
63
+ (0, vitest_1.expect)(v.filter((x) => x.message.includes('never used'))).toHaveLength(0);
64
+ });
65
+ });
66
+ //# sourceMappingURL=dead-code.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dead-code.test.js","sourceRoot":"","sources":["../../src/__tests__/dead-code.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=duplicate-logic.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"duplicate-logic.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/duplicate-logic.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const vitest_1 = require("vitest");
7
+ const core_1 = require("@guardrail-ai/core");
8
+ const duplicate_logic_js_1 = __importDefault(require("../duplicate-logic.js"));
9
+ function detect(source) {
10
+ const ast = (0, core_1.parseSource)(source, 'test.js');
11
+ return duplicate_logic_js_1.default.detect({ filePath: 'test.js', source, ast });
12
+ }
13
+ (0, vitest_1.describe)('quality/duplicate-logic', () => {
14
+ (0, vitest_1.it)('detects identical function bodies', () => {
15
+ const v = detect(`
16
+ function calcA(amount) {
17
+ const rate = 0.15;
18
+ const base = amount * rate;
19
+ const surcharge = base > 1000 ? base * 0.05 : 0;
20
+ return base + surcharge;
21
+ }
22
+ function calcB(amount) {
23
+ const rate = 0.15;
24
+ const base = amount * rate;
25
+ const surcharge = base > 1000 ? base * 0.05 : 0;
26
+ return base + surcharge;
27
+ }
28
+ `);
29
+ (0, vitest_1.expect)(v.length).toBeGreaterThanOrEqual(1);
30
+ (0, vitest_1.expect)(v[0].ruleId).toBe('quality/duplicate-logic');
31
+ });
32
+ (0, vitest_1.it)('does not flag different function bodies', () => {
33
+ const v = detect(`
34
+ function add(a, b) { return a + b; }
35
+ function sub(a, b) { return a - b; }
36
+ `);
37
+ (0, vitest_1.expect)(v).toHaveLength(0);
38
+ });
39
+ (0, vitest_1.it)('ignores small functions', () => {
40
+ const v = detect(`
41
+ function a() { return 1; }
42
+ function b() { return 1; }
43
+ `);
44
+ (0, vitest_1.expect)(v).toHaveLength(0);
45
+ });
46
+ });
47
+ //# sourceMappingURL=duplicate-logic.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"duplicate-logic.test.js","sourceRoot":"","sources":["../../src/__tests__/duplicate-logic.test.ts"],"names":[],"mappings":";;;;;AAAA,mCAA8C;AAC9C,6CAAiD;AACjD,+EAAyC;AAEzC,SAAS,MAAM,CAAC,MAAc;IAC5B,MAAM,GAAG,GAAG,IAAA,kBAAW,EAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IAC3C,OAAO,4BAAI,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;AAC3D,CAAC;AAED,IAAA,iBAAQ,EAAC,yBAAyB,EAAE,GAAG,EAAE;IACvC,IAAA,WAAE,EAAC,mCAAmC,EAAE,GAAG,EAAE;QAC3C,MAAM,CAAC,GAAG,MAAM,CAAC;;;;;;;;;;;;;CAapB,CAAC,CAAC;QACC,IAAA,eAAM,EAAC,CAAC,CAAC,MAAM,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC;QAC3C,IAAA,eAAM,EAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,yCAAyC,EAAE,GAAG,EAAE;QACjD,MAAM,CAAC,GAAG,MAAM,CAAC;;;CAGpB,CAAC,CAAC;QACC,IAAA,eAAM,EAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAC5B,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,yBAAyB,EAAE,GAAG,EAAE;QACjC,MAAM,CAAC,GAAG,MAAM,CAAC;;;CAGpB,CAAC,CAAC;QACC,IAAA,eAAM,EAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAC5B,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=hardcoded-api-key.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hardcoded-api-key.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/hardcoded-api-key.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const vitest_1 = require("vitest");
7
+ const core_1 = require("@guardrail-ai/core");
8
+ const hardcoded_api_key_js_1 = __importDefault(require("../hardcoded-api-key.js"));
9
+ function detect(source) {
10
+ const ast = (0, core_1.parseSource)(source, 'test.js');
11
+ return hardcoded_api_key_js_1.default.detect({ filePath: 'test.js', source, ast });
12
+ }
13
+ (0, vitest_1.describe)('security/hardcoded-api-key', () => {
14
+ (0, vitest_1.it)('detects hardcoded API key in variable', () => {
15
+ const v = detect('const API_KEY = "sk-abc12345678901234567890123456789";');
16
+ (0, vitest_1.expect)(v.length).toBeGreaterThanOrEqual(1);
17
+ (0, vitest_1.expect)(v[0].ruleId).toBe('security/hardcoded-api-key');
18
+ });
19
+ (0, vitest_1.it)('detects hardcoded password', () => {
20
+ const v = detect('const password = "super-secret-password-123";');
21
+ (0, vitest_1.expect)(v.length).toBeGreaterThanOrEqual(1);
22
+ });
23
+ (0, vitest_1.it)('detects hardcoded token in object property', () => {
24
+ const v = detect('const cfg = { secret_token: "abcdefghijklmnop" };');
25
+ (0, vitest_1.expect)(v.length).toBeGreaterThanOrEqual(1);
26
+ });
27
+ (0, vitest_1.it)('detects JWT-like string literal', () => {
28
+ const v = detect('fetch("/api", { headers: { Authorization: "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.abc123def456" } });');
29
+ (0, vitest_1.expect)(v.length).toBeGreaterThanOrEqual(1);
30
+ });
31
+ (0, vitest_1.it)('ignores short strings', () => {
32
+ const v = detect('const password = "short";');
33
+ (0, vitest_1.expect)(v).toHaveLength(0);
34
+ });
35
+ (0, vitest_1.it)('ignores env variable usage', () => {
36
+ const v = detect('const apiKey = process.env.API_KEY;');
37
+ (0, vitest_1.expect)(v).toHaveLength(0);
38
+ });
39
+ (0, vitest_1.it)('ignores non-suspicious variable names', () => {
40
+ const v = detect('const greeting = "hello world and some extra text";');
41
+ (0, vitest_1.expect)(v).toHaveLength(0);
42
+ });
43
+ });
44
+ //# sourceMappingURL=hardcoded-api-key.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hardcoded-api-key.test.js","sourceRoot":"","sources":["../../src/__tests__/hardcoded-api-key.test.ts"],"names":[],"mappings":";;;;;AAAA,mCAA8C;AAC9C,6CAAiD;AACjD,mFAA2C;AAE3C,SAAS,MAAM,CAAC,MAAc;IAC5B,MAAM,GAAG,GAAG,IAAA,kBAAW,EAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IAC3C,OAAO,8BAAI,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;AAC3D,CAAC;AAED,IAAA,iBAAQ,EAAC,4BAA4B,EAAE,GAAG,EAAE;IAC1C,IAAA,WAAE,EAAC,uCAAuC,EAAE,GAAG,EAAE;QAC/C,MAAM,CAAC,GAAG,MAAM,CAAC,wDAAwD,CAAC,CAAC;QAC3E,IAAA,eAAM,EAAC,CAAC,CAAC,MAAM,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC;QAC3C,IAAA,eAAM,EAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,4BAA4B,EAAE,GAAG,EAAE;QACpC,MAAM,CAAC,GAAG,MAAM,CAAC,+CAA+C,CAAC,CAAC;QAClE,IAAA,eAAM,EAAC,CAAC,CAAC,MAAM,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,4CAA4C,EAAE,GAAG,EAAE;QACpD,MAAM,CAAC,GAAG,MAAM,CAAC,mDAAmD,CAAC,CAAC;QACtE,IAAA,eAAM,EAAC,CAAC,CAAC,MAAM,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,iCAAiC,EAAE,GAAG,EAAE;QACzC,MAAM,CAAC,GAAG,MAAM,CAAC,iHAAiH,CAAC,CAAC;QACpI,IAAA,eAAM,EAAC,CAAC,CAAC,MAAM,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,uBAAuB,EAAE,GAAG,EAAE;QAC/B,MAAM,CAAC,GAAG,MAAM,CAAC,2BAA2B,CAAC,CAAC;QAC9C,IAAA,eAAM,EAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAC5B,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,4BAA4B,EAAE,GAAG,EAAE;QACpC,MAAM,CAAC,GAAG,MAAM,CAAC,qCAAqC,CAAC,CAAC;QACxD,IAAA,eAAM,EAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAC5B,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,uCAAuC,EAAE,GAAG,EAAE;QAC/C,MAAM,CAAC,GAAG,MAAM,CAAC,qDAAqD,CAAC,CAAC;QACxE,IAAA,eAAM,EAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAC5B,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=inefficient-loop.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inefficient-loop.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/inefficient-loop.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const vitest_1 = require("vitest");
7
+ const core_1 = require("@guardrail-ai/core");
8
+ const inefficient_loop_js_1 = __importDefault(require("../inefficient-loop.js"));
9
+ function detect(source) {
10
+ const ast = (0, core_1.parseSource)(source, 'test.js');
11
+ return inefficient_loop_js_1.default.detect({ filePath: 'test.js', source, ast });
12
+ }
13
+ (0, vitest_1.describe)('performance/inefficient-loop', () => {
14
+ (0, vitest_1.it)('detects uncached array length', () => {
15
+ const src = 'var arr = [1,2,3]; for (var i = 0; i < arr.length; i++) { console.log(arr[i]); }';
16
+ const v = detect(src);
17
+ (0, vitest_1.expect)(v.length).toBeGreaterThanOrEqual(1);
18
+ (0, vitest_1.expect)(v[0].ruleId).toBe('performance/inefficient-loop');
19
+ });
20
+ (0, vitest_1.it)('ignores cached array length', () => {
21
+ const src = 'var arr = [1,2,3]; var len = arr.length; for (var i = 0; i < len; i++) { console.log(arr[i]); }';
22
+ const v = detect(src);
23
+ (0, vitest_1.expect)(v).toHaveLength(0);
24
+ });
25
+ (0, vitest_1.it)('detects sequential await in loop', () => {
26
+ const v = detect(`
27
+ async function f(urls) {
28
+ for (const url of urls) {
29
+ await fetch(url);
30
+ }
31
+ }
32
+ f([]);
33
+ `);
34
+ (0, vitest_1.expect)(v.some((x) => x.message.includes('Sequential await'))).toBe(true);
35
+ });
36
+ (0, vitest_1.it)('ignores await in nested function inside loop', () => {
37
+ const v = detect(`
38
+ async function f(items) {
39
+ for (const item of items) {
40
+ const handler = async () => { await process(item); };
41
+ handler();
42
+ }
43
+ }
44
+ f([]);
45
+ `);
46
+ (0, vitest_1.expect)(v.filter((x) => x.message.includes('Sequential await'))).toHaveLength(0);
47
+ });
48
+ });
49
+ //# sourceMappingURL=inefficient-loop.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inefficient-loop.test.js","sourceRoot":"","sources":["../../src/__tests__/inefficient-loop.test.ts"],"names":[],"mappings":";;;;;AAAA,mCAA8C;AAC9C,6CAAiD;AACjD,iFAA0C;AAE1C,SAAS,MAAM,CAAC,MAAc;IAC5B,MAAM,GAAG,GAAG,IAAA,kBAAW,EAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IAC3C,OAAO,6BAAI,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;AAC3D,CAAC;AAED,IAAA,iBAAQ,EAAC,8BAA8B,EAAE,GAAG,EAAE;IAC5C,IAAA,WAAE,EAAC,+BAA+B,EAAE,GAAG,EAAE;QACvC,MAAM,GAAG,GAAG,kFAAkF,CAAC;QAC/F,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;QACtB,IAAA,eAAM,EAAC,CAAC,CAAC,MAAM,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC;QAC3C,IAAA,eAAM,EAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,6BAA6B,EAAE,GAAG,EAAE;QACrC,MAAM,GAAG,GAAG,iGAAiG,CAAC;QAC9G,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;QACtB,IAAA,eAAM,EAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAC5B,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,kCAAkC,EAAE,GAAG,EAAE;QAC1C,MAAM,CAAC,GAAG,MAAM,CAAC;;;;;;;CAOpB,CAAC,CAAC;QACC,IAAA,eAAM,EAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC3E,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,8CAA8C,EAAE,GAAG,EAAE;QACtD,MAAM,CAAC,GAAG,MAAM,CAAC;;;;;;;;CAQpB,CAAC,CAAC;QACC,IAAA,eAAM,EAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAClF,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=new-rules.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"new-rules.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/new-rules.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,193 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const vitest_1 = require("vitest");
7
+ const core_1 = require("@guardrail-ai/core");
8
+ const hallucinated_import_js_1 = __importDefault(require("../hallucinated-import.js"));
9
+ const placeholder_code_js_1 = __importDefault(require("../placeholder-code.js"));
10
+ const hardcoded_localhost_js_1 = __importDefault(require("../hardcoded-localhost.js"));
11
+ const console_log_spam_js_1 = __importDefault(require("../console-log-spam.js"));
12
+ const overly_broad_catch_js_1 = __importDefault(require("../overly-broad-catch.js"));
13
+ const unused_imports_js_1 = __importDefault(require("../unused-imports.js"));
14
+ const any_type_abuse_js_1 = __importDefault(require("../any-type-abuse.js"));
15
+ const fetch_without_error_handling_js_1 = __importDefault(require("../fetch-without-error-handling.js"));
16
+ const promise_without_catch_js_1 = __importDefault(require("../promise-without-catch.js"));
17
+ const magic_numbers_js_1 = __importDefault(require("../magic-numbers.js"));
18
+ const insecure_cors_js_1 = __importDefault(require("../insecure-cors.js"));
19
+ const env_var_leak_js_1 = __importDefault(require("../env-var-leak.js"));
20
+ const no_rate_limiting_js_1 = __importDefault(require("../no-rate-limiting.js"));
21
+ const n_plus_one_query_js_1 = __importDefault(require("../n-plus-one-query.js"));
22
+ function detect(rule, source, file = 'test.js') {
23
+ const ast = (0, core_1.parseSource)(source, file);
24
+ return rule.detect({ filePath: file, source, ast });
25
+ }
26
+ // --- AI-Codegen Rules ---
27
+ (0, vitest_1.describe)('ai-codegen/hallucinated-import', () => {
28
+ (0, vitest_1.it)('detects known hallucinated package', () => {
29
+ const v = detect(hallucinated_import_js_1.default, 'import { foo } from "validation-utils";');
30
+ (0, vitest_1.expect)(v.length).toBeGreaterThanOrEqual(1);
31
+ });
32
+ (0, vitest_1.it)('ignores real packages', () => {
33
+ const v = detect(hallucinated_import_js_1.default, 'import express from "express";');
34
+ (0, vitest_1.expect)(v).toHaveLength(0);
35
+ });
36
+ (0, vitest_1.it)('ignores relative imports', () => {
37
+ const v = detect(hallucinated_import_js_1.default, 'import { foo } from "./utils";');
38
+ (0, vitest_1.expect)(v).toHaveLength(0);
39
+ });
40
+ });
41
+ (0, vitest_1.describe)('ai-codegen/placeholder-code', () => {
42
+ (0, vitest_1.it)('detects TODO comments', () => {
43
+ const v = detect(placeholder_code_js_1.default, '// TODO: implement this');
44
+ (0, vitest_1.expect)(v.length).toBeGreaterThanOrEqual(1);
45
+ });
46
+ (0, vitest_1.it)('detects example.com URLs', () => {
47
+ const v = detect(placeholder_code_js_1.default, 'const url = "https://example.com/api";');
48
+ (0, vitest_1.expect)(v.length).toBeGreaterThanOrEqual(1);
49
+ });
50
+ (0, vitest_1.it)('ignores normal strings', () => {
51
+ const v = detect(placeholder_code_js_1.default, 'const name = "production-api.myapp.com";');
52
+ (0, vitest_1.expect)(v).toHaveLength(0);
53
+ });
54
+ });
55
+ (0, vitest_1.describe)('ai-codegen/hardcoded-localhost', () => {
56
+ (0, vitest_1.it)('detects localhost URL', () => {
57
+ const v = detect(hardcoded_localhost_js_1.default, 'const url = "http://localhost:3000/api";');
58
+ (0, vitest_1.expect)(v).toHaveLength(1);
59
+ });
60
+ (0, vitest_1.it)('detects 127.0.0.1', () => {
61
+ const v = detect(hardcoded_localhost_js_1.default, 'fetch("http://127.0.0.1:8080");');
62
+ (0, vitest_1.expect)(v).toHaveLength(1);
63
+ });
64
+ (0, vitest_1.it)('ignores production URLs', () => {
65
+ const v = detect(hardcoded_localhost_js_1.default, 'const url = "https://api.myapp.com";');
66
+ (0, vitest_1.expect)(v).toHaveLength(0);
67
+ });
68
+ });
69
+ (0, vitest_1.describe)('ai-codegen/console-log-spam', () => {
70
+ (0, vitest_1.it)('detects console.log', () => {
71
+ const v = detect(console_log_spam_js_1.default, 'console.log("test");');
72
+ (0, vitest_1.expect)(v).toHaveLength(1);
73
+ (0, vitest_1.expect)(v[0].fix).toBeDefined();
74
+ });
75
+ (0, vitest_1.it)('ignores console.error', () => {
76
+ const v = detect(console_log_spam_js_1.default, 'console.error("critical failure");');
77
+ (0, vitest_1.expect)(v).toHaveLength(0);
78
+ });
79
+ (0, vitest_1.it)('ignores console.warn', () => {
80
+ const v = detect(console_log_spam_js_1.default, 'console.warn("deprecated");');
81
+ (0, vitest_1.expect)(v).toHaveLength(0);
82
+ });
83
+ });
84
+ (0, vitest_1.describe)('ai-codegen/overly-broad-catch', () => {
85
+ (0, vitest_1.it)('detects catch with only console.log', () => {
86
+ const v = detect(overly_broad_catch_js_1.default, 'try { x(); } catch (e) { console.log(e); }');
87
+ (0, vitest_1.expect)(v).toHaveLength(1);
88
+ });
89
+ (0, vitest_1.it)('ignores catch with rethrow', () => {
90
+ const v = detect(overly_broad_catch_js_1.default, 'try { x(); } catch (e) { console.log(e); throw e; }');
91
+ (0, vitest_1.expect)(v).toHaveLength(0);
92
+ });
93
+ });
94
+ (0, vitest_1.describe)('ai-codegen/unused-imports', () => {
95
+ (0, vitest_1.it)('detects unused import', () => {
96
+ const v = detect(unused_imports_js_1.default, 'import { unused } from "mod"; const x = 1;');
97
+ (0, vitest_1.expect)(v).toHaveLength(1);
98
+ });
99
+ (0, vitest_1.it)('ignores used import', () => {
100
+ const v = detect(unused_imports_js_1.default, 'import { used } from "mod"; used();');
101
+ (0, vitest_1.expect)(v).toHaveLength(0);
102
+ });
103
+ });
104
+ (0, vitest_1.describe)('ai-codegen/any-type-abuse', () => {
105
+ (0, vitest_1.it)('detects : any in TS files', () => {
106
+ const v = detect(any_type_abuse_js_1.default, 'const x: any = 1;', 'test.ts');
107
+ (0, vitest_1.expect)(v).toHaveLength(1);
108
+ });
109
+ (0, vitest_1.it)('skips JS files', () => {
110
+ const v = detect(any_type_abuse_js_1.default, 'const x = 1;', 'test.js');
111
+ (0, vitest_1.expect)(v).toHaveLength(0);
112
+ });
113
+ });
114
+ (0, vitest_1.describe)('ai-codegen/fetch-without-error-handling', () => {
115
+ (0, vitest_1.it)('detects unhandled fetch', () => {
116
+ const v = detect(fetch_without_error_handling_js_1.default, 'async function f() { const r = await fetch("/api"); }');
117
+ (0, vitest_1.expect)(v.length).toBeGreaterThanOrEqual(1);
118
+ });
119
+ (0, vitest_1.it)('ignores fetch in try/catch', () => {
120
+ const v = detect(fetch_without_error_handling_js_1.default, 'async function f() { try { await fetch("/api"); } catch(e) { throw e; } }');
121
+ (0, vitest_1.expect)(v).toHaveLength(0);
122
+ });
123
+ });
124
+ (0, vitest_1.describe)('ai-codegen/promise-without-catch', () => {
125
+ (0, vitest_1.it)('detects .then without .catch', () => {
126
+ const v = detect(promise_without_catch_js_1.default, 'fetch("/api").then(r => r.json());');
127
+ (0, vitest_1.expect)(v.length).toBeGreaterThanOrEqual(1);
128
+ });
129
+ (0, vitest_1.it)('ignores .then with .catch', () => {
130
+ const v = detect(promise_without_catch_js_1.default, 'fetch("/api").then(r => r.json()).catch(e => console.error(e));');
131
+ (0, vitest_1.expect)(v).toHaveLength(0);
132
+ });
133
+ });
134
+ (0, vitest_1.describe)('ai-codegen/magic-numbers', () => {
135
+ (0, vitest_1.it)('detects magic numbers', () => {
136
+ const v = detect(magic_numbers_js_1.default, 'const result = value * 3.14159;');
137
+ (0, vitest_1.expect)(v).toHaveLength(1);
138
+ });
139
+ (0, vitest_1.it)('ignores 0 and 1', () => {
140
+ const v = detect(magic_numbers_js_1.default, 'const x = arr[0]; const y = x + 1;');
141
+ (0, vitest_1.expect)(v).toHaveLength(0);
142
+ });
143
+ });
144
+ // --- Security Rules ---
145
+ (0, vitest_1.describe)('security/insecure-cors', () => {
146
+ (0, vitest_1.it)('detects cors() with no args', () => {
147
+ const v = detect(insecure_cors_js_1.default, 'app.use(cors());');
148
+ (0, vitest_1.expect)(v).toHaveLength(1);
149
+ });
150
+ (0, vitest_1.it)('detects cors({ origin: "*" })', () => {
151
+ const v = detect(insecure_cors_js_1.default, 'app.use(cors({ origin: "*" }));');
152
+ (0, vitest_1.expect)(v).toHaveLength(1);
153
+ });
154
+ (0, vitest_1.it)('ignores cors with specific origin', () => {
155
+ const v = detect(insecure_cors_js_1.default, 'app.use(cors({ origin: "https://myapp.com" }));');
156
+ (0, vitest_1.expect)(v).toHaveLength(0);
157
+ });
158
+ });
159
+ (0, vitest_1.describe)('security/env-var-leak', () => {
160
+ (0, vitest_1.it)('detects process.env in console.log', () => {
161
+ const v = detect(env_var_leak_js_1.default, 'console.log(process.env.SECRET);');
162
+ (0, vitest_1.expect)(v).toHaveLength(1);
163
+ });
164
+ (0, vitest_1.it)('ignores non-env console.log', () => {
165
+ const v = detect(env_var_leak_js_1.default, 'console.log("hello");');
166
+ (0, vitest_1.expect)(v).toHaveLength(0);
167
+ });
168
+ });
169
+ (0, vitest_1.describe)('security/no-rate-limiting', () => {
170
+ (0, vitest_1.it)('detects express without rate limiting', () => {
171
+ const v = detect(no_rate_limiting_js_1.default, 'import express from "express"; const app = express();');
172
+ (0, vitest_1.expect)(v).toHaveLength(1);
173
+ });
174
+ (0, vitest_1.it)('passes when rate limiting is present', () => {
175
+ const v = detect(no_rate_limiting_js_1.default, 'import express from "express"; import rateLimit from "express-rate-limit";');
176
+ (0, vitest_1.expect)(v).toHaveLength(0);
177
+ });
178
+ });
179
+ (0, vitest_1.describe)('performance/n-plus-one-query', () => {
180
+ (0, vitest_1.it)('detects query inside loop', () => {
181
+ const v = detect(n_plus_one_query_js_1.default, `
182
+ for (const id of ids) {
183
+ db.query("SELECT * FROM posts WHERE user_id = ?", [id]);
184
+ }
185
+ `);
186
+ (0, vitest_1.expect)(v).toHaveLength(1);
187
+ });
188
+ (0, vitest_1.it)('ignores query outside loop', () => {
189
+ const v = detect(n_plus_one_query_js_1.default, 'db.query("SELECT * FROM posts");');
190
+ (0, vitest_1.expect)(v).toHaveLength(0);
191
+ });
192
+ });
193
+ //# sourceMappingURL=new-rules.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"new-rules.test.js","sourceRoot":"","sources":["../../src/__tests__/new-rules.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=sql-injection.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sql-injection.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/sql-injection.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const vitest_1 = require("vitest");
7
+ const core_1 = require("@guardrail-ai/core");
8
+ const sql_injection_js_1 = __importDefault(require("../sql-injection.js"));
9
+ function detect(source) {
10
+ const ast = (0, core_1.parseSource)(source, 'test.js');
11
+ return sql_injection_js_1.default.detect({ filePath: 'test.js', source, ast });
12
+ }
13
+ (0, vitest_1.describe)('security/sql-injection', () => {
14
+ (0, vitest_1.it)('detects string concatenation in query', () => {
15
+ const v = detect('db.query("SELECT * FROM users WHERE id = " + userId);');
16
+ (0, vitest_1.expect)(v).toHaveLength(1);
17
+ (0, vitest_1.expect)(v[0].ruleId).toBe('security/sql-injection');
18
+ });
19
+ (0, vitest_1.it)('detects template literal in query', () => {
20
+ const v = detect('db.query(`SELECT * FROM users WHERE id = ${userId}`);');
21
+ (0, vitest_1.expect)(v).toHaveLength(1);
22
+ });
23
+ (0, vitest_1.it)('detects execute method', () => {
24
+ const v = detect('conn.execute("DELETE FROM users WHERE name = " + name);');
25
+ (0, vitest_1.expect)(v).toHaveLength(1);
26
+ });
27
+ (0, vitest_1.it)('ignores parameterized queries', () => {
28
+ const v = detect('db.query("SELECT * FROM users WHERE id = $1", [userId]);');
29
+ (0, vitest_1.expect)(v).toHaveLength(0);
30
+ });
31
+ (0, vitest_1.it)('ignores static string queries', () => {
32
+ const v = detect('db.query("SELECT * FROM users");');
33
+ (0, vitest_1.expect)(v).toHaveLength(0);
34
+ });
35
+ (0, vitest_1.it)('ignores non-SQL method calls', () => {
36
+ const v = detect('console.log("SELECT * FROM " + table);');
37
+ (0, vitest_1.expect)(v).toHaveLength(0);
38
+ });
39
+ });
40
+ //# sourceMappingURL=sql-injection.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sql-injection.test.js","sourceRoot":"","sources":["../../src/__tests__/sql-injection.test.ts"],"names":[],"mappings":";;;;;AAAA,mCAA8C;AAC9C,6CAAiD;AACjD,2EAAuC;AAEvC,SAAS,MAAM,CAAC,MAAc;IAC5B,MAAM,GAAG,GAAG,IAAA,kBAAW,EAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IAC3C,OAAO,0BAAI,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;AAC3D,CAAC;AAED,IAAA,iBAAQ,EAAC,wBAAwB,EAAE,GAAG,EAAE;IACtC,IAAA,WAAE,EAAC,uCAAuC,EAAE,GAAG,EAAE;QAC/C,MAAM,CAAC,GAAG,MAAM,CAAC,uDAAuD,CAAC,CAAC;QAC1E,IAAA,eAAM,EAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAC1B,IAAA,eAAM,EAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,mCAAmC,EAAE,GAAG,EAAE;QAC3C,MAAM,CAAC,GAAG,MAAM,CAAC,uDAAuD,CAAC,CAAC;QAC1E,IAAA,eAAM,EAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAC5B,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,wBAAwB,EAAE,GAAG,EAAE;QAChC,MAAM,CAAC,GAAG,MAAM,CAAC,yDAAyD,CAAC,CAAC;QAC5E,IAAA,eAAM,EAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAC5B,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,+BAA+B,EAAE,GAAG,EAAE;QACvC,MAAM,CAAC,GAAG,MAAM,CAAC,0DAA0D,CAAC,CAAC;QAC7E,IAAA,eAAM,EAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAC5B,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,+BAA+B,EAAE,GAAG,EAAE;QACvC,MAAM,CAAC,GAAG,MAAM,CAAC,kCAAkC,CAAC,CAAC;QACrD,IAAA,eAAM,EAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAC5B,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,8BAA8B,EAAE,GAAG,EAAE;QACtC,MAAM,CAAC,GAAG,MAAM,CAAC,wCAAwC,CAAC,CAAC;QAC3D,IAAA,eAAM,EAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAC5B,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { Rule } from '@guardrail-ai/core';
2
+ declare const anyTypeAbuseRule: Rule;
3
+ export default anyTypeAbuseRule;
4
+ //# sourceMappingURL=any-type-abuse.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"any-type-abuse.d.ts","sourceRoot":"","sources":["../src/any-type-abuse.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAA0B,MAAM,oBAAoB,CAAC;AAEvE,QAAA,MAAM,gBAAgB,EAAE,IAiCvB,CAAC;AAEF,eAAe,gBAAgB,CAAC"}