@sun-asterisk/sunlint 1.3.2 → 1.3.4
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/CHANGELOG.md +73 -0
- package/README.md +5 -3
- package/config/rules/enhanced-rules-registry.json +144 -33
- package/core/analysis-orchestrator.js +173 -42
- package/core/auto-performance-manager.js +243 -0
- package/core/cli-action-handler.js +24 -2
- package/core/cli-program.js +19 -5
- package/core/constants/defaults.js +56 -0
- package/core/performance-optimizer.js +271 -0
- package/docs/FILE_LIMITS_COMPLETION_REPORT.md +151 -0
- package/docs/FILE_LIMITS_EXPLANATION.md +190 -0
- package/docs/PERFORMANCE.md +311 -0
- package/docs/PERFORMANCE_MIGRATION_GUIDE.md +368 -0
- package/docs/PERFORMANCE_OPTIMIZATION_PLAN.md +255 -0
- package/docs/QUICK_FILE_LIMITS.md +64 -0
- package/docs/SIMPLIFIED_USAGE_GUIDE.md +208 -0
- package/engines/engine-factory.js +7 -0
- package/engines/heuristic-engine.js +182 -5
- package/package.json +2 -1
- package/rules/common/C048_no_bypass_architectural_layers/analyzer.js +180 -0
- package/rules/common/C048_no_bypass_architectural_layers/config.json +50 -0
- package/rules/common/C048_no_bypass_architectural_layers/symbol-based-analyzer.js +235 -0
- package/rules/common/C052_parsing_or_data_transformation/analyzer.js +180 -0
- package/rules/common/C052_parsing_or_data_transformation/config.json +50 -0
- package/rules/common/C052_parsing_or_data_transformation/symbol-based-analyzer.js +132 -0
- package/rules/index.js +2 -0
- package/rules/security/S017_use_parameterized_queries/README.md +128 -0
- package/rules/security/S017_use_parameterized_queries/analyzer.js +286 -0
- package/rules/security/S017_use_parameterized_queries/config.json +109 -0
- package/rules/security/S017_use_parameterized_queries/regex-based-analyzer.js +541 -0
- package/rules/security/S017_use_parameterized_queries/symbol-based-analyzer.js +777 -0
- package/rules/security/S031_secure_session_cookies/README.md +127 -0
- package/rules/security/S031_secure_session_cookies/analyzer.js +245 -0
- package/rules/security/S031_secure_session_cookies/config.json +86 -0
- package/rules/security/S031_secure_session_cookies/regex-based-analyzer.js +196 -0
- package/rules/security/S031_secure_session_cookies/symbol-based-analyzer.js +1084 -0
- package/rules/security/S032_httponly_session_cookies/FRAMEWORK_SUPPORT.md +209 -0
- package/rules/security/S032_httponly_session_cookies/README.md +184 -0
- package/rules/security/S032_httponly_session_cookies/analyzer.js +282 -0
- package/rules/security/S032_httponly_session_cookies/config.json +96 -0
- package/rules/security/S032_httponly_session_cookies/regex-based-analyzer.js +715 -0
- package/rules/security/S032_httponly_session_cookies/symbol-based-analyzer.js +1348 -0
- package/rules/security/S033_samesite_session_cookies/README.md +227 -0
- package/rules/security/S033_samesite_session_cookies/analyzer.js +242 -0
- package/rules/security/S033_samesite_session_cookies/config.json +87 -0
- package/rules/security/S033_samesite_session_cookies/regex-based-analyzer.js +703 -0
- package/rules/security/S033_samesite_session_cookies/symbol-based-analyzer.js +732 -0
- package/rules/security/S034_host_prefix_session_cookies/README.md +204 -0
- package/rules/security/S034_host_prefix_session_cookies/analyzer.js +290 -0
- package/rules/security/S034_host_prefix_session_cookies/config.json +62 -0
- package/rules/security/S034_host_prefix_session_cookies/regex-based-analyzer.js +478 -0
- package/rules/security/S034_host_prefix_session_cookies/symbol-based-analyzer.js +277 -0
- package/rules/security/S035_path_session_cookies/README.md +257 -0
- package/rules/security/S035_path_session_cookies/analyzer.js +316 -0
- package/rules/security/S035_path_session_cookies/config.json +99 -0
- package/rules/security/S035_path_session_cookies/regex-based-analyzer.js +724 -0
- package/rules/security/S035_path_session_cookies/symbol-based-analyzer.js +373 -0
- package/scripts/batch-processing-demo.js +334 -0
- package/scripts/performance-test.js +541 -0
- package/scripts/quick-performance-test.js +108 -0
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* S035 Main Analyzer - Set Path attribute for Session Cookies
|
|
3
|
+
* Primary: Symbol-based analysis (when available)
|
|
4
|
+
* Fallback: Regex-based for all other cases
|
|
5
|
+
* Command: node cli.js --rule=S035 --input=examples/rule-test-fixtures/rules/S035_path_session_cookies --engine=heuristic
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const S035SymbolBasedAnalyzer = require("./symbol-based-analyzer.js");
|
|
9
|
+
const S035RegexBasedAnalyzer = require("./regex-based-analyzer.js");
|
|
10
|
+
|
|
11
|
+
class S035Analyzer {
|
|
12
|
+
constructor(options = {}) {
|
|
13
|
+
if (process.env.SUNLINT_DEBUG) {
|
|
14
|
+
console.log(`🔧 [S035] Constructor called with options:`, !!options);
|
|
15
|
+
console.log(
|
|
16
|
+
`🔧 [S035] Options type:`,
|
|
17
|
+
typeof options,
|
|
18
|
+
Object.keys(options || {})
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
this.ruleId = "S035";
|
|
23
|
+
this.ruleName = "Set Path attribute for Session Cookies";
|
|
24
|
+
this.description =
|
|
25
|
+
"Set Path attribute for Session Cookies to limit access scope. This restricts where cookies can be sent, reducing the attack surface by limiting cookie access to specific paths.";
|
|
26
|
+
this.semanticEngine = options.semanticEngine || null;
|
|
27
|
+
this.verbose = options.verbose || false;
|
|
28
|
+
|
|
29
|
+
// Configuration - Use symbol-based as primary, regex for additional coverage
|
|
30
|
+
this.config = {
|
|
31
|
+
useSymbolBased: true, // Primary approach
|
|
32
|
+
fallbackToRegex: true, // Additional coverage
|
|
33
|
+
regexBasedOnly: false, // Can be set to true for pure mode
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
// Initialize analyzers
|
|
37
|
+
try {
|
|
38
|
+
this.symbolAnalyzer = new S035SymbolBasedAnalyzer(this.semanticEngine);
|
|
39
|
+
if (process.env.SUNLINT_DEBUG) {
|
|
40
|
+
console.log(`🔧 [S035] Symbol analyzer created successfully`);
|
|
41
|
+
}
|
|
42
|
+
} catch (error) {
|
|
43
|
+
console.error(`🔧 [S035] Error creating symbol analyzer:`, error);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
try {
|
|
47
|
+
this.regexAnalyzer = new S035RegexBasedAnalyzer(this.semanticEngine);
|
|
48
|
+
if (process.env.SUNLINT_DEBUG) {
|
|
49
|
+
console.log(`🔧 [S035] Regex analyzer created successfully`);
|
|
50
|
+
}
|
|
51
|
+
} catch (error) {
|
|
52
|
+
console.error(`🔧 [S035] Error creating regex analyzer:`, error);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Initialize analyzer with semantic engine
|
|
58
|
+
*/
|
|
59
|
+
async initialize(semanticEngine) {
|
|
60
|
+
this.semanticEngine = semanticEngine;
|
|
61
|
+
|
|
62
|
+
if (process.env.SUNLINT_DEBUG) {
|
|
63
|
+
console.log(`🔧 [S035] Main analyzer initializing...`);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Initialize both analyzers
|
|
67
|
+
if (this.symbolAnalyzer) {
|
|
68
|
+
await this.symbolAnalyzer.initialize?.(semanticEngine);
|
|
69
|
+
}
|
|
70
|
+
if (this.regexAnalyzer) {
|
|
71
|
+
await this.regexAnalyzer.initialize?.(semanticEngine);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Clean up if needed
|
|
75
|
+
if (this.regexAnalyzer) {
|
|
76
|
+
this.regexAnalyzer.cleanup?.();
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (process.env.SUNLINT_DEBUG) {
|
|
80
|
+
console.log(`🔧 [S035] Main analyzer initialized successfully`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Single file analysis method for testing
|
|
86
|
+
*/
|
|
87
|
+
analyzeSingle(filePath, options = {}) {
|
|
88
|
+
if (process.env.SUNLINT_DEBUG) {
|
|
89
|
+
console.log(`🔍 [S035] analyzeSingle() called for: ${filePath}`);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Return result using same format as analyze method
|
|
93
|
+
return this.analyze([filePath], "typescript", options);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
async analyze(files, language, options = {}) {
|
|
97
|
+
if (process.env.SUNLINT_DEBUG) {
|
|
98
|
+
console.log(
|
|
99
|
+
`🔧 [S035] analyze() method called with ${files.length} files, language: ${language}`
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const violations = [];
|
|
104
|
+
|
|
105
|
+
for (const filePath of files) {
|
|
106
|
+
try {
|
|
107
|
+
if (process.env.SUNLINT_DEBUG) {
|
|
108
|
+
console.log(`🔧 [S035] Processing file: ${filePath}`);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const fileViolations = await this.analyzeFile(filePath, options);
|
|
112
|
+
violations.push(...fileViolations);
|
|
113
|
+
|
|
114
|
+
if (process.env.SUNLINT_DEBUG) {
|
|
115
|
+
console.log(
|
|
116
|
+
`🔧 [S035] File ${filePath}: Found ${fileViolations.length} violations`
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
} catch (error) {
|
|
120
|
+
console.warn(
|
|
121
|
+
`⚠ [S035] Analysis failed for ${filePath}:`,
|
|
122
|
+
error.message
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (process.env.SUNLINT_DEBUG) {
|
|
128
|
+
console.log(`🔧 [S035] Total violations found: ${violations.length}`);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return violations;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
async analyzeFile(filePath, options = {}) {
|
|
135
|
+
if (process.env.SUNLINT_DEBUG) {
|
|
136
|
+
console.log(`🔍 [S035] analyzeFile() called for: ${filePath}`);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Create a Map to track unique violations and prevent duplicates
|
|
140
|
+
const violationMap = new Map();
|
|
141
|
+
const lineToViolationMap = new Map(); // Track which lines already have violations
|
|
142
|
+
const cookieToViolationMap = new Map(); // Track which cookies already have violations
|
|
143
|
+
|
|
144
|
+
// 1. Try Symbol-based analysis first (primary)
|
|
145
|
+
if (
|
|
146
|
+
this.config.useSymbolBased &&
|
|
147
|
+
this.semanticEngine?.project &&
|
|
148
|
+
this.semanticEngine?.initialized
|
|
149
|
+
) {
|
|
150
|
+
try {
|
|
151
|
+
if (process.env.SUNLINT_DEBUG) {
|
|
152
|
+
console.log(`🔧 [S035] Trying symbol-based analysis...`);
|
|
153
|
+
}
|
|
154
|
+
const sourceFile = this.semanticEngine.project.getSourceFile(filePath);
|
|
155
|
+
if (sourceFile) {
|
|
156
|
+
if (process.env.SUNLINT_DEBUG) {
|
|
157
|
+
console.log(`🔧 [S035] Source file found, analyzing...`);
|
|
158
|
+
}
|
|
159
|
+
const symbolViolations = await this.symbolAnalyzer.analyze(
|
|
160
|
+
sourceFile,
|
|
161
|
+
filePath
|
|
162
|
+
);
|
|
163
|
+
|
|
164
|
+
// Add symbol violations first (higher priority)
|
|
165
|
+
symbolViolations.forEach((violation) => {
|
|
166
|
+
// Extract cookie name from message for better deduplication
|
|
167
|
+
const cookieNameMatch = violation.message.match(
|
|
168
|
+
/(?:Session (?:cookie|middleware cookie name)|Set-Cookie.*?|NextAuth.*?) "([^"]+)"/
|
|
169
|
+
);
|
|
170
|
+
const cookieName = cookieNameMatch ? cookieNameMatch[1] : "unknown";
|
|
171
|
+
|
|
172
|
+
// Use specific key including column for exact match
|
|
173
|
+
const specificKey = `${violation.line}:${
|
|
174
|
+
violation.column || 1
|
|
175
|
+
}:${cookieName}`;
|
|
176
|
+
const lineKey = `${violation.line}:${cookieName}`;
|
|
177
|
+
|
|
178
|
+
if (!violationMap.has(specificKey)) {
|
|
179
|
+
violationMap.set(specificKey, {
|
|
180
|
+
...violation,
|
|
181
|
+
source: "symbol", // Track source for debugging
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
// Also track by line for regex deduplication
|
|
185
|
+
lineToViolationMap.set(lineKey, specificKey);
|
|
186
|
+
|
|
187
|
+
// Track by cookie name for broader deduplication
|
|
188
|
+
const cookieKey = `${cookieName}:${violation.line}`;
|
|
189
|
+
cookieToViolationMap.set(cookieKey, specificKey);
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
if (process.env.SUNLINT_DEBUG) {
|
|
194
|
+
console.log(
|
|
195
|
+
`🔧 [S035] Symbol analysis completed: ${symbolViolations.length} violations`
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
} else {
|
|
199
|
+
if (process.env.SUNLINT_DEBUG) {
|
|
200
|
+
console.log(`🔧 [S035] Source file not found, falling back...`);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
} catch (error) {
|
|
204
|
+
console.warn(`⚠ [S035] Symbol analysis failed:`, error.message);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// 2. Try Regex-based analysis (fallback or additional)
|
|
209
|
+
if (this.config.fallbackToRegex || this.config.regexBasedOnly) {
|
|
210
|
+
try {
|
|
211
|
+
if (process.env.SUNLINT_DEBUG) {
|
|
212
|
+
console.log(`🔧 [S035] Trying regex-based analysis...`);
|
|
213
|
+
}
|
|
214
|
+
const regexViolations = await this.regexAnalyzer.analyze(filePath);
|
|
215
|
+
|
|
216
|
+
// Add regex violations only if not already covered by symbol analysis
|
|
217
|
+
regexViolations.forEach((violation) => {
|
|
218
|
+
// Extract cookie name from message for better deduplication
|
|
219
|
+
const cookieNameMatch =
|
|
220
|
+
violation.message.match(
|
|
221
|
+
/(?:Session (?:cookie|middleware cookie name)|Set-Cookie.*?|NextAuth.*?) "([^"]+)"/
|
|
222
|
+
) ||
|
|
223
|
+
violation.message.match(
|
|
224
|
+
/Insecure session cookie:.*?(?:Session cookie|NextAuth.*?) "([^"]+)"/
|
|
225
|
+
);
|
|
226
|
+
const cookieName = cookieNameMatch ? cookieNameMatch[1] : "unknown";
|
|
227
|
+
|
|
228
|
+
// Check if this line+cookie (or ±1 line) already has a violation from symbol analyzer
|
|
229
|
+
const currentLine = violation.line;
|
|
230
|
+
const hasSymbolViolation = [
|
|
231
|
+
currentLine - 1,
|
|
232
|
+
currentLine,
|
|
233
|
+
currentLine + 1,
|
|
234
|
+
].some((line) => {
|
|
235
|
+
const lineKey = `${line}:${cookieName}`;
|
|
236
|
+
return lineToViolationMap.has(lineKey);
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
// Also check if this cookie already has a violation nearby (±5 lines for same cookie)
|
|
240
|
+
const hasCookieViolation = Array.from(
|
|
241
|
+
cookieToViolationMap.keys()
|
|
242
|
+
).some((key) => {
|
|
243
|
+
const [existingCookie, existingLine] = key.split(":");
|
|
244
|
+
return (
|
|
245
|
+
existingCookie === cookieName &&
|
|
246
|
+
Math.abs(parseInt(existingLine) - currentLine) <= 5
|
|
247
|
+
);
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
if (!hasSymbolViolation && !hasCookieViolation) {
|
|
251
|
+
// No symbol violation or nearby cookie violation, add regex violation
|
|
252
|
+
const specificKey = `${violation.line}:${
|
|
253
|
+
violation.column || 1
|
|
254
|
+
}:${cookieName}:regex`;
|
|
255
|
+
|
|
256
|
+
if (!violationMap.has(specificKey)) {
|
|
257
|
+
violationMap.set(specificKey, {
|
|
258
|
+
...violation,
|
|
259
|
+
source: "regex", // Track source for debugging
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
// Track this regex violation for future deduplication
|
|
263
|
+
const cookieKey = `${cookieName}:${violation.line}`;
|
|
264
|
+
cookieToViolationMap.set(cookieKey, specificKey);
|
|
265
|
+
}
|
|
266
|
+
} else if (process.env.SUNLINT_DEBUG) {
|
|
267
|
+
const reason = hasSymbolViolation
|
|
268
|
+
? "already covered by symbol"
|
|
269
|
+
: "duplicate cookie violation nearby";
|
|
270
|
+
console.log(
|
|
271
|
+
`🔧 [S035] Skipping duplicate regex violation at line ${currentLine} for cookie "${cookieName}" (${reason})`
|
|
272
|
+
);
|
|
273
|
+
}
|
|
274
|
+
});
|
|
275
|
+
if (process.env.SUNLINT_DEBUG) {
|
|
276
|
+
console.log(
|
|
277
|
+
`🔧 [S035] Regex analysis completed: ${regexViolations.length} violations`
|
|
278
|
+
);
|
|
279
|
+
}
|
|
280
|
+
} catch (error) {
|
|
281
|
+
console.warn(`⚠ [S035] Regex analysis failed:`, error.message);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// Convert Map values to array and add filePath to each violation
|
|
286
|
+
const finalViolations = Array.from(violationMap.values()).map(
|
|
287
|
+
(violation) => ({
|
|
288
|
+
...violation,
|
|
289
|
+
filePath: filePath,
|
|
290
|
+
file: filePath, // Also add 'file' for compatibility
|
|
291
|
+
})
|
|
292
|
+
);
|
|
293
|
+
|
|
294
|
+
if (process.env.SUNLINT_DEBUG) {
|
|
295
|
+
console.log(
|
|
296
|
+
`🔧 [S035] File analysis completed: ${finalViolations.length} unique violations`
|
|
297
|
+
);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
return finalViolations;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* Clean up resources
|
|
305
|
+
*/
|
|
306
|
+
cleanup() {
|
|
307
|
+
if (this.symbolAnalyzer?.cleanup) {
|
|
308
|
+
this.symbolAnalyzer.cleanup();
|
|
309
|
+
}
|
|
310
|
+
if (this.regexAnalyzer?.cleanup) {
|
|
311
|
+
this.regexAnalyzer.cleanup();
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
module.exports = S035Analyzer;
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "S035",
|
|
3
|
+
"name": "Set Path attribute for Session Cookies",
|
|
4
|
+
"category": "security",
|
|
5
|
+
"description": "S035 - Set Path attribute for Session Cookies to limit access scope. This restricts where cookies can be sent, reducing the attack surface by limiting cookie access to specific paths.",
|
|
6
|
+
"severity": "warning",
|
|
7
|
+
"enabled": true,
|
|
8
|
+
"semantic": {
|
|
9
|
+
"enabled": true,
|
|
10
|
+
"priority": "high",
|
|
11
|
+
"fallback": "heuristic"
|
|
12
|
+
},
|
|
13
|
+
"patterns": {
|
|
14
|
+
"include": ["**/*.js", "**/*.ts", "**/*.jsx", "**/*.tsx"],
|
|
15
|
+
"exclude": [
|
|
16
|
+
"**/*.test.js",
|
|
17
|
+
"**/*.test.ts",
|
|
18
|
+
"**/*.spec.js",
|
|
19
|
+
"**/*.spec.ts",
|
|
20
|
+
"**/node_modules/**",
|
|
21
|
+
"**/dist/**",
|
|
22
|
+
"**/build/**"
|
|
23
|
+
]
|
|
24
|
+
},
|
|
25
|
+
"analysis": {
|
|
26
|
+
"approach": "symbol-based-primary",
|
|
27
|
+
"fallback": "regex-based",
|
|
28
|
+
"depth": 2,
|
|
29
|
+
"timeout": 5000
|
|
30
|
+
},
|
|
31
|
+
"validation": {
|
|
32
|
+
"cookieMethods": [
|
|
33
|
+
"setCookie",
|
|
34
|
+
"cookie",
|
|
35
|
+
"set",
|
|
36
|
+
"append",
|
|
37
|
+
"session",
|
|
38
|
+
"setHeader",
|
|
39
|
+
"writeHead"
|
|
40
|
+
],
|
|
41
|
+
"cookieLibraries": [
|
|
42
|
+
"express",
|
|
43
|
+
"koa",
|
|
44
|
+
"fastify",
|
|
45
|
+
"hapi",
|
|
46
|
+
"next",
|
|
47
|
+
"nuxt",
|
|
48
|
+
"cookie",
|
|
49
|
+
"cookie-parser",
|
|
50
|
+
"express-session",
|
|
51
|
+
"connect-session",
|
|
52
|
+
"passport"
|
|
53
|
+
],
|
|
54
|
+
"sessionIndicators": [
|
|
55
|
+
"session",
|
|
56
|
+
"sessionid",
|
|
57
|
+
"sessid",
|
|
58
|
+
"jsessionid",
|
|
59
|
+
"phpsessid",
|
|
60
|
+
"asp.net_sessionid",
|
|
61
|
+
"connect.sid",
|
|
62
|
+
"auth",
|
|
63
|
+
"token",
|
|
64
|
+
"jwt",
|
|
65
|
+
"csrf",
|
|
66
|
+
"refresh",
|
|
67
|
+
"user",
|
|
68
|
+
"login",
|
|
69
|
+
"authentication"
|
|
70
|
+
],
|
|
71
|
+
"pathPatterns": [
|
|
72
|
+
"path:\\s*['\"][^'\"]*['\"]",
|
|
73
|
+
"path:['\"][^'\"]*['\"]",
|
|
74
|
+
"Path=[^;\\s]+",
|
|
75
|
+
"path=[\\/][^;\\s]*"
|
|
76
|
+
],
|
|
77
|
+
"insecurePatterns": [
|
|
78
|
+
"(?<!path[\\s=:]+)(?<!Path=)Set-Cookie",
|
|
79
|
+
"res\\.cookie\\([^)]*\\)(?![^{]*path)",
|
|
80
|
+
"document\\.cookie\\s*="
|
|
81
|
+
],
|
|
82
|
+
"acceptableValues": [
|
|
83
|
+
"/",
|
|
84
|
+
"/app",
|
|
85
|
+
"/admin",
|
|
86
|
+
"/api",
|
|
87
|
+
"/auth",
|
|
88
|
+
"/user",
|
|
89
|
+
"/secure"
|
|
90
|
+
],
|
|
91
|
+
"recommendedValues": ["/app", "/admin", "/api", "/auth"],
|
|
92
|
+
"securityRequirements": {
|
|
93
|
+
"mustHavePath": true,
|
|
94
|
+
"mustNotBeRoot": false,
|
|
95
|
+
"specificPathRequired": true,
|
|
96
|
+
"pathValidation": true
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|