From c0c03f5aa18f48346ccca4a11c9ec9432fa7acc2 Mon Sep 17 00:00:00 2001 From: peopleinfo <49970466+peopleinfo@users.noreply.github.com> Date: Fri, 9 Jan 2026 15:33:39 +0700 Subject: [PATCH 01/11] Add security score helper and tests --- apps/ui/src/renderer/src/lib/securityScore.js | 87 ++++++ .../renderer/src/views/AntiBrowserView.jsx | 279 +++++++++++++++++- apps/ui/tests/unit/security-score.test.js | 57 ++++ 3 files changed, 416 insertions(+), 7 deletions(-) create mode 100644 apps/ui/src/renderer/src/lib/securityScore.js create mode 100644 apps/ui/tests/unit/security-score.test.js diff --git a/apps/ui/src/renderer/src/lib/securityScore.js b/apps/ui/src/renderer/src/lib/securityScore.js new file mode 100644 index 0000000..cede793 --- /dev/null +++ b/apps/ui/src/renderer/src/lib/securityScore.js @@ -0,0 +1,87 @@ +const buildProtectionChecks = (profile) => [ + { + id: "webrtc", + label: "WebRTC leak protection", + enabled: Boolean(profile?.settings?.blockWebRTC), + }, + { + id: "canvas", + label: "Canvas fingerprint masking", + enabled: Boolean(profile?.settings?.blockCanvasFingerprint), + }, + { + id: "audio", + label: "Audio fingerprint masking", + enabled: Boolean(profile?.settings?.blockAudioFingerprint), + }, + { + id: "webgl", + label: "WebGL shielding", + enabled: Boolean(profile?.settings?.blockWebGL), + }, + { + id: "fonts", + label: "Font enumeration blocking", + enabled: Boolean(profile?.settings?.blockFonts), + }, + { + id: "geo", + label: "Geolocation guarding", + enabled: Boolean(profile?.settings?.blockGeolocation), + }, +]; + +const getScoreTone = (normalizedScore) => { + if (normalizedScore >= 80) return "bg-emerald-500"; + if (normalizedScore >= 60) return "bg-amber-500"; + return "bg-rose-500"; +}; + +const getScoreLabel = (normalizedScore) => { + if (normalizedScore >= 80) return "High"; + if (normalizedScore >= 60) return "Medium"; + return "Low"; +}; + +export const getSecurityScore = ({ + profiles = [], + proxies = [], + activeProfileId = null, +} = {}) => { + const stats = { + proxies: proxies.length, + activeProxies: proxies.filter((proxy) => proxy.status === "active").length, + profiles: profiles.length, + runningProfiles: profiles.filter((profile) => profile.status === "running") + .length, + }; + + const activeProfile = profiles.find( + (profile) => profile.id === activeProfileId + ); + const activeProxy = proxies.find( + (proxy) => proxy.id === activeProfile?.proxyId + ); + + const protectionChecks = buildProtectionChecks(activeProfile); + const protectionScore = protectionChecks.filter((item) => item.enabled).length; + const rawScore = + 30 + + (stats.profiles > 0 ? 10 : 0) + + (activeProfileId ? 10 : 0) + + (stats.runningProfiles > 0 ? 10 : 0) + + (activeProxy?.status === "active" ? 15 : 0) + + protectionScore * 5; + const normalizedScore = Math.min(Math.max(rawScore, 0), 100); + + return { + stats, + activeProfile, + activeProxy, + protectionChecks, + protectionScore, + normalizedScore, + scoreLabel: getScoreLabel(normalizedScore), + scoreTone: getScoreTone(normalizedScore), + }; +}; diff --git a/apps/ui/src/renderer/src/views/AntiBrowserView.jsx b/apps/ui/src/renderer/src/views/AntiBrowserView.jsx index c58af85..db58f48 100644 --- a/apps/ui/src/renderer/src/views/AntiBrowserView.jsx +++ b/apps/ui/src/renderer/src/views/AntiBrowserView.jsx @@ -1,9 +1,17 @@ -import { Globe, Network, Settings2, Shield, Users } from "lucide-react"; +import { Globe, Network, Settings2, Shield, ShieldCheck, Users } from "lucide-react"; import React, { useCallback, useState } from "react"; import { toast } from "sonner"; import BrowserProfilesPanel from "../components/BrowserProfilesPanel"; import ProxyManagementPanel from "../components/ProxyManagementPanel"; +import { Badge } from "../components/ui/badge"; import { Button } from "../components/ui/button"; +import { + Card, + CardContent, + CardDescription, + CardHeader, + CardTitle, +} from "../components/ui/card"; import { Tabs, TabsContent, @@ -17,6 +25,7 @@ import { TooltipTrigger, } from "../components/ui/tooltip"; import { cn } from "../lib/utils"; +import { getSecurityScore } from "../lib/securityScore"; import { useBrowserProfileStore } from "../stores/browserProfileStore"; import { useBrowserTabsStore } from "../stores/browserTabsStore"; import { useProxyStore } from "../stores/proxyStore"; @@ -62,12 +71,15 @@ export function AntiBrowserView({ children }) { [openUrlTab, profiles, setActiveProfile] ); - const stats = { - proxies: proxies.length, - activeProxies: proxies.filter((p) => p.status === "active").length, - profiles: profiles.length, - runningProfiles: profiles.filter((p) => p.status === "running").length, - }; + const { + stats, + activeProxy, + protectionChecks, + protectionScore, + normalizedScore, + scoreLabel, + scoreTone, + } = getSecurityScore({ profiles, proxies, activeProfileId }); return (
+ {normalizedScore} +
++ of 100 secure points +
+Based on proxy routing and profile protections.
+Enable more safeguards to improve trust.
+