(originalResponse, modifiedResponse, originalText, modifiedText, settings)
| 324 | // ============================================================================ |
| 325 | |
| 326 | async function analyzeResponseDifference(originalResponse, modifiedResponse, originalText, modifiedText, settings) { |
| 327 | const result = { |
| 328 | isDifferent: false, |
| 329 | confidence: 0, |
| 330 | reasons: [], |
| 331 | severity: 'low', |
| 332 | debugIndicators: null, |
| 333 | headerChanges: [], |
| 334 | }; |
| 335 | |
| 336 | // 1. Status code change detection |
| 337 | if (settings.detectStatusChanges && originalResponse.status !== modifiedResponse.status) { |
| 338 | result.reasons.push(`Status changed: ${originalResponse.status} → ${modifiedResponse.status}`); |
| 339 | result.confidence += 30; |
| 340 | |
| 341 | // Special cases |
| 342 | if (originalResponse.status === 403 && modifiedResponse.status === 200) { |
| 343 | result.confidence += 40; // Bypass! |
| 344 | result.severity = 'critical'; |
| 345 | } else if (modifiedResponse.status >= 500) { |
| 346 | result.confidence += 20; // Server error triggered |
| 347 | result.severity = 'high'; |
| 348 | } |
| 349 | } |
| 350 | |
| 351 | // 2. Header changes |
| 352 | if (settings.detectHeaderChanges) { |
| 353 | const originalHeaders = extractInterestingHeaders(originalResponse); |
| 354 | const modifiedHeaders = extractInterestingHeaders(modifiedResponse); |
| 355 | result.headerChanges = compareHeaders(originalHeaders, modifiedHeaders); |
| 356 | |
| 357 | if (result.headerChanges.length > 0) { |
| 358 | result.reasons.push(`Header changes detected: ${result.headerChanges.length}`); |
| 359 | result.confidence += 15 * result.headerChanges.length; |
| 360 | } |
| 361 | } |
| 362 | |
| 363 | // 3. Content length difference |
| 364 | const lengthDiff = Math.abs(modifiedText.length - originalText.length); |
| 365 | if (lengthDiff >= settings.minLengthDiff) { |
| 366 | result.reasons.push(`Content length diff: ${lengthDiff} bytes`); |
| 367 | result.confidence += Math.min(lengthDiff / 100, 25); |
| 368 | } |
| 369 | |
| 370 | // 4. Debug indicator detection |
| 371 | const debugCheck = containsDebugIndicators(modifiedText); |
| 372 | if (debugCheck.found) { |
| 373 | result.debugIndicators = debugCheck; |
| 374 | result.reasons.push(`Debug indicators found: ${debugCheck.level}`); |
| 375 | result.confidence += debugCheck.level === 'critical' ? 50 : debugCheck.level === 'high' ? 35 : 20; |
| 376 | |
| 377 | if (debugCheck.level === 'critical') result.severity = 'critical'; |
| 378 | else if (debugCheck.level === 'high' && result.severity !== 'critical') result.severity = 'high'; |
| 379 | else if (debugCheck.level === 'medium' && !['critical', 'high'].includes(result.severity)) result.severity = 'medium'; |
| 380 | } |
| 381 | |
| 382 | // 5. Similarity check (after filtering dynamic content) |
| 383 | let originalFiltered = originalText; |
no test coverage detected