Spaces:
Running
Running
| document.addEventListener('DOMContentLoaded', () => { | |
| // Production-Grade OSINT Data Stream | |
| const osintStream = document.getElementById('osint-stream'); | |
| let osintDataCache = []; | |
| // Real-time timestamp formatter | |
| function formatTime(date) { | |
| const now = new Date(); | |
| const diff = Math.floor((now - date) / 1000); | |
| if (diff < 60) return 'Just now'; | |
| if (diff < 3600) return `${Math.floor(diff / 60)}m ago`; | |
| if (diff < 86400) return `${Math.floor(diff / 3600)}h ago`; | |
| return date.toLocaleDateString(); | |
| } | |
| // Fetch NIST NVD CVE Data (Production Vulnerability Feed) | |
| async function fetchNVDCVEs() { | |
| try { | |
| const response = await fetch('https://services.nvd.nist.gov/rest/json/cves/2.0?resultsPerPage=8&cvssV3Severity=CRITICAL,HIGH'); | |
| const data = await response.json(); | |
| return data.vulnerabilities.map(vuln => { | |
| const cve = vuln.cve; | |
| const metrics = cve.metrics?.cvssMetricV31?.[0]?.cvssData || {}; | |
| const severity = metrics.baseScore || 0; | |
| const vector = metrics.attackVector || 'N/A'; | |
| const description = cve.descriptions?.[0]?.value || 'No description available'; | |
| const publishedDate = new Date(cve.published); | |
| return { | |
| type: 'VULNERABILITY', | |
| platform: 'NIST NVD', | |
| msg: `${cve.id}: ${description.substring(0, 70)}... [AV:${vector}]`, | |
| time: formatTime(publishedDate), | |
| severity: severity, | |
| source: 'NVD', | |
| cveId: cve.id | |
| }; | |
| }); | |
| } catch (error) { | |
| console.error('NVD API Error:', error); | |
| return []; | |
| } | |
| } | |
| // Fetch CISA Known Exploited Vulnerabilities | |
| async function fetchCISAVulns() { | |
| try { | |
| const response = await fetch('https://www.cisa.gov/known-exploited-vulnerabilities-catalog.json'); | |
| const data = await response.json(); | |
| const today = new Date(); | |
| return data.vulnerabilities.slice(0, 5).map(vuln => { | |
| const dueDate = new Date(vuln.dueDate); | |
| const isUrgent = dueDate < today; | |
| return { | |
| type: 'ACTIVE_EXPLOIT', | |
| platform: 'CISA KEV', | |
| msg: `${vuln.cveID} - ${vuln.vendorProject}: ${vuln.vulnerabilityName.substring(0, 50)}...`, | |
| time: isUrgent ? `DUE: ${vuln.dueDate}` : `Due: ${vuln.dueDate}`, | |
| severity: 'CRITICAL', | |
| source: 'CISA', | |
| isUrgent: isUrgent | |
| }; | |
| }); | |
| } catch (error) { | |
| console.error('CISA API Error:', error); | |
| return []; | |
| } | |
| } | |
| // Fetch Hacker News Security Stories | |
| async function fetchHackerNews() { | |
| try { | |
| const response = await fetch('https://hacker-news.firebaseio.com/v0/newstories.json?print=pretty'); | |
| const storyIds = await response.json(); | |
| const stories = await Promise.all( | |
| storyIds.slice(0, 10).map(async id => { | |
| const storyResponse = await fetch(`https://hacker-news.firebaseio.com/v0/item/${id}.json?print=pretty`); | |
| return storyResponse.json(); | |
| }) | |
| ); | |
| const securityKeywords = ['security', 'vulnerability', 'hack', 'cyber', 'exploit', 'malware', 'breach', 'attack', 'zero-day', '0day', 'ransomware', 'phishing']; | |
| return stories | |
| .filter(story => story.title && securityKeywords.some(keyword => | |
| story.title.toLowerCase().includes(keyword))) | |
| .slice(0, 4) | |
| .map(story => ({ | |
| type: 'INTELLIGENCE', | |
| platform: 'Hacker News', | |
| msg: story.title, | |
| time: formatTime(new Date(story.time * 1000)), | |
| url: story.url || `https://news.ycombinator.com/item?id=${story.id}`, | |
| source: 'HN' | |
| })); | |
| } catch (error) { | |
| console.error('Hacker News API Error:', error); | |
| return []; | |
| } | |
| } | |
| // Fetch GitHub Trending Security Repositories | |
| async function fetchGitHubSecurity() { | |
| try { | |
| const query = 'topic:security topic:cybersecurity stars:>500 pushed:>2024-01-01'; | |
| const response = await fetch(`https://api.github.com/search/repositories?q=${encodeURIComponent(query)}&sort=updated&order=desc&per_page=4`); | |
| const data = await response.json(); | |
| return data.items.map(repo => { | |
| const lastPush = new Date(repo.pushed_at); | |
| return { | |
| type: 'TOOL_DISCOVERY', | |
| platform: 'GitHub', | |
| msg: `${repo.name}: ${repo.description?.substring(0, 55) || 'No description'}`, | |
| time: `${repo.stargazers_count.toLocaleString()} ★ • Updated ${formatTime(lastPush)}`, | |
| source: 'GH', | |
| url: repo.html_url | |
| }; | |
| }); | |
| } catch (error) { | |
| console.error('GitHub API Error:', error); | |
| return []; | |
| } | |
| } | |
| // Get Real Browser/System Information | |
| function getSystemInfo() { | |
| const connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection; | |
| const connectionType = connection ? `${connection.effectiveType.toUpperCase()} • ${connection.downlink}Mbps` : 'Unknown'; | |
| const cores = navigator.hardwareConcurrency || 'Unknown'; | |
| const memory = navigator.deviceMemory ? `${navigator.deviceMemory}GB` : 'Unknown'; | |
| const doNotTrack = navigator.doNotTrack === '1' ? 'Enabled' : 'Disabled'; | |
| return { | |
| type: 'SYSTEM', | |
| platform: 'Browser Fingerprint', | |
| msg: `Cores: ${cores} | RAM: ${memory} | DNT: ${doNotTrack} | Network: ${connectionType}`, | |
| time: 'Live', | |
| source: 'LOCAL' | |
| }; | |
| } | |
| // Fetch IP Geolocation and Threat Data | |
| async function fetchIPInfo() { | |
| try { | |
| const response = await fetch('https://ipapi.co/json/'); | |
| const data = await response.json(); | |
| // Check for VPN/Proxy indicators | |
| const indicators = []; | |
| if (data.privacy?.vpn) indicators.push('VPN'); | |
| if (data.privacy?.proxy) indicators.push('Proxy'); | |
| if (data.privacy?.tor) indicators.push('TOR'); | |
| if (data.privacy?.hosting) indicators.push('Hosting'); | |
| const threatLevel = indicators.length > 0 ? 'ELEVATED' : 'NORMAL'; | |
| const indicatorText = indicators.length > 0 ? ` [${indicators.join(' + ')}]` : ''; | |
| return { | |
| type: 'NETWORK', | |
| platform: 'IP Intelligence', | |
| msg: `IP: ${data.ip} • ${data.city}, ${data.country_name} • ASN: ${data.asn} • ISP: ${data.org}${indicatorText}`, | |
| time: 'Live', | |
| source: 'IPAPI', | |
| threatLevel: threatLevel | |
| }; | |
| } catch (error) { | |
| console.error('IP API Error:', error); | |
| return { | |
| type: 'NETWORK', | |
| platform: 'IP Intelligence', | |
| msg: 'Unable to retrieve IP information - Check network connectivity', | |
| time: 'Error', | |
| source: 'IPAPI' | |
| }; | |
| } | |
| } | |
| // Fetch URLhaus Malware URLs (Public API) | |
| async function fetchURLhaus() { | |
| try { | |
| const response = await fetch('https://urlhaus-api.abuse.ch/api/v1/urls/recent/limit/3/'); | |
| const data = await response.json(); | |
| if (data.query_status !== 'ok') return []; | |
| return data.urls.map(urlData => ({ | |
| type: 'MALWARE', | |
| platform: 'URLhaus', | |
| msg: `Malware URL detected - Threat: ${urlData.threat} • ${urlData.url.substring(0, 50)}...`, | |
| time: new Date(urlData.date_added * 1000).toLocaleDateString(), | |
| source: 'URLHAUS', | |
| url: urlData.url | |
| })); | |
| } catch (error) { | |
| console.error('URLhaus API Error:', error); | |
| return []; | |
| } | |
| } | |
| // Fetch MalwareBazaar Samples | |
| async function fetchMalwareBazaar() { | |
| try { | |
| const formData = new FormData(); | |
| formData.append('query', 'get_recent'); | |
| formData.append('limit', '3'); | |
| const response = await fetch('https://mb-api.abuse.ch/api/v1/', { | |
| method: 'POST', | |
| body: formData | |
| }); | |
| const data = await response.json(); | |
| if (data.query_status !== 'ok') return []; | |
| return data.data.map(sample => ({ | |
| type: 'MALWARE_SAMPLE', | |
| platform: 'MalwareBazaar', | |
| msg: `${sample.malware_family || 'Unknown'} • ${sample.sha256_hash.substring(0, 20)}... • ${sample.file_name || 'Unnamed'}`, | |
| time: new Date(sample.first_seen).toLocaleDateString(), | |
| source: 'MALWAREBAZAAR' | |
| })); | |
| } catch (error) { | |
| console.error('MalwareBazaar API Error:', error); | |
| return []; | |
| } | |
| } | |
| // Fetch Crypto Market Data (CoinGecko - Free Public API) | |
| async function fetchCryptoData() { | |
| try { | |
| const response = await fetch('https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&order=market_cap_desc&per_page=3&page=1&sparkline=false'); | |
| const data = await response.json(); | |
| return data.map(coin => ({ | |
| type: 'FINANCIAL', | |
| platform: 'CoinGecko', | |
| msg: `${coin.name} (${coin.symbol.toUpperCase()}) • ${coin.current_price.toLocaleString()} • ${coin.price_change_percentage_24h >= 0 ? '+' : ''}${coin.price_change_percentage_24h.toFixed(2)}% (24h)`, | |
| time: `MCap: ${(coin.market_cap / 1000000000).toFixed(1)}B`, | |
| source: 'COINGECKO', | |
| url: `https://www.coingecko.com/en/coins/${coin.id}` | |
| })); | |
| } catch (error) { | |
| console.error('CoinGecko API Error:', error); | |
| return []; | |
| } | |
| } | |
| // Fetch Earthquake Data (USGS - Real-time monitoring) | |
| async function fetchEarthquakeData() { | |
| try { | |
| const response = await fetch('https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/2.5_day.geojson'); | |
| const data = await response.json(); | |
| return data.features.slice(0, 3).map(quake => ({ | |
| type: 'GEOPHYSICAL', | |
| platform: 'USGS', | |
| msg: `M${quake.properties.mag.toFixed(1)} earthquake • ${quake.properties.place} • Depth: ${quake.geometry.coordinates[2]}km`, | |
| time: new Date(quake.properties.time).toLocaleString(), | |
| source: 'USGS', | |
| url: quake.properties.url | |
| })); | |
| } catch (error) { | |
| console.error('USGS API Error:', error); | |
| return []; | |
| } | |
| } | |
| // Fetch Space Weather (NOAA) | |
| async function fetchSpaceWeather() { | |
| try { | |
| const response = await fetch('https://services.swpc.noaa.gov/json/goes/primary/xrays-6-hour.json'); | |
| const data = await response.json(); | |
| if (!data || data.length === 0) return []; | |
| const latest = data[data.length - 1]; | |
| const flux = latest.flux; | |
| const classification = flux < 1.0e-8 ? 'A' : flux < 1.0e-7 ? 'B' : flux < 1.0e-6 ? 'C' : flux < 1.0e-5 ? 'M' : 'X'; | |
| return [{ | |
| type: 'SPACE_WEATHER', | |
| platform: 'NOAA SWPC', | |
| msg: `Solar X-Ray Flux: ${flux.toExponential(2)} W/m² • Class: ${classification}`, | |
| time: new Date(latest.time).toLocaleString(), | |
| source: 'NOAA' | |
| }]; | |
| } catch (error) { | |
| console.error('NOAA API Error:', error); | |
| return []; | |
| } | |
| } | |
| function createOSINTItem(data) { | |
| const div = document.createElement('div'); | |
| let colorClass = 'border-gray-700'; | |
| let icon = 'info'; | |
| let textColor = 'text-gray-300'; | |
| // Enhanced color coding based on data type | |
| switch(data.type) { | |
| case 'ACTIVE_EXPLOIT': | |
| colorClass = 'border-red-500/70 bg-red-900/20'; | |
| icon = 'alert-octagon'; | |
| textColor = 'text-red-400'; | |
| break; | |
| case 'MALWARE': | |
| case 'MALWARE_SAMPLE': | |
| colorClass = 'border-red-600/50 bg-red-900/15'; | |
| icon = 'virus'; | |
| textColor = 'text-red-300'; | |
| break; | |
| case 'VULNERABILITY': | |
| colorClass = 'border-secondary/50 bg-secondary/5'; | |
| icon = 'alert-triangle'; | |
| textColor = data.severity >= 9.0 ? 'text-red-400' : data.severity >= 7.0 ? 'text-orange-400' : 'text-secondary'; | |
| break; | |
| case 'SYSTEM': | |
| colorClass = 'border-primary/50 bg-primary/5'; | |
| icon = 'server'; | |
| textColor = 'text-primary'; | |
| break; | |
| case 'NETWORK': | |
| colorClass = data.threatLevel === 'ELEVATED' ? 'border-yellow-500/50 bg-yellow-900/20' : 'border-cyan-500/50 bg-cyan-900/20'; | |
| icon = data.threatLevel === 'ELEVATED' ? 'shield-alert' : 'globe'; | |
| textColor = data.threatLevel === 'ELEVATED' ? 'text-yellow-400' : 'text-cyan-400'; | |
| break; | |
| case 'INTELLIGENCE': | |
| colorClass = 'border-blue-500/50 bg-blue-500/5'; | |
| icon = 'target'; | |
| textColor = 'text-blue-400'; | |
| break; | |
| case 'TOOL_DISCOVERY': | |
| colorClass = 'border-purple-500/50 bg-purple-900/20'; | |
| icon = 'package'; | |
| textColor = 'text-purple-400'; | |
| break; | |
| case 'FINANCIAL': | |
| colorClass = 'border-green-500/50 bg-green-900/20'; | |
| icon = 'dollar-sign'; | |
| textColor = 'text-green-400'; | |
| break; | |
| case 'GEOPHYSICAL': | |
| colorClass = 'border-amber-500/50 bg-amber-900/20'; | |
| icon = 'activity'; | |
| textColor = 'text-amber-400'; | |
| break; | |
| case 'SPACE_WEATHER': | |
| colorClass = 'border-indigo-500/50 bg-indigo-900/20'; | |
| icon = 'sun'; | |
| textColor = 'text-indigo-400'; | |
| break; | |
| default: | |
| colorClass = 'border-gray-700 bg-gray-800/50'; | |
| icon = 'info'; | |
| textColor = 'text-gray-400'; | |
| } | |
| div.className = `p-3 rounded border ${colorClass} text-sm animate-fade-in flex items-start gap-3 hover:bg-opacity-10 transition-all cursor-pointer`; | |
| const linkAttr = data.url ? `href="${data.url}" target="_blank" rel="noopener noreferrer"` : ''; | |
| const linkWrapper = data.url ? 'a' : 'div'; | |
| const sourceBadgeClass = { | |
| 'CISA': 'bg-red-900/60 text-red-300 border border-red-700/50', | |
| 'URLHAUS': 'bg-red-900/40 text-red-300 border border-red-800/50', | |
| 'MALWAREBAZAAR': 'bg-red-950/60 text-red-400 border border-red-900/50', | |
| 'NVD': 'bg-orange-900/40 text-orange-300 border border-orange-800/50', | |
| 'HN': 'bg-orange-600/20 text-orange-300 border border-orange-700/50', | |
| 'GH': 'bg-purple-900/40 text-purple-300 border border-purple-800/50', | |
| 'IPAPI': 'bg-cyan-900/40 text-cyan-300 border border-cyan-800/50', | |
| 'COINGECKO': 'bg-green-900/40 text-green-300 border border-green-800/50', | |
| 'USGS': 'bg-amber-900/40 text-amber-300 border border-amber-800/50', | |
| 'NOAA': 'bg-indigo-900/40 text-indigo-300 border border-indigo-800/50', | |
| 'LOCAL': 'bg-gray-700/50 text-gray-400 border border-gray-600/50' | |
| }[data.source] || 'bg-gray-700/50 text-gray-400 border border-gray-600/50'; | |
| div.innerHTML = ` | |
| <${linkWrapper} ${linkAttr} class="flex-1 flex items-start gap-3 text-decoration-none"> | |
| <i data-feather="${icon}" class="w-4 h-4 mt-0.5 ${textColor} flex-shrink-0"></i> | |
| <div class="flex-1 min-w-0"> | |
| <div class="flex justify-between items-center mb-1 flex-wrap gap-2"> | |
| <span class="font-bold ${textColor} text-xs tracking-wider">${data.type.replace(/_/g, ' ')}</span> | |
| <span class="text-[10px] px-2 py-0.5 rounded ${sourceBadgeClass}">${data.source}</span> | |
| </div> | |
| <p class="text-gray-300 text-xs leading-relaxed break-words"> | |
| <span class="text-gray-500 font-semibold text-[10px] uppercase tracking-wider">[${data.platform}]</span> ${data.msg} | |
| </p> | |
| <div class="mt-1 flex items-center gap-2"> | |
| <span class="text-[10px] text-gray-500 font-mono-tech">${data.time}</span> | |
| ${data.isUrgent ? '<span class="text-[10px] px-1.5 py-0.5 rounded bg-red-600 text-white animate-pulse font-bold">URGENT</span>' : ''} | |
| ${data.cveId ? `<span class="text-[10px] px-1.5 py-0.5 rounded bg-slate-700 text-gray-300 font-mono">${data.cveId}</span>` : ''} | |
| </div> | |
| </div> | |
| </${linkWrapper}> | |
| `; | |
| return div; | |
| } | |
| // Load all real data sources | |
| async function loadRealData() { | |
| osintStream.innerHTML = '<div class="text-center py-8 text-gray-500"><i data-feather="loader" class="animate-spin inline-block"></i> Loading real-time intelligence...</div>'; | |
| feather.replace(); | |
| const [cves, cisa, hn, github, system, ip, urlhaus, malware, crypto, quakes, space] = await Promise.allSettled([ | |
| fetchNVDCVEs(), | |
| fetchCISAVulns(), | |
| fetchHackerNews(), | |
| fetchGitHubSecurity(), | |
| Promise.resolve(getSystemInfo()), | |
| fetchIPInfo(), | |
| fetchURLhaus(), | |
| fetchMalwareBazaar(), | |
| fetchCryptoData(), | |
| fetchEarthquakeData(), | |
| fetchSpaceWeather() | |
| ]); | |
| osintStream.innerHTML = ''; | |
| const allData = [ | |
| ...(cves.status === 'fulfilled' ? cves.value : []), | |
| ...(cisa.status === 'fulfilled' ? cisa.value : []), | |
| ...(hn.status === 'fulfilled' ? hn.value : []), | |
| ...(github.status === 'fulfilled' ? github.value : []), | |
| system, | |
| ...(ip.status === 'fulfilled' ? [ip.value] : []), | |
| ...(urlhaus.status === 'fulfilled' ? urlhaus.value : []), | |
| ...(malware.status === 'fulfilled' ? malware.value : []), | |
| ...(crypto.status === 'fulfilled' ? crypto.value : []), | |
| ...(quakes.status === 'fulfilled' ? quakes.value : []), | |
| ...(space.status === 'fulfilled' ? space.value : []) | |
| ]; | |
| osintDataCache = allData; | |
| // Sort by priority: Active exploits > Malware > Critical CVEs > Intelligence > Other | |
| const priorityOrder = { | |
| 'ACTIVE_EXPLOIT': 1, | |
| 'MALWARE': 2, | |
| 'MALWARE_SAMPLE': 3, | |
| 'VULNERABILITY': 4, | |
| 'INTELLIGENCE': 5, | |
| 'THREAT_INTEL': 6, | |
| 'TOOL_DISCOVERY': 7, | |
| 'NETWORK': 8, | |
| 'SYSTEM': 9, | |
| 'FINANCIAL': 10, | |
| 'GEOPHYSICAL': 11, | |
| 'SPACE_WEATHER': 12 | |
| }; | |
| allData.sort((a, b) => { | |
| const priorityA = priorityOrder[a.type] || 99; | |
| const priorityB = priorityOrder[b.type] || 99; | |
| if (priorityA !== priorityB) return priorityA - priorityB; | |
| return 0; | |
| }); | |
| allData.forEach(item => { | |
| osintStream.appendChild(createOSINTItem(item)); | |
| }); | |
| feather.replace(); | |
| } | |
| // Auto-refresh data every 3 minutes | |
| loadRealData(); | |
| setInterval(loadRealData, 180000); | |
| // Add simple fade-in animation style dynamically | |
| const style = document.createElement('style'); | |
| style.innerHTML = ` | |
| @keyframes fadeIn { | |
| from { opacity: 0; transform: translateY(5px); } | |
| to { opacity: 1; transform: translateY(0); } | |
| } | |
| .animate-fade-in { | |
| animation: fadeIn 0.5s ease-out forwards; | |
| } | |
| `; | |
| document.head.appendChild(style); | |
| // Expose update function globally | |
| window.refreshOSINT = loadRealData; | |
| // Android Security Intelligence Feed | |
| async function loadAndroidSecurity() { | |
| const androidFeed = document.getElementById('android-security-feed'); | |
| if (!androidFeed) return; | |
| try { | |
| // Fetch real Android security tools from GitHub | |
| const githubResponse = await fetch('https://api.github.com/search/repositories?q=topic:android+topic:security+topic:malware+stars:>100&sort=updated&order=desc&per_page=5'); | |
| const githubData = await githubResponse.json(); | |
| // Fetch Android security patches bulletin (MITRE CVE database) | |
| const nvdResponse = await fetch('https://services.nvd.nist.gov/rest/json/cves/2.0?keywordSearch=android&resultsPerPage=3'); | |
| const nvdData = await nvdResponse.json(); | |
| const androidCVEs = nvdData.vulnerabilities?.map(vuln => ({ | |
| id: vuln.cve.id, | |
| score: vuln.cve.metrics?.cvssMetricV31?.[0]?.cvssData?.baseScore || 0, | |
| desc: vuln.cve.descriptions?.[0]?.value?.substring(0, 50) || 'No description' | |
| })) || []; | |
| androidFeed.innerHTML = githubData.items.map(repo => { | |
| const lastUpdated = new Date(repo.pushed_at); | |
| const daysSinceUpdate = Math.floor((new Date() - lastUpdated) / (1000 * 60 * 60 * 24)); | |
| const isRecent = daysSinceUpdate < 30; | |
| // Find related CVE if any | |
| const relatedCVE = androidCVEs.find(cve => | |
| repo.name.toLowerCase().includes('android') || | |
| repo.description?.toLowerCase().includes(cve.id.toLowerCase()) | |
| ); | |
| return ` | |
| <div class="flex items-center gap-3 p-3 bg-darker rounded-lg border ${isRecent ? 'border-green-900/50' : 'border-gray-800'} hover:border-gray-600 transition-all group"> | |
| <div class="w-10 h-10 ${repo.language === 'Kotlin' ? 'bg-purple-900/30' : repo.language === 'Java' ? 'bg-orange-900/30' : 'bg-gray-800'} rounded-lg flex items-center justify-center group-hover:scale-110 transition-transform"> | |
| <i data-feather="${repo.language === 'Kotlin' ? 'code-2' : repo.language === 'Java' ? 'box' : 'shield'}" class="${repo.language === 'Kotlin' ? 'text-purple-400' : repo.language === 'Java' ? 'text-orange-400' : 'text-gray-400'}"></i> | |
| </div> | |
| <div class="flex-1 min-w-0"> | |
| <div class="flex items-center gap-2"> | |
| <h4 class="text-white font-medium text-sm truncate">${repo.name}</h4> | |
| ${isRecent ? '<span class="text-[9px] px-1 py-0.5 rounded bg-green-600/30 text-green-400 font-bold animate-pulse">NEW</span>' : ''} | |
| </div> | |
| <p class="text-xs text-gray-500 truncate mt-0.5">${repo.description?.substring(0, 45) || 'No description'}...</p> | |
| <div class="flex items-center gap-2 mt-1.5 flex-wrap"> | |
| <span class="text-[10px] px-1.5 py-0.5 rounded bg-gray-800 text-gray-400">${repo.language || 'Unknown'}</span> | |
| <span class="text-[10px] text-gray-600">★ ${repo.stargazers_count.toLocaleString()}</span> | |
| ${repo.open_issues_count > 0 ? `<span class="text-[10px] text-yellow-500">${repo.open_issues_count} issues</span>` : ''} | |
| </div> | |
| </div> | |
| <div class="text-right"> | |
| ${relatedCVE ? ` | |
| <div class="text-[10px] px-1.5 py-0.5 rounded ${relatedCVE.score >= 7.0 ? 'bg-red-900/40 text-red-400' : 'bg-orange-900/40 text-orange-400'} font-mono mb-1"> | |
| ${relatedCVE.id} | |
| </div> | |
| <div class="text-[9px] text-gray-500">CVSS: ${relatedCVE.score}</div> | |
| ` : ` | |
| <a href="${repo.html_url}" target="_blank" rel="noopener noreferrer" class="text-[10px] px-2 py-1 rounded bg-primary/20 text-primary hover:bg-primary/30 transition"> | |
| View | |
| </a> | |
| `} | |
| </div> | |
| </div> | |
| `; | |
| }).join(''); | |
| feather.replace(); | |
| } catch (error) { | |
| console.error('Android Security Feed Error:', error); | |
| androidFeed.innerHTML = ` | |
| <div class="text-center py-6 text-gray-500 text-sm"> | |
| <i data-feather="alert-triangle" class="inline-block w-5 h-5 mb-2 text-secondary"></i> | |
| <p>Unable to load Android security data</p> | |
| <p class="text-xs text-gray-600 mt-1">Rate limit may apply</p> | |
| </div> | |
| `; | |
| feather.replace(); | |
| } | |
| } | |
| // Load Android security feed | |
| loadAndroidSecurity(); | |
| // Refresh every 5 minutes | |
| setInterval(loadAndroidSecurity, 300000); | |
| // Update threat summary based on real data | |
| async function updateThreatSummary() { | |
| const threatSummary = document.getElementById('threat-summary'); | |
| if (!threatSummary) return; | |
| try { | |
| const [cves, cisa, urlhaus] = await Promise.allSettled([ | |
| fetchNVDCVEs(), | |
| fetchCISAVulns(), | |
| fetchURLhaus() | |
| ]); | |
| const cveData = cves.status === 'fulfilled' ? cves.value : []; | |
| const cisaData = cisa.status === 'fulfilled' ? cisa.value : []; | |
| const malwareData = urlhaus.status === 'fulfilled' ? urlhaus.value : []; | |
| const criticalCount = cveData.filter(cve => cve.severity >= 9.0).length; | |
| const highCount = cveData.filter(cve => cve.severity >= 7.0 && cve.severity < 9.0).length; | |
| const urgentCISA = cisaData.filter(vuln => vuln.isUrgent).length; | |
| const totalThreats = cveData.length + cisaData.length + malwareData.length; | |
| const threatLevel = urgentCISA > 0 ? 'CRITICAL' : criticalCount > 0 ? 'HIGH' : totalThreats > 5 ? 'ELEVATED' : 'MODERATE'; | |
| const threatColor = { | |
| 'CRITICAL': 'text-red-500 animate-pulse', | |
| 'HIGH': 'text-orange-500', | |
| 'ELEVATED': 'text-yellow-500', | |
| 'MODERATE': 'text-green-400' | |
| }[threatLevel]; | |
| threatSummary.innerHTML = ` | |
| <span class="${threatColor} font-bold text-base">[${threatLevel}]</span> | |
| <span class="text-white font-semibold">${totalThreats.toLocaleString()}</span> active threats • | |
| <span class="text-red-400">${criticalCount}</span> critical / | |
| <span class="text-orange-400">${highCount}</span> high CVEs • | |
| <span class="text-purple-400">${cisaData.length}</span> CISA KEV • | |
| <span class="text-secondary">${malwareData.length}</span> malware URLs detected | |
| `; | |
| } catch (error) { | |
| threatSummary.textContent = 'Unable to fetch real-time threat data. Check network connection.'; | |
| } | |
| } | |
| // Initialize threat summary after initial data load | |
| setTimeout(updateThreatSummary, 2000); | |
| setInterval(updateThreatSummary, 180000); | |
| // Add keyboard shortcut for data refresh | |
| document.addEventListener('keydown', (e) => { | |
| if (e.ctrlKey && e.key === 'r') { | |
| e.preventDefault(); | |
| loadRealData(); | |
| loadAndroidSecurity(); | |
| } | |
| }); | |
| }); | |