eslint-plugin-secure-coding 1.0.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 (155) hide show
  1. package/AGENTS.md +196 -0
  2. package/CHANGELOG.md +105 -0
  3. package/LICENSE +23 -0
  4. package/README.md +377 -0
  5. package/package.json +80 -0
  6. package/src/index.d.ts +32 -0
  7. package/src/index.js +345 -0
  8. package/src/index.js.map +1 -0
  9. package/src/rules/security/database-injection.d.ts +13 -0
  10. package/src/rules/security/database-injection.js +407 -0
  11. package/src/rules/security/database-injection.js.map +1 -0
  12. package/src/rules/security/detect-child-process.d.ts +11 -0
  13. package/src/rules/security/detect-child-process.js +460 -0
  14. package/src/rules/security/detect-child-process.js.map +1 -0
  15. package/src/rules/security/detect-eval-with-expression.d.ts +9 -0
  16. package/src/rules/security/detect-eval-with-expression.js +393 -0
  17. package/src/rules/security/detect-eval-with-expression.js.map +1 -0
  18. package/src/rules/security/detect-non-literal-fs-filename.d.ts +7 -0
  19. package/src/rules/security/detect-non-literal-fs-filename.js +322 -0
  20. package/src/rules/security/detect-non-literal-fs-filename.js.map +1 -0
  21. package/src/rules/security/detect-non-literal-regexp.d.ts +9 -0
  22. package/src/rules/security/detect-non-literal-regexp.js +387 -0
  23. package/src/rules/security/detect-non-literal-regexp.js.map +1 -0
  24. package/src/rules/security/detect-object-injection.d.ts +11 -0
  25. package/src/rules/security/detect-object-injection.js +411 -0
  26. package/src/rules/security/detect-object-injection.js.map +1 -0
  27. package/src/rules/security/no-buffer-overread.d.ts +14 -0
  28. package/src/rules/security/no-buffer-overread.js +519 -0
  29. package/src/rules/security/no-buffer-overread.js.map +1 -0
  30. package/src/rules/security/no-clickjacking.d.ts +10 -0
  31. package/src/rules/security/no-clickjacking.js +381 -0
  32. package/src/rules/security/no-clickjacking.js.map +1 -0
  33. package/src/rules/security/no-directive-injection.d.ts +12 -0
  34. package/src/rules/security/no-directive-injection.js +446 -0
  35. package/src/rules/security/no-directive-injection.js.map +1 -0
  36. package/src/rules/security/no-document-cookie.d.ts +5 -0
  37. package/src/rules/security/no-document-cookie.js +90 -0
  38. package/src/rules/security/no-document-cookie.js.map +1 -0
  39. package/src/rules/security/no-electron-security-issues.d.ts +10 -0
  40. package/src/rules/security/no-electron-security-issues.js +421 -0
  41. package/src/rules/security/no-electron-security-issues.js.map +1 -0
  42. package/src/rules/security/no-exposed-sensitive-data.d.ts +11 -0
  43. package/src/rules/security/no-exposed-sensitive-data.js +341 -0
  44. package/src/rules/security/no-exposed-sensitive-data.js.map +1 -0
  45. package/src/rules/security/no-format-string-injection.d.ts +17 -0
  46. package/src/rules/security/no-format-string-injection.js +653 -0
  47. package/src/rules/security/no-format-string-injection.js.map +1 -0
  48. package/src/rules/security/no-graphql-injection.d.ts +12 -0
  49. package/src/rules/security/no-graphql-injection.js +410 -0
  50. package/src/rules/security/no-graphql-injection.js.map +1 -0
  51. package/src/rules/security/no-hardcoded-credentials.d.ts +26 -0
  52. package/src/rules/security/no-hardcoded-credentials.js +377 -0
  53. package/src/rules/security/no-hardcoded-credentials.js.map +1 -0
  54. package/src/rules/security/no-improper-sanitization.d.ts +12 -0
  55. package/src/rules/security/no-improper-sanitization.js +408 -0
  56. package/src/rules/security/no-improper-sanitization.js.map +1 -0
  57. package/src/rules/security/no-improper-type-validation.d.ts +10 -0
  58. package/src/rules/security/no-improper-type-validation.js +420 -0
  59. package/src/rules/security/no-improper-type-validation.js.map +1 -0
  60. package/src/rules/security/no-insecure-comparison.d.ts +7 -0
  61. package/src/rules/security/no-insecure-comparison.js +125 -0
  62. package/src/rules/security/no-insecure-comparison.js.map +1 -0
  63. package/src/rules/security/no-insecure-cookie-settings.d.ts +9 -0
  64. package/src/rules/security/no-insecure-cookie-settings.js +305 -0
  65. package/src/rules/security/no-insecure-cookie-settings.js.map +1 -0
  66. package/src/rules/security/no-insecure-jwt.d.ts +10 -0
  67. package/src/rules/security/no-insecure-jwt.js +338 -0
  68. package/src/rules/security/no-insecure-jwt.js.map +1 -0
  69. package/src/rules/security/no-insecure-redirects.d.ts +7 -0
  70. package/src/rules/security/no-insecure-redirects.js +215 -0
  71. package/src/rules/security/no-insecure-redirects.js.map +1 -0
  72. package/src/rules/security/no-insufficient-postmessage-validation.d.ts +14 -0
  73. package/src/rules/security/no-insufficient-postmessage-validation.js +390 -0
  74. package/src/rules/security/no-insufficient-postmessage-validation.js.map +1 -0
  75. package/src/rules/security/no-insufficient-random.d.ts +9 -0
  76. package/src/rules/security/no-insufficient-random.js +207 -0
  77. package/src/rules/security/no-insufficient-random.js.map +1 -0
  78. package/src/rules/security/no-ldap-injection.d.ts +10 -0
  79. package/src/rules/security/no-ldap-injection.js +449 -0
  80. package/src/rules/security/no-ldap-injection.js.map +1 -0
  81. package/src/rules/security/no-missing-authentication.d.ts +13 -0
  82. package/src/rules/security/no-missing-authentication.js +322 -0
  83. package/src/rules/security/no-missing-authentication.js.map +1 -0
  84. package/src/rules/security/no-missing-cors-check.d.ts +9 -0
  85. package/src/rules/security/no-missing-cors-check.js +449 -0
  86. package/src/rules/security/no-missing-cors-check.js.map +1 -0
  87. package/src/rules/security/no-missing-csrf-protection.d.ts +11 -0
  88. package/src/rules/security/no-missing-csrf-protection.js +183 -0
  89. package/src/rules/security/no-missing-csrf-protection.js.map +1 -0
  90. package/src/rules/security/no-missing-security-headers.d.ts +7 -0
  91. package/src/rules/security/no-missing-security-headers.js +217 -0
  92. package/src/rules/security/no-missing-security-headers.js.map +1 -0
  93. package/src/rules/security/no-privilege-escalation.d.ts +13 -0
  94. package/src/rules/security/no-privilege-escalation.js +321 -0
  95. package/src/rules/security/no-privilege-escalation.js.map +1 -0
  96. package/src/rules/security/no-redos-vulnerable-regex.d.ts +7 -0
  97. package/src/rules/security/no-redos-vulnerable-regex.js +307 -0
  98. package/src/rules/security/no-redos-vulnerable-regex.js.map +1 -0
  99. package/src/rules/security/no-sensitive-data-exposure.d.ts +11 -0
  100. package/src/rules/security/no-sensitive-data-exposure.js +251 -0
  101. package/src/rules/security/no-sensitive-data-exposure.js.map +1 -0
  102. package/src/rules/security/no-sql-injection.d.ts +10 -0
  103. package/src/rules/security/no-sql-injection.js +332 -0
  104. package/src/rules/security/no-sql-injection.js.map +1 -0
  105. package/src/rules/security/no-timing-attack.d.ts +10 -0
  106. package/src/rules/security/no-timing-attack.js +358 -0
  107. package/src/rules/security/no-timing-attack.js.map +1 -0
  108. package/src/rules/security/no-toctou-vulnerability.d.ts +7 -0
  109. package/src/rules/security/no-toctou-vulnerability.js +165 -0
  110. package/src/rules/security/no-toctou-vulnerability.js.map +1 -0
  111. package/src/rules/security/no-unchecked-loop-condition.d.ts +12 -0
  112. package/src/rules/security/no-unchecked-loop-condition.js +635 -0
  113. package/src/rules/security/no-unchecked-loop-condition.js.map +1 -0
  114. package/src/rules/security/no-unencrypted-transmission.d.ts +11 -0
  115. package/src/rules/security/no-unencrypted-transmission.js +237 -0
  116. package/src/rules/security/no-unencrypted-transmission.js.map +1 -0
  117. package/src/rules/security/no-unescaped-url-parameter.d.ts +9 -0
  118. package/src/rules/security/no-unescaped-url-parameter.js +266 -0
  119. package/src/rules/security/no-unescaped-url-parameter.js.map +1 -0
  120. package/src/rules/security/no-unlimited-resource-allocation.d.ts +12 -0
  121. package/src/rules/security/no-unlimited-resource-allocation.js +659 -0
  122. package/src/rules/security/no-unlimited-resource-allocation.js.map +1 -0
  123. package/src/rules/security/no-unsafe-deserialization.d.ts +10 -0
  124. package/src/rules/security/no-unsafe-deserialization.js +501 -0
  125. package/src/rules/security/no-unsafe-deserialization.js.map +1 -0
  126. package/src/rules/security/no-unsafe-dynamic-require.d.ts +5 -0
  127. package/src/rules/security/no-unsafe-dynamic-require.js +107 -0
  128. package/src/rules/security/no-unsafe-dynamic-require.js.map +1 -0
  129. package/src/rules/security/no-unsafe-regex-construction.d.ts +9 -0
  130. package/src/rules/security/no-unsafe-regex-construction.js +292 -0
  131. package/src/rules/security/no-unsafe-regex-construction.js.map +1 -0
  132. package/src/rules/security/no-unsanitized-html.d.ts +9 -0
  133. package/src/rules/security/no-unsanitized-html.js +347 -0
  134. package/src/rules/security/no-unsanitized-html.js.map +1 -0
  135. package/src/rules/security/no-unvalidated-user-input.d.ts +9 -0
  136. package/src/rules/security/no-unvalidated-user-input.js +418 -0
  137. package/src/rules/security/no-unvalidated-user-input.js.map +1 -0
  138. package/src/rules/security/no-weak-crypto.d.ts +11 -0
  139. package/src/rules/security/no-weak-crypto.js +350 -0
  140. package/src/rules/security/no-weak-crypto.js.map +1 -0
  141. package/src/rules/security/no-weak-password-recovery.d.ts +12 -0
  142. package/src/rules/security/no-weak-password-recovery.js +401 -0
  143. package/src/rules/security/no-weak-password-recovery.js.map +1 -0
  144. package/src/rules/security/no-xpath-injection.d.ts +10 -0
  145. package/src/rules/security/no-xpath-injection.js +487 -0
  146. package/src/rules/security/no-xpath-injection.js.map +1 -0
  147. package/src/rules/security/no-xxe-injection.d.ts +7 -0
  148. package/src/rules/security/no-xxe-injection.js +270 -0
  149. package/src/rules/security/no-xxe-injection.js.map +1 -0
  150. package/src/rules/security/no-zip-slip.d.ts +9 -0
  151. package/src/rules/security/no-zip-slip.js +446 -0
  152. package/src/rules/security/no-zip-slip.js.map +1 -0
  153. package/src/types/index.d.ts +131 -0
  154. package/src/types/index.js +18 -0
  155. package/src/types/index.js.map +1 -0
@@ -0,0 +1,183 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.noMissingCsrfProtection = void 0;
4
+ const eslint_devkit_1 = require("@interlace/eslint-devkit");
5
+ const eslint_devkit_2 = require("@interlace/eslint-devkit");
6
+ /**
7
+ * Default CSRF middleware patterns
8
+ */
9
+ const DEFAULT_CSRF_MIDDLEWARE_PATTERNS = [
10
+ 'csrf',
11
+ 'csurf',
12
+ 'csrfProtection',
13
+ 'verifyCsrfToken',
14
+ 'csrfToken',
15
+ 'validateCsrf',
16
+ 'checkCsrf',
17
+ 'csrfMiddleware',
18
+ ];
19
+ /**
20
+ * Default HTTP methods that require CSRF protection
21
+ */
22
+ const DEFAULT_PROTECTED_METHODS = ['post', 'put', 'delete', 'patch'];
23
+ /**
24
+ * Check if a route handler method requires CSRF protection
25
+ */
26
+ function requiresCsrfProtection(methodName, protectedMethods) {
27
+ return protectedMethods.some(method => method.toLowerCase() === methodName.toLowerCase());
28
+ }
29
+ /**
30
+ * Check if a string matches any ignore pattern
31
+ */
32
+ function matchesIgnorePattern(text, patterns) {
33
+ return patterns.some(pattern => {
34
+ try {
35
+ const regex = new RegExp(pattern, 'i');
36
+ return regex.test(text);
37
+ }
38
+ catch {
39
+ return text.toLowerCase().includes(pattern.toLowerCase());
40
+ }
41
+ });
42
+ }
43
+ exports.noMissingCsrfProtection = (0, eslint_devkit_2.createRule)({
44
+ name: 'no-missing-csrf-protection',
45
+ meta: {
46
+ type: 'problem',
47
+ docs: {
48
+ description: 'Detects missing CSRF token validation in POST/PUT/DELETE requests',
49
+ },
50
+ hasSuggestions: true,
51
+ messages: {
52
+ missingCsrfProtection: (0, eslint_devkit_1.formatLLMMessage)({
53
+ icon: eslint_devkit_1.MessageIcons.SECURITY,
54
+ issueName: 'Missing CSRF Protection',
55
+ cwe: 'CWE-352',
56
+ description: 'Missing CSRF protection detected: {{issue}}',
57
+ severity: 'HIGH',
58
+ fix: '{{safeAlternative}}',
59
+ documentationLink: 'https://cwe.mitre.org/data/definitions/352.html',
60
+ }),
61
+ addCsrfValidation: (0, eslint_devkit_1.formatLLMMessage)({
62
+ icon: eslint_devkit_1.MessageIcons.INFO,
63
+ issueName: 'Add CSRF Validation',
64
+ description: 'Add CSRF middleware',
65
+ severity: 'LOW',
66
+ fix: 'app.use(csrf({ cookie: true }))',
67
+ documentationLink: 'https://github.com/expressjs/csurf',
68
+ }),
69
+ },
70
+ schema: [
71
+ {
72
+ type: 'object',
73
+ properties: {
74
+ allowInTests: {
75
+ type: 'boolean',
76
+ default: false,
77
+ description: 'Allow missing CSRF protection in test files',
78
+ },
79
+ csrfMiddlewarePatterns: {
80
+ type: 'array',
81
+ items: { type: 'string' },
82
+ default: [],
83
+ description: 'CSRF middleware patterns to recognize',
84
+ },
85
+ protectedMethods: {
86
+ type: 'array',
87
+ items: { type: 'string' },
88
+ default: [],
89
+ description: 'HTTP methods that require CSRF protection',
90
+ },
91
+ ignorePatterns: {
92
+ type: 'array',
93
+ items: { type: 'string' },
94
+ default: [],
95
+ description: 'Additional safe patterns to ignore',
96
+ },
97
+ },
98
+ additionalProperties: false,
99
+ },
100
+ ],
101
+ },
102
+ defaultOptions: [
103
+ {
104
+ allowInTests: false,
105
+ csrfMiddlewarePatterns: [],
106
+ protectedMethods: [],
107
+ ignorePatterns: [],
108
+ },
109
+ ],
110
+ create(context, [options = {}]) {
111
+ const { allowInTests = false, csrfMiddlewarePatterns, protectedMethods: customProtectedMethods, ignorePatterns = [], } = options;
112
+ const csrfPatterns = csrfMiddlewarePatterns && csrfMiddlewarePatterns.length > 0
113
+ ? csrfMiddlewarePatterns
114
+ : DEFAULT_CSRF_MIDDLEWARE_PATTERNS;
115
+ const protectedMethods = customProtectedMethods && customProtectedMethods.length > 0
116
+ ? customProtectedMethods
117
+ : DEFAULT_PROTECTED_METHODS;
118
+ const filename = context.getFilename();
119
+ const isTestFile = allowInTests && /\.(test|spec)\.(ts|tsx|js|jsx)$/.test(filename);
120
+ const sourceCode = context.sourceCode || context.sourceCode;
121
+ function checkCallExpression(node) {
122
+ if (isTestFile) {
123
+ return;
124
+ }
125
+ const callee = node.callee;
126
+ const callText = sourceCode.getText(node);
127
+ // Check if it matches any ignore pattern
128
+ if (matchesIgnorePattern(callText, ignorePatterns)) {
129
+ return;
130
+ }
131
+ // Check for route handler methods (app.post, router.put, etc.)
132
+ if (callee.type === 'MemberExpression' && callee.property.type === 'Identifier') {
133
+ const methodName = callee.property.name;
134
+ // Only check if it's a route handler that requires CSRF
135
+ if (requiresCsrfProtection(methodName, protectedMethods)) {
136
+ // Must have at least 2 arguments (path and handler)
137
+ if (node.arguments.length < 2) {
138
+ return;
139
+ }
140
+ // Check if CSRF middleware is in the route chain arguments
141
+ let hasCsrfInChain = false;
142
+ // Check if any argument (after the first path argument) is a CSRF middleware
143
+ // Skip the first argument (path) and check the rest
144
+ for (let i = 1; i < node.arguments.length; i++) {
145
+ const arg = node.arguments[i];
146
+ const argText = sourceCode.getText(arg);
147
+ if (csrfPatterns.some(pattern => argText.toLowerCase().includes(pattern.toLowerCase()))) {
148
+ hasCsrfInChain = true;
149
+ break;
150
+ }
151
+ }
152
+ if (!hasCsrfInChain) {
153
+ context.report({
154
+ node,
155
+ messageId: 'missingCsrfProtection',
156
+ data: {
157
+ issue: `${methodName.toUpperCase()} route handler missing CSRF protection`,
158
+ safeAlternative: `Add CSRF middleware: app.${methodName}("/path", csrf(), handler) or use app.use(csrf()) globally`,
159
+ },
160
+ suggest: [
161
+ {
162
+ messageId: 'addCsrfValidation',
163
+ fix(fixer) {
164
+ // Add CSRF middleware after the first argument (path)
165
+ const firstArg = node.arguments[0];
166
+ if (firstArg) {
167
+ return fixer.insertTextAfter(firstArg, ', csrf()');
168
+ }
169
+ return null;
170
+ },
171
+ },
172
+ ],
173
+ });
174
+ }
175
+ }
176
+ }
177
+ }
178
+ return {
179
+ CallExpression: checkCallExpression,
180
+ };
181
+ },
182
+ });
183
+ //# sourceMappingURL=no-missing-csrf-protection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-missing-csrf-protection.js","sourceRoot":"","sources":["../../../../../../packages/eslint-plugin-secure-coding/src/rules/security/no-missing-csrf-protection.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export interface Options {
2
+ /** Required security headers. Default: ['Content-Security-Policy', 'X-Frame-Options', 'X-Content-Type-Options'] */
3
+ requiredHeaders?: string[];
4
+ /** Ignore in test files. Default: true */
5
+ ignoreInTests?: boolean;
6
+ }
7
+ export declare const noMissingSecurityHeaders: ESLintUtils.RuleModule<MessageIds, Options, unknown, ESLintUtils.RuleListener>;
@@ -0,0 +1,217 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.noMissingSecurityHeaders = void 0;
4
+ const eslint_devkit_1 = require("@interlace/eslint-devkit");
5
+ const eslint_devkit_2 = require("@interlace/eslint-devkit");
6
+ const DEFAULT_REQUIRED_HEADERS = [
7
+ 'Content-Security-Policy',
8
+ 'X-Frame-Options',
9
+ 'X-Content-Type-Options',
10
+ ];
11
+ /**
12
+ * Extract header name from setHeader call
13
+ */
14
+ function extractHeaderName(node) {
15
+ if (node.arguments.length > 0 && node.arguments[0].type === 'Literal') {
16
+ return String(node.arguments[0].value);
17
+ }
18
+ return null;
19
+ }
20
+ /**
21
+ * Check if all security headers are set in the current scope
22
+ */
23
+ function checkFunctionForSecurityHeaders(node, requiredHeaders, context) {
24
+ const setHeaders = new Set();
25
+ // Find the function that contains this setHeader call
26
+ let current = node;
27
+ let scopeNode = null;
28
+ while (current) {
29
+ if (current.type === 'FunctionDeclaration' ||
30
+ current.type === 'FunctionExpression' ||
31
+ current.type === 'ArrowFunctionExpression') {
32
+ scopeNode = current;
33
+ break;
34
+ }
35
+ current = current.parent ?? null;
36
+ }
37
+ // If no function found, use the program scope (for test cases)
38
+ if (!scopeNode) {
39
+ scopeNode = context.sourceCode.ast;
40
+ }
41
+ // Collect all setHeader calls in this scope
42
+ function collectHeaders(node) {
43
+ if (node.type === 'CallExpression' &&
44
+ node.callee.type === 'MemberExpression' &&
45
+ node.callee.property.type === 'Identifier' &&
46
+ ['setHeader', 'header', 'set'].includes(node.callee.property.name)) {
47
+ const headerName = extractHeaderName(node);
48
+ if (headerName) {
49
+ setHeaders.add(headerName);
50
+ }
51
+ }
52
+ // Recursively check children - only traverse standard AST properties
53
+ if (node.type === 'Program' && node.body) {
54
+ node.body.forEach(collectHeaders);
55
+ }
56
+ else if ((node.type === 'FunctionDeclaration' ||
57
+ node.type === 'FunctionExpression' ||
58
+ node.type === 'ArrowFunctionExpression') && node.body) {
59
+ collectHeaders(node.body);
60
+ }
61
+ else if (node.type === 'BlockStatement' && node.body) {
62
+ node.body.forEach(collectHeaders);
63
+ }
64
+ else if (node.type === 'ExpressionStatement' && node.expression) {
65
+ collectHeaders(node.expression);
66
+ }
67
+ }
68
+ if (scopeNode) {
69
+ collectHeaders(scopeNode);
70
+ }
71
+ // Return missing headers
72
+ return requiredHeaders.filter(header => !setHeaders.has(header));
73
+ }
74
+ exports.noMissingSecurityHeaders = (0, eslint_devkit_2.createRule)({
75
+ name: 'no-missing-security-headers',
76
+ meta: {
77
+ type: 'problem',
78
+ docs: {
79
+ description: 'Detects missing security headers in HTTP responses',
80
+ },
81
+ hasSuggestions: true,
82
+ messages: {
83
+ missingSecurityHeader: (0, eslint_devkit_1.formatLLMMessage)({
84
+ icon: eslint_devkit_1.MessageIcons.SECURITY,
85
+ issueName: 'Missing security headers',
86
+ cwe: 'CWE-693',
87
+ description: 'Missing security headers: {{headers}}',
88
+ severity: 'HIGH',
89
+ fix: 'Set security headers: Content-Security-Policy, X-Frame-Options, X-Content-Type-Options',
90
+ documentationLink: 'https://owasp.org/www-project-secure-headers/',
91
+ }),
92
+ addSecurityHeaders: (0, eslint_devkit_1.formatLLMMessage)({
93
+ icon: eslint_devkit_1.MessageIcons.INFO,
94
+ issueName: 'Add Security Headers',
95
+ description: 'Add security headers middleware',
96
+ severity: 'LOW',
97
+ fix: 'Add Content-Security-Policy, X-Frame-Options headers',
98
+ documentationLink: 'https://owasp.org/www-project-secure-headers/',
99
+ }),
100
+ useMiddleware: (0, eslint_devkit_1.formatLLMMessage)({
101
+ icon: eslint_devkit_1.MessageIcons.INFO,
102
+ issueName: 'Use Helmet',
103
+ description: 'Use helmet.js for security headers',
104
+ severity: 'LOW',
105
+ fix: 'app.use(helmet())',
106
+ documentationLink: 'https://helmetjs.github.io/',
107
+ }),
108
+ setHeader: (0, eslint_devkit_1.formatLLMMessage)({
109
+ icon: eslint_devkit_1.MessageIcons.INFO,
110
+ issueName: 'Set Headers',
111
+ description: 'Set security headers manually',
112
+ severity: 'LOW',
113
+ fix: 'res.setHeader("X-Frame-Options", "DENY")',
114
+ documentationLink: 'https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers',
115
+ }),
116
+ },
117
+ schema: [
118
+ {
119
+ type: 'object',
120
+ properties: {
121
+ requiredHeaders: {
122
+ type: 'array',
123
+ items: { type: 'string' },
124
+ default: DEFAULT_REQUIRED_HEADERS,
125
+ },
126
+ ignoreInTests: {
127
+ type: 'boolean',
128
+ default: true,
129
+ },
130
+ },
131
+ additionalProperties: false,
132
+ },
133
+ ],
134
+ },
135
+ defaultOptions: [
136
+ {
137
+ requiredHeaders: DEFAULT_REQUIRED_HEADERS,
138
+ ignoreInTests: true,
139
+ },
140
+ ],
141
+ create(context, [options = {}]) {
142
+ const { requiredHeaders = DEFAULT_REQUIRED_HEADERS, ignoreInTests = true, } = options || {};
143
+ const filename = context.getFilename();
144
+ const isTestFile = ignoreInTests && /\.(test|spec)\.(ts|tsx|js|jsx)$/.test(filename);
145
+ if (isTestFile) {
146
+ return {};
147
+ }
148
+ const reportedScopes = new Set();
149
+ /**
150
+ * Get a unique key for the current scope
151
+ */
152
+ function getScopeKey(node) {
153
+ // Find the function that contains this call
154
+ let current = node;
155
+ while (current) {
156
+ if (current.type === 'FunctionDeclaration' ||
157
+ current.type === 'FunctionExpression' ||
158
+ current.type === 'ArrowFunctionExpression') {
159
+ return `${current.range?.[0]}-${current.range?.[1]}`;
160
+ }
161
+ current = current.parent ?? null;
162
+ }
163
+ // If no function found, use program scope
164
+ return 'program';
165
+ }
166
+ /**
167
+ * Check for response header setting
168
+ */
169
+ function checkCallExpression(node) {
170
+ // Check for res.setHeader, res.header, res.set
171
+ if (node.callee.type === 'MemberExpression' &&
172
+ node.callee.property.type === 'Identifier') {
173
+ const methodName = node.callee.property.name;
174
+ if (['setHeader', 'header', 'set'].includes(methodName)) {
175
+ const scopeKey = getScopeKey(node);
176
+ // Only check once per scope
177
+ if (reportedScopes.has(scopeKey)) {
178
+ return;
179
+ }
180
+ const missing = checkFunctionForSecurityHeaders(node, requiredHeaders, context);
181
+ if (missing.length > 0) {
182
+ reportedScopes.add(scopeKey);
183
+ context.report({
184
+ node,
185
+ messageId: 'missingSecurityHeader',
186
+ data: {
187
+ headers: missing.join(', '),
188
+ },
189
+ suggest: [
190
+ {
191
+ messageId: 'addSecurityHeaders',
192
+ fix: () => null,
193
+ },
194
+ {
195
+ messageId: 'useMiddleware',
196
+ fix: () => null,
197
+ },
198
+ {
199
+ messageId: 'setHeader',
200
+ fix: () => null,
201
+ },
202
+ ],
203
+ });
204
+ }
205
+ else {
206
+ // Mark as checked even if no error
207
+ reportedScopes.add(scopeKey);
208
+ }
209
+ }
210
+ }
211
+ }
212
+ return {
213
+ CallExpression: checkCallExpression,
214
+ };
215
+ },
216
+ });
217
+ //# sourceMappingURL=no-missing-security-headers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-missing-security-headers.js","sourceRoot":"","sources":["../../../../../../packages/eslint-plugin-secure-coding/src/rules/security/no-missing-security-headers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ export interface Options {
2
+ /** Allow privilege escalation patterns in test files. Default: false */
3
+ allowInTests?: boolean;
4
+ /** Test file pattern regex string. Default: '\\.(test|spec)\\.(ts|tsx|js|jsx)$' */
5
+ testFilePattern?: string;
6
+ /** Role check patterns to recognize. Default: ['hasRole', 'checkRole', 'isAdmin', 'isAuthorized'] */
7
+ roleCheckPatterns?: string[];
8
+ /** User input patterns that should be validated. Default: ['req.body', 'req.query', 'req.params'] */
9
+ userInputPatterns?: string[];
10
+ /** Additional patterns to ignore. Default: [] */
11
+ ignorePatterns?: string[];
12
+ }
13
+ export declare const noPrivilegeEscalation: ESLintUtils.RuleModule<MessageIds, Options, unknown, ESLintUtils.RuleListener>;