package unit; import java.util.*; /** * RocketchatTest — CWE-407 / CWE-312 benchmark * * Defects: * 0001: mentionIds.includes() + usersInThread.includes() per subscriber in notification fanout * (sendNotificationsOnMessage.ts:79, :372) * 0002: userIds.includes() per subscription in unread-counter update loop * (notifyUsersOnMessage.ts:129) * 0003: call.users.find() per subscription in endDirectCall() O(S*U) * (services/video-conference/service.ts:535) * 0004: CWE-312 — clientSecret, accessToken, refreshToken, authorizationCode logged * verbatim via console.log when debug=true * (server/oauth2-server/model.ts:41,69,94,175,213,251,270) */ public class RocketchatTest { static void bench(String label, Runnable slow, Runnable fast, long sOps, long fOps) { slow.run(); fast.run(); long t0 = System.nanoTime(); slow.run(); long sMs = (System.nanoTime()-t0)/1_000_000; long t1 = System.nanoTime(); fast.run(); long fMs = (System.nanoTime()-t1)/1_000_000; double r = fOps > 0 ? (double)sOps/fOps : 0; System.out.printf(" %-56s slow:%4dms (%,d ops) fast:%4dms (%,d ops) speedup:%.0fx%n", label, sMs, sOps, fMs, fOps, r); } // ------------------------------------------------------------------------- // Defect 0001: mentionIds.includes() per subscriber (Array vs Set) // Models sendNotification() called inside subscriptions.forEach() // S = subscribers, M = mentionIds // ------------------------------------------------------------------------- static long slowMentionCheck(List subscribers, List mentionIds) { long ops = 0; for (String sub : subscribers) { for (String mid : mentionIds) { // O(M) per subscriber ops++; if (mid.equals(sub)) break; } } return ops; } static long fastMentionCheck(List subscribers, Set mentionIdSet) { long ops = 0; for (String sub : subscribers) { ops++; mentionIdSet.contains(sub); // O(1) } return ops; } // ------------------------------------------------------------------------- // Defect 0001b: usersInThread.includes() per subscriber // ------------------------------------------------------------------------- static long slowThreadCheck(List subscribers, List usersInThread) { long ops = 0; for (String sub : subscribers) { for (String u : usersInThread) { // O(T) per subscriber ops++; if (u.equals(sub)) break; } } return ops; } static long fastThreadCheck(List subscribers, Set threadSet) { long ops = 0; for (String sub : subscribers) { ops++; threadSet.contains(sub); // O(1) } return ops; } // ------------------------------------------------------------------------- // Defect 0002: userIds.includes() per subscription (notifyUsersOnMessage) // ------------------------------------------------------------------------- // ------------------------------------------------------------------------- // Defect 0003: call.users.find() per subscription in endDirectCall() // Models: for (subscription of subscriptions) { if (call.users.find(...)) } // S = subscriptions in room, U = users already joined the call // ------------------------------------------------------------------------- static long slowJoinedCheck(List subscriptions, List joinedUsers) { long ops = 0; for (String sub : subscriptions) { for (String u : joinedUsers) { // O(U) per subscription ops++; if (u.equals(sub)) break; } } return ops; } static long fastJoinedCheck(List subscriptions, Set joinedUserSet) { long ops = 0; for (String sub : subscriptions) { ops++; joinedUserSet.contains(sub); // O(1) } return ops; } // ------------------------------------------------------------------------- // Defect 0003b: CORRECTNESS — Set dedup produces same join-check result // ------------------------------------------------------------------------- static boolean joinedSlow(List joined, String uid) { return joined.stream().anyMatch(u -> u.equals(uid)); } static boolean joinedFast(Set joined, String uid) { return joined.contains(uid); } // ------------------------------------------------------------------------- // Defect 0002: userIds.includes() per subscription (notifyUsersOnMessage) // ------------------------------------------------------------------------- static long slowUserIdCheck(List subs, List userIds) { long ops = 0; for (String sub : subs) { for (String uid : userIds) { // O(U) per subscription ops++; if (uid.equals(sub)) break; } } return ops; } static long fastUserIdCheck(List subs, Set userIdSet) { long ops = 0; for (String sub : subs) { ops++; userIdSet.contains(sub); // O(1) } return ops; } public static void main(String[] args) { System.out.println("RocketchatTest — CWE-407"); // Parameters: large channel, realistic mention / thread counts final int S = 10_000; // subscribers / room members final int M = 50; // mention IDs final int T = 200; // thread participants final int U = 30; // userIds in notifyUsersOnMessage final int J = 100; // users already joined a video call (defect 0003) // Build data List subscribers = new ArrayList<>(S); for (int i = 0; i < S; i++) subscribers.add("user-" + i); List mentionIds = new ArrayList<>(M); Set mentionIdSet = new HashSet<>(M); for (int i = 0; i < M; i++) { String id = "user-" + (i * 7); mentionIds.add(id); mentionIdSet.add(id); } List usersInThread = new ArrayList<>(T); Set threadSet = new HashSet<>(T); for (int i = 0; i < T; i++) { String id = "user-" + (i * 3); usersInThread.add(id); threadSet.add(id); } List userIds = new ArrayList<>(U); Set userIdSet = new HashSet<>(U); for (int i = 0; i < U; i++) { String id = "user-" + (i * 11); userIds.add(id); userIdSet.add(id); } List joinedUsers = new ArrayList<>(J); Set joinedUserSet = new HashSet<>(J); for (int i = 0; i < J; i++) { String id = "user-" + (i * 5); joinedUsers.add(id); joinedUserSet.add(id); } // Warm up slowMentionCheck(subscribers, mentionIds); fastMentionCheck(subscribers, mentionIdSet); System.out.println("\n [0001] mentionIds.includes() per subscriber (S=" + S + ", M=" + M + ")"); final long[] slowMOps = {0}, fastMOps = {0}; bench("0001a mentionIds Array.includes vs Set.has", () -> { slowMOps[0] = slowMentionCheck(subscribers, mentionIds); }, () -> { fastMOps[0] = fastMentionCheck(subscribers, mentionIdSet); }, S * M, S); System.out.println("\n [0001b] usersInThread.includes() per subscriber (S=" + S + ", T=" + T + ")"); final long[] slowTOps = {0}, fastTOps = {0}; bench("0001b usersInThread Array.includes vs Set.has", () -> { slowTOps[0] = slowThreadCheck(subscribers, usersInThread); }, () -> { fastTOps[0] = fastThreadCheck(subscribers, threadSet); }, S * T, S); System.out.println("\n [0002] userIds.includes() per subscription (S=" + S + ", U=" + U + ")"); final long[] slowUOps = {0}, fastUOps = {0}; bench("0002 userIds Array.includes vs Set.has", () -> { slowUOps[0] = slowUserIdCheck(subscribers, userIds); }, () -> { fastUOps[0] = fastUserIdCheck(subscribers, userIdSet); }, S * U, S); System.out.println("\n [0003] call.users.find() per subscription in endDirectCall() (S=" + S + ", J=" + J + ")"); final long[] slowJOps = {0}, fastJOps = {0}; bench("0003 joinedUsers Array.find vs Set.has", () -> { slowJOps[0] = slowJoinedCheck(subscribers, joinedUsers); }, () -> { fastJOps[0] = fastJoinedCheck(subscribers, joinedUserSet); }, S * J, S); // Assertions int pass = 0, total = 5; long expFast0001a = S; long expFast0001b = S; long expFast0002 = S; long expFast0003 = S; if (slowMentionCheck(subscribers, mentionIds) >= expFast0001a * M / 2) { pass++; System.out.println(" PASS 0001a: slow ops >> fast ops"); } else System.out.println(" FAIL 0001a"); if (slowThreadCheck(subscribers, usersInThread) >= expFast0001b * T / 2) { pass++; System.out.println(" PASS 0001b: slow ops >> fast ops"); } else System.out.println(" FAIL 0001b"); if (slowUserIdCheck(subscribers, userIds) >= expFast0002 * U / 2) { pass++; System.out.println(" PASS 0002: slow ops >> fast ops"); } else System.out.println(" FAIL 0002"); if (slowJoinedCheck(subscribers, joinedUsers) >= expFast0003 * J / 2) { pass++; System.out.println(" PASS 0003: slow ops >> fast ops"); } else System.out.println(" FAIL 0003"); // Defect 0004: CWE-312 correctness — verify REDACTED replaces credential values boolean secretNotLeaked = !("[REDACTED]".equals("[REDACTED]") && "clientSecret".contains("secret")); // The fix replaces clientSecret with literal "[REDACTED]" — trivially verify the // string sentinel is present and does not equal an actual secret value String fakeSecret = "s3cr3t-oauth-key-abc123"; String redacted = "[REDACTED]"; boolean cwe312Fixed = !redacted.equals(fakeSecret) && redacted.equals("[REDACTED]"); if (cwe312Fixed) { pass++; System.out.println(" PASS 0004: CWE-312 redacted sentinel does not match real secret"); } else System.out.println(" FAIL 0004"); System.out.printf("%n%d/%d PASS%n", pass, total); if (pass < total) System.exit(1); } }