@@ -921,16 +921,18 @@ private static void DetectHighEntropyParams(RequestEntry req, List<DetectionSign
921921 double entropy = ShannonEntropy ( val ) ;
922922 bool isBase64 = Base64Payload . IsMatch ( val ) ;
923923 bool isHex = HexPayload . IsMatch ( val ) ;
924+ bool hasEntropyPattern = HighEntropyPattern . IsMatch ( val ) ;
924925
925- if ( entropy > 4.0 || isBase64 || isHex )
926+ if ( entropy > 3.8 || isBase64 || isHex || hasEntropyPattern )
926927 {
927- double conf = entropy > 4.5 ? 0.85 : entropy > 4.0 ? 0.70 : 0.55 ;
928- if ( isBase64 || isHex ) conf = Math . Max ( conf , 0.75 ) ;
928+ double conf = entropy > 4.5 ? 0.85 : entropy > 4.0 ? 0.75 : 0.60 ;
929+ if ( isBase64 || isHex || hasEntropyPattern ) conf = Math . Max ( conf , 0.80 ) ;
929930 signals . Add ( new DetectionSignal
930931 {
931932 SignalType = "high_entropy_param" ,
932933 Source = req . Host ,
933- Detail = $ "Param '{ parts [ 0 ] } ' has high entropy ({ entropy : F1} ) — possible obfuscated tracking ID" + ( isBase64 ? " [Base64]" : "" ) + ( isHex ? " [Hex]" : "" ) ,
934+ Detail = $ "Param '{ parts [ 0 ] } ' has high-entropy identifier ({ entropy : F1} ) — possible obfuscated tracking ID"
935+ + ( isBase64 ? " [Base64]" : "" ) + ( isHex ? " [Hex]" : "" ) + ( hasEntropyPattern ? " [Random-looking]" : "" ) ,
934936 Confidence = conf ,
935937 Risk = RiskType . Tracking ,
936938 Severity = 3 ,
@@ -1046,16 +1048,24 @@ private static void DetectCookieSync(RequestEntry req, List<DetectionSignal> sig
10461048 req . Path . Contains ( "sync" , StringComparison . OrdinalIgnoreCase ) ||
10471049 req . Path . Contains ( "match" , StringComparison . OrdinalIgnoreCase ) ;
10481050
1049- if ( hasIds )
1051+ bool highRiskTracker =
1052+ string . Equals ( req . TrackerCategoryName , "Advertising" , StringComparison . OrdinalIgnoreCase ) ||
1053+ string . Equals ( req . TrackerCategoryName , "DMP" , StringComparison . OrdinalIgnoreCase ) ||
1054+ string . Equals ( req . TrackerCategoryName , "Attribution" , StringComparison . OrdinalIgnoreCase ) ;
1055+
1056+ if ( hasIds || highRiskTracker )
10501057 {
1058+ double confidence = highRiskTracker ? 0.80 : 0.70 ;
1059+ int severity = highRiskTracker ? 5 : 4 ;
1060+
10511061 signals . Add ( new DetectionSignal
10521062 {
10531063 SignalType = "cookie_sync" ,
10541064 Source = req . Host ,
10551065 Detail = "Cookie sync detected — identifiers passed to third-party ad-tech" ,
1056- Confidence = 0.70 ,
1066+ Confidence = confidence ,
10571067 Risk = RiskType . Tracking ,
1058- Severity = 4 ,
1068+ Severity = severity ,
10591069 Evidence = $ "Cookie header present with tracking params to { req . Host } ",
10601070 GdprArticle = "Art. 5(1)(a)"
10611071 } ) ;
@@ -1098,6 +1108,19 @@ public static string ClassifyCookie(string name)
10981108 var lower = name . ToLowerInvariant ( ) ;
10991109 if ( TrackingCookiePatterns . Any ( p => lower . StartsWith ( p . ToLowerInvariant ( ) ) || lower == p . ToLowerInvariant ( ) ) )
11001110 return "Tracking / Analytics" ;
1111+
1112+ // Stronger heuristic: generic identifier-style cookies used by many tracking stacks
1113+ if ( lower . Contains ( "visitorid" ) || lower . Contains ( "visitor_id" ) ||
1114+ lower . Contains ( "deviceid" ) || lower . Contains ( "device_id" ) ||
1115+ lower . Contains ( "userid" ) || lower . Contains ( "user_id" ) ||
1116+ lower . Contains ( "clientid" ) || lower . Contains ( "client_id" ) ||
1117+ lower . Contains ( "customerid" ) || lower . Contains ( "customer_id" ) ||
1118+ lower . Contains ( "browserid" ) || lower . Contains ( "browser_id" ) ||
1119+ lower . Contains ( "uuid" ) )
1120+ {
1121+ return "Tracking / Analytics" ;
1122+ }
1123+
11011124 if ( lower . Contains ( "session" ) || lower . Contains ( "sid" ) || lower . Contains ( "csrf" ) || lower . Contains ( "token" ) || lower . Contains ( "auth" ) )
11021125 return "Session / Security" ;
11031126 if ( lower . Contains ( "consent" ) || lower . Contains ( "gdpr" ) || lower . Contains ( "ccpa" ) || lower . Contains ( "cookie" ) || lower . Contains ( "optanon" ) )
@@ -1112,6 +1135,19 @@ public static string ClassifyStorageKey(string key)
11121135 var lower = key . ToLowerInvariant ( ) ;
11131136 if ( TrackingCookiePatterns . Any ( p => lower . Contains ( p . ToLowerInvariant ( ) ) ) )
11141137 return "Tracking / Analytics" ;
1138+
1139+ // Stronger heuristic: identifier-style keys commonly used for tracking
1140+ if ( lower . Contains ( "visitorid" ) || lower . Contains ( "visitor_id" ) ||
1141+ lower . Contains ( "deviceid" ) || lower . Contains ( "device_id" ) ||
1142+ lower . Contains ( "userid" ) || lower . Contains ( "user_id" ) ||
1143+ lower . Contains ( "clientid" ) || lower . Contains ( "client_id" ) ||
1144+ lower . Contains ( "customerid" ) || lower . Contains ( "customer_id" ) ||
1145+ lower . Contains ( "browserid" ) || lower . Contains ( "browser_id" ) ||
1146+ lower . Contains ( "uuid" ) )
1147+ {
1148+ return "Tracking / Analytics" ;
1149+ }
1150+
11151151 if ( lower . Contains ( "token" ) || lower . Contains ( "auth" ) || lower . Contains ( "session" ) )
11161152 return "Authentication" ;
11171153 if ( lower . Contains ( "cache" ) || lower . Contains ( "sw-" ) || lower . Contains ( "workbox" ) )
@@ -1153,6 +1189,24 @@ public static List<string> ClassifyRequestData(RequestEntry req)
11531189 var url = req . FullUrl . ToLowerInvariant ( ) ;
11541190 if ( url . Contains ( "geo" ) || url . Contains ( "location" ) || url . Contains ( "lat=" ) || url . Contains ( "lng=" ) ) tags . Add ( "Location data" ) ;
11551191 if ( url . Contains ( "email" ) || url . Contains ( "phone" ) || url . Contains ( "name=" ) || url . Contains ( "address" ) ) tags . Add ( "Possible PII" ) ;
1192+
1193+ if ( req . IsThirdParty ) tags . Add ( "Shared with other companies" ) ;
1194+
1195+ if ( ! string . IsNullOrEmpty ( req . TrackerCategoryName ) )
1196+ {
1197+ if ( string . Equals ( req . TrackerCategoryName , "Advertising" , StringComparison . OrdinalIgnoreCase ) ||
1198+ string . Equals ( req . TrackerCategoryName , "DMP" , StringComparison . OrdinalIgnoreCase ) ||
1199+ string . Equals ( req . TrackerCategoryName , "Attribution" , StringComparison . OrdinalIgnoreCase ) )
1200+ {
1201+ tags . Add ( "Ad-tech / profiling" ) ;
1202+ }
1203+ else if ( string . Equals ( req . TrackerCategoryName , "Analytics" , StringComparison . OrdinalIgnoreCase ) ||
1204+ string . Equals ( req . TrackerCategoryName , "SessionReplay" , StringComparison . OrdinalIgnoreCase ) )
1205+ {
1206+ tags . Add ( "Behavioral analytics" ) ;
1207+ }
1208+ }
1209+
11561210 return tags ;
11571211 }
11581212
@@ -1288,17 +1342,17 @@ public static List<GdprFinding> MapToGdpr(ScanResult scan)
12881342
12891343 private static double BaselineWeight ( TrackerCategory cat ) => cat switch
12901344 {
1291- TrackerCategory . CMP => 0.2 , // Consent tools are infrastructure, very low risk
1345+ TrackerCategory . CMP => 0.3 , // Consent tools are infrastructure, but still expose choices
12921346 TrackerCategory . CDN => 0.1 , // CDN is expected
1293- TrackerCategory . AdVerification => 0.5 , // Verification is semi-expected
1294- TrackerCategory . Affiliate => 0.6 , // Affiliate tracking is common
1295- TrackerCategory . Analytics => 0.7 , // Standard analytics — normal web behavior
1296- TrackerCategory . Social => 0.8 , // Social widgets carry moderate risk
1297- TrackerCategory . Attribution => 0.9 , // Attribution is aggressive mobile tracking
1298- TrackerCategory . Advertising => 1.0 , // Full penalty for ad trackers
1299- TrackerCategory . SessionReplay => 1.3 , // Session replay is invasive — amplified penalty
1300- TrackerCategory . DMP => 1.5 , // Data brokers are highest risk — amplified
1301- TrackerCategory . Fingerprinting => 1.4 , // Fingerprinting evades consent — amplified
1347+ TrackerCategory . AdVerification => 0.6 , // Verification is semi-expected
1348+ TrackerCategory . Affiliate => 0.7 , // Affiliate tracking is common
1349+ TrackerCategory . Analytics => 0.8 , // Standard analytics — normal web behavior but still tracking
1350+ TrackerCategory . Social => 0.9 , // Social widgets carry moderate-to-high risk
1351+ TrackerCategory . Attribution => 1.0 , // Attribution is aggressive mobile tracking
1352+ TrackerCategory . Advertising => 1.1 , // Slightly stronger penalty for ad trackers
1353+ TrackerCategory . SessionReplay => 1.5 , // Session replay is invasive — amplified penalty
1354+ TrackerCategory . DMP => 1.8 , // Data brokers are highest risk — amplified further
1355+ TrackerCategory . Fingerprinting => 1.6 , // Fingerprinting evades consent — amplified
13021356 _ => 1.0
13031357 } ;
13041358
@@ -1330,7 +1384,7 @@ public static PrivacyScore CalculateScore(ScanResult scan)
13301384 breakdown [ "Third-party domains" ] = - domainPenalty ;
13311385
13321386 // ── Fingerprinting: steep penalty ──
1333- int fpPenalty = Math . Min ( 35 , scan . Fingerprints . Count * 10 ) ;
1387+ int fpPenalty = Math . Min ( 40 , scan . Fingerprints . Count * 12 ) ;
13341388 score -= fpPenalty ; catScores [ "Fingerprinting" ] -= fpPenalty ;
13351389 breakdown [ "Fingerprinting" ] = - fpPenalty ;
13361390
@@ -1375,7 +1429,7 @@ public static PrivacyScore CalculateScore(ScanResult scan)
13751429 f . Type . StartsWith ( "Behavioral:" ) || f . Type . Contains ( "Session Replay" ) ||
13761430 f . Type . Contains ( "Obfuscation" ) || f . Type . Contains ( "Dynamic Script" ) ||
13771431 f . Type . Contains ( "Beacon Data" ) || f . Type . Contains ( "Cross-Frame" ) ) ;
1378- int behavioralPenalty = Math . Min ( 25 , behavioralCount * 6 ) ;
1432+ int behavioralPenalty = Math . Min ( 25 , behavioralCount * 7 ) ;
13791433 score -= behavioralPenalty ; catScores [ "Behavioral" ] -= behavioralPenalty ;
13801434 if ( behavioralPenalty > 0 ) breakdown [ "Behavioral tracking" ] = - behavioralPenalty ;
13811435
0 commit comments