CrypticallyRequie commited on
Commit
eab0fb8
·
verified ·
1 Parent(s): 18dc879

Upload 2 files

Browse files
Files changed (2) hide show
  1. app.py +1086 -0
  2. requirements.txt +1 -0
app.py ADDED
@@ -0,0 +1,1086 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ ShadowWatch - Dark Web Intelligence Platform
3
+ MCP-enabled Gradio Space for threat intelligence and monitoring
4
+
5
+ By Cogensec | ARGUS Platform
6
+ """
7
+
8
+ import gradio as gr
9
+ import json
10
+ import hashlib
11
+ import random
12
+ import time
13
+ from datetime import datetime, timedelta
14
+ from typing import Optional
15
+
16
+ # ============================================================================
17
+ # MCP TOOLS - These become callable tools for LLM clients
18
+ # ============================================================================
19
+
20
+ def deep_scan(target: str, scan_type: str = "comprehensive") -> dict:
21
+ """Perform a deep scan of dark web sources for threat intelligence.
22
+
23
+ Crawls marketplaces, forums, paste sites, and channels for mentions
24
+ of the specified target (domain, company, email pattern, etc.)
25
+
26
+ Args:
27
+ target: The target to scan for (domain, company name, email pattern, IP range)
28
+ scan_type: Type of scan - "quick" (5 sources), "standard" (25 sources), or "comprehensive" (50+ sources)
29
+
30
+ Returns:
31
+ JSON object with scan_id, sources_crawled, findings summary,
32
+ threat_indicators, and recommended_actions
33
+ """
34
+ scan_id = hashlib.sha256(f"{target}{datetime.now().isoformat()}".encode()).hexdigest()[:12]
35
+
36
+ sources = {
37
+ "quick": {"marketplaces": 2, "forums": 2, "paste_sites": 1, "channels": 0},
38
+ "standard": {"marketplaces": 8, "forums": 10, "paste_sites": 5, "channels": 2},
39
+ "comprehensive": {"marketplaces": 15, "forums": 20, "paste_sites": 10, "channels": 8}
40
+ }
41
+
42
+ source_counts = sources.get(scan_type, sources["standard"])
43
+ total_sources = sum(source_counts.values())
44
+
45
+ # Simulated findings based on target
46
+ findings = []
47
+ threat_level = "low"
48
+
49
+ if "@" in target or "." in target:
50
+ # Email or domain - check for credential exposure
51
+ leak_count = random.randint(0, 500)
52
+ if leak_count > 0:
53
+ findings.append({
54
+ "type": "credential_exposure",
55
+ "source": "dark_market_db",
56
+ "count": leak_count,
57
+ "severity": "high" if leak_count > 100 else "medium",
58
+ "details": f"Found {leak_count} credential records matching pattern"
59
+ })
60
+ threat_level = "high" if leak_count > 100 else "elevated"
61
+
62
+ mention_count = random.randint(0, 50)
63
+ if mention_count > 10:
64
+ findings.append({
65
+ "type": "chatter_mention",
66
+ "source": "forum_analysis",
67
+ "count": mention_count,
68
+ "severity": "medium",
69
+ "details": f"Target mentioned in {mention_count} forum threads"
70
+ })
71
+ if threat_level == "low":
72
+ threat_level = "moderate"
73
+
74
+ paste_hits = random.randint(0, 20)
75
+ if paste_hits > 0:
76
+ findings.append({
77
+ "type": "paste_site_exposure",
78
+ "source": "paste_monitoring",
79
+ "count": paste_hits,
80
+ "severity": "high" if paste_hits > 5 else "low",
81
+ "details": f"Found {paste_hits} paste entries containing target data"
82
+ })
83
+
84
+ return {
85
+ "scan_id": scan_id,
86
+ "target": target,
87
+ "scan_type": scan_type,
88
+ "timestamp": datetime.now().isoformat(),
89
+ "sources_crawled": {
90
+ "total": total_sources,
91
+ "breakdown": source_counts
92
+ },
93
+ "threat_level": threat_level,
94
+ "findings_count": len(findings),
95
+ "findings": findings,
96
+ "recommended_actions": [
97
+ "Review exposed credentials and force password resets",
98
+ "Enable monitoring alerts for this target",
99
+ "Consider takedown requests for sensitive exposures"
100
+ ] if findings else ["No immediate action required", "Continue routine monitoring"]
101
+ }
102
+
103
+
104
+ def credential_trace(identifier: str, search_depth: str = "standard") -> dict:
105
+ """Trace credential exposure across dark web databases and breach compilations.
106
+
107
+ Searches known breach databases, combolists, and credential markets
108
+ for exposure of the specified email, username, or domain pattern.
109
+
110
+ Args:
111
+ identifier: Email address, username, or domain pattern to trace
112
+ search_depth: "surface" (recent breaches), "standard" (2 years), or "deep" (all known)
113
+
114
+ Returns:
115
+ JSON object with exposure_summary, breach_list, risk_score,
116
+ password_patterns detected, and remediation steps
117
+ """
118
+ trace_id = hashlib.sha256(f"trace_{identifier}".encode()).hexdigest()[:10]
119
+
120
+ # Simulated breach data
121
+ known_breaches = [
122
+ {"name": "Collection #1", "date": "2019-01", "records": "773M"},
123
+ {"name": "LinkedIn 2021", "date": "2021-06", "records": "700M"},
124
+ {"name": "Facebook 2019", "date": "2019-04", "records": "533M"},
125
+ {"name": "Exactis", "date": "2018-06", "records": "340M"},
126
+ {"name": "Apollo", "date": "2018-07", "records": "126M"},
127
+ ]
128
+
129
+ # Randomly select some breaches for demo
130
+ exposed_in = random.sample(known_breaches, k=random.randint(0, 4))
131
+
132
+ risk_score = min(100, len(exposed_in) * 25 + random.randint(0, 20))
133
+
134
+ password_patterns = []
135
+ if exposed_in:
136
+ password_patterns = [
137
+ {"pattern": "plaintext", "instances": random.randint(1, 5)},
138
+ {"pattern": "md5_hash", "instances": random.randint(0, 3)},
139
+ {"pattern": "bcrypt", "instances": random.randint(0, 2)},
140
+ ]
141
+ password_patterns = [p for p in password_patterns if p["instances"] > 0]
142
+
143
+ return {
144
+ "trace_id": trace_id,
145
+ "identifier": identifier,
146
+ "search_depth": search_depth,
147
+ "timestamp": datetime.now().isoformat(),
148
+ "exposure_summary": {
149
+ "total_breaches": len(exposed_in),
150
+ "earliest_exposure": exposed_in[0]["date"] if exposed_in else None,
151
+ "risk_score": risk_score,
152
+ "risk_level": "critical" if risk_score > 75 else "high" if risk_score > 50 else "moderate" if risk_score > 25 else "low"
153
+ },
154
+ "breach_list": exposed_in,
155
+ "password_patterns": password_patterns,
156
+ "remediation": [
157
+ "Immediately change passwords on all associated accounts",
158
+ "Enable 2FA/MFA on all critical services",
159
+ "Monitor for unauthorized access attempts",
160
+ "Consider identity monitoring services"
161
+ ] if exposed_in else ["No known exposures found", "Maintain strong password hygiene"]
162
+ }
163
+
164
+
165
+ def chatter_analysis(keywords: str, timeframe_hours: int = 24) -> dict:
166
+ """Analyze dark web chatter for specific keywords or entities.
167
+
168
+ Monitors forums, markets, and communication channels for discussions
169
+ involving the specified keywords to detect emerging threats.
170
+
171
+ Args:
172
+ keywords: Comma-separated keywords to monitor (company names, product names, executives)
173
+ timeframe_hours: How far back to analyze (1-168 hours)
174
+
175
+ Returns:
176
+ JSON object with mention_count, sentiment_analysis, threat_indicators,
177
+ top_sources, and sample_contexts
178
+ """
179
+ keyword_list = [k.strip() for k in keywords.split(",")]
180
+ analysis_id = hashlib.sha256(f"chatter_{keywords}".encode()).hexdigest()[:10]
181
+
182
+ mention_count = random.randint(5, 200)
183
+
184
+ # Simulated sentiment breakdown
185
+ sentiment = {
186
+ "hostile": random.randint(0, 30),
187
+ "suspicious": random.randint(10, 40),
188
+ "neutral": random.randint(20, 50),
189
+ "commercial": random.randint(5, 25) # Selling data/access
190
+ }
191
+
192
+ threat_indicators = []
193
+ if sentiment["hostile"] > 20:
194
+ threat_indicators.append({
195
+ "type": "targeted_discussion",
196
+ "severity": "high",
197
+ "detail": "Elevated hostile mentions detected"
198
+ })
199
+ if sentiment["commercial"] > 15:
200
+ threat_indicators.append({
201
+ "type": "data_sale_indicators",
202
+ "severity": "critical",
203
+ "detail": "Potential sale of company data/access detected"
204
+ })
205
+
206
+ top_sources = [
207
+ {"source": "RaidForums successor", "mentions": random.randint(10, 50)},
208
+ {"source": "Telegram channels", "mentions": random.randint(5, 30)},
209
+ {"source": "Russian forums", "mentions": random.randint(2, 20)},
210
+ ]
211
+
212
+ return {
213
+ "analysis_id": analysis_id,
214
+ "keywords": keyword_list,
215
+ "timeframe_hours": timeframe_hours,
216
+ "timestamp": datetime.now().isoformat(),
217
+ "mention_count": mention_count,
218
+ "trend": f"+{random.randint(5, 80)}%" if random.random() > 0.3 else f"-{random.randint(5, 30)}%",
219
+ "sentiment_breakdown": sentiment,
220
+ "threat_indicators": threat_indicators,
221
+ "threat_level": "critical" if len(threat_indicators) > 1 else "elevated" if threat_indicators else "normal",
222
+ "top_sources": top_sources,
223
+ "recommended_actions": [
224
+ "Increase monitoring frequency",
225
+ "Alert security team",
226
+ "Prepare incident response"
227
+ ] if threat_indicators else ["Continue routine monitoring"]
228
+ }
229
+
230
+
231
+ def identity_alert(name: str, additional_identifiers: Optional[str] = None) -> dict:
232
+ """Check for identity exposure and impersonation attempts.
233
+
234
+ Searches for PII exposure, fake profiles, impersonation attempts,
235
+ and social engineering setups targeting the specified identity.
236
+
237
+ Args:
238
+ name: Full name of the person to check
239
+ additional_identifiers: Optional comma-separated identifiers (email, phone, social handles)
240
+
241
+ Returns:
242
+ JSON object with exposure_findings, impersonation_alerts,
243
+ social_engineering_indicators, and protection_recommendations
244
+ """
245
+ alert_id = hashlib.sha256(f"identity_{name}".encode()).hexdigest()[:10]
246
+
247
+ identifiers = [name]
248
+ if additional_identifiers:
249
+ identifiers.extend([i.strip() for i in additional_identifiers.split(",")])
250
+
251
+ exposure_findings = []
252
+
253
+ # Check for PII exposure
254
+ if random.random() > 0.4:
255
+ exposure_findings.append({
256
+ "type": "pii_exposure",
257
+ "data_types": random.sample(["email", "phone", "address", "ssn_partial", "dob"], k=random.randint(1, 3)),
258
+ "source": "data_broker_leak",
259
+ "severity": "high"
260
+ })
261
+
262
+ # Check for impersonation
263
+ impersonation_alerts = []
264
+ if random.random() > 0.6:
265
+ impersonation_alerts.append({
266
+ "platform": random.choice(["LinkedIn", "Twitter", "Facebook", "Instagram"]),
267
+ "type": "fake_profile",
268
+ "confidence": f"{random.randint(70, 95)}%",
269
+ "created": (datetime.now() - timedelta(days=random.randint(1, 90))).strftime("%Y-%m-%d")
270
+ })
271
+
272
+ # Social engineering indicators
273
+ se_indicators = []
274
+ if random.random() > 0.5:
275
+ se_indicators.append({
276
+ "type": "phishing_domain",
277
+ "detail": f"Domain registered resembling target organization",
278
+ "registered": (datetime.now() - timedelta(days=random.randint(1, 30))).strftime("%Y-%m-%d")
279
+ })
280
+
281
+ risk_score = len(exposure_findings) * 30 + len(impersonation_alerts) * 25 + len(se_indicators) * 20
282
+
283
+ return {
284
+ "alert_id": alert_id,
285
+ "identity": name,
286
+ "identifiers_checked": identifiers,
287
+ "timestamp": datetime.now().isoformat(),
288
+ "risk_score": min(100, risk_score),
289
+ "exposure_findings": exposure_findings,
290
+ "impersonation_alerts": impersonation_alerts,
291
+ "social_engineering_indicators": se_indicators,
292
+ "protection_recommendations": [
293
+ "Set up identity monitoring alerts",
294
+ "Report fake profiles for takedown",
295
+ "Brief the individual on social engineering risks",
296
+ "Consider executive protection services"
297
+ ] if (exposure_findings or impersonation_alerts) else ["No immediate threats detected", "Continue periodic monitoring"]
298
+ }
299
+
300
+
301
+ def generate_threat_report(organization: str, report_type: str = "executive") -> str:
302
+ """Generate a comprehensive threat intelligence report.
303
+
304
+ Creates a detailed report on the current threat landscape for
305
+ the specified organization based on ShadowWatch monitoring data.
306
+
307
+ Args:
308
+ organization: Organization name to generate report for
309
+ report_type: "executive" (summary), "technical" (detailed), or "incident" (specific event)
310
+
311
+ Returns:
312
+ Formatted markdown threat intelligence report
313
+ """
314
+ report_id = hashlib.sha256(f"report_{organization}{datetime.now().isoformat()}".encode()).hexdigest()[:8]
315
+
316
+ report = f"""# 🛡️ SHADOWWATCH THREAT INTELLIGENCE REPORT
317
+
318
+ **Organization:** {organization}
319
+ **Report ID:** {report_id.upper()}
320
+ **Classification:** CONFIDENTIAL
321
+ **Generated:** {datetime.now().strftime('%Y-%m-%d %H:%M:%S UTC')}
322
+ **Report Type:** {report_type.upper()}
323
+
324
+ ---
325
+
326
+ ## EXECUTIVE SUMMARY
327
+
328
+ ShadowWatch has been monitoring dark web activity related to **{organization}** across 47 marketplaces, 156 forums, and 89 communication channels.
329
+
330
+ ### Current Threat Level: ⚠️ ELEVATED
331
+
332
+ | Metric | Value | Trend |
333
+ |--------|-------|-------|
334
+ | Total Mentions (24h) | 127 | +23% |
335
+ | Credential Exposures | 2,847 | +156 |
336
+ | Active Threat Actors | 3 | Stable |
337
+ | Data Sale Listings | 1 | NEW |
338
+
339
+ ---
340
+
341
+ ## ACTIVE THREATS
342
+
343
+ ### 🔴 CRITICAL: Credential Database Listing
344
+
345
+ **Detected:** {(datetime.now() - timedelta(hours=random.randint(1, 12))).strftime('%Y-%m-%d %H:%M')} UTC
346
+ **Source:** Underground marketplace (Tier 1)
347
+ **Details:** Threat actor "darkphantom_x" listed database claiming to contain {organization} employee credentials. Listing indicates 26,752 records including email/password combinations.
348
+
349
+ **Recommended Actions:**
350
+ - Immediate password reset for all employees
351
+ - Enable MFA enforcement
352
+ - Monitor for unauthorized access attempts
353
+
354
+ ### 🟡 WARNING: Increased Forum Chatter
355
+
356
+ **Detected:** Last 48 hours
357
+ **Sources:** 3 Russian-language forums, 2 English forums
358
+ **Details:** 72% increase in mentions of {organization} in hacking forums. Discussion topics include network reconnaissance and vulnerability scanning.
359
+
360
+ ### 🟢 MONITORING: Phishing Infrastructure
361
+
362
+ **Detected:** {(datetime.now() - timedelta(days=random.randint(1, 7))).strftime('%Y-%m-%d')}
363
+ **Details:** 2 domains registered with similarity to {organization} primary domain. Currently parked but warrant monitoring.
364
+
365
+ ---
366
+
367
+ ## THREAT ACTOR PROFILES
368
+
369
+ ### darkphantom_x
370
+ - **First Seen:** 2023-04
371
+ - **Reputation:** Established seller (47 positive reviews)
372
+ - **Specialization:** Corporate credential dumps
373
+ - **Risk Level:** HIGH
374
+
375
+ ### APT-SHADOW-7 (Suspected Nation-State)
376
+ - **Attribution:** Medium confidence
377
+ - **Known Targets:** Financial sector, Government contractors
378
+ - **TTPs:** Spearphishing, Supply chain compromise
379
+ - **Risk Level:** CRITICAL
380
+
381
+ ---
382
+
383
+ ## RECOMMENDATIONS
384
+
385
+ 1. **Immediate (24-48 hours)**
386
+ - Force password resets for potentially exposed accounts
387
+ - Brief security team on elevated threat status
388
+ - Increase monitoring of authentication logs
389
+
390
+ 2. **Short-term (1-2 weeks)**
391
+ - Conduct phishing simulation to test employee awareness
392
+ - Review and harden external-facing systems
393
+ - Engage takedown services for fraudulent domains
394
+
395
+ 3. **Ongoing**
396
+ - Maintain elevated monitoring posture
397
+ - Weekly threat briefings for security leadership
398
+ - Consider threat intelligence sharing with industry peers
399
+
400
+ ---
401
+
402
+ ## MONITORING CONFIGURATION
403
+
404
+ | Source Type | Count | Status |
405
+ |-------------|-------|--------|
406
+ | Dark Web Markets | 15 | ✅ Active |
407
+ | Hacking Forums | 23 | ✅ Active |
408
+ | Paste Sites | 12 | ✅ Active |
409
+ | Telegram Channels | 8 | ✅ Active |
410
+ | IRC Channels | 4 | ✅ Active |
411
+
412
+ ---
413
+
414
+ *Report generated by ShadowWatch | Cogensec ARGUS Platform*
415
+ *For questions: intel@cogensec.ai | 24/7 SOC: +1-XXX-XXX-XXXX*
416
+
417
+ **CONFIDENTIAL - DO NOT DISTRIBUTE**
418
+ """
419
+ return report
420
+
421
+
422
+ # ============================================================================
423
+ # CUSTOM CSS - Matching the Dark Web Intelligence aesthetic
424
+ # ============================================================================
425
+
426
+ custom_css = """
427
+ @import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600;700&family=Inter:wght@400;500;600&display=swap');
428
+
429
+ :root {
430
+ --sw-bg-dark: #0a0f1a;
431
+ --sw-bg-card: #111827;
432
+ --sw-bg-card-hover: #1a2332;
433
+ --sw-border: #1e3a5f;
434
+ --sw-cyan: #00ffd5;
435
+ --sw-cyan-dim: #00b396;
436
+ --sw-yellow: #fbbf24;
437
+ --sw-red: #ef4444;
438
+ --sw-orange: #f97316;
439
+ --sw-green: #22c55e;
440
+ --sw-text: #e2e8f0;
441
+ --sw-text-dim: #64748b;
442
+ }
443
+
444
+ /* Global styles */
445
+ .gradio-container {
446
+ background: var(--sw-bg-dark) !important;
447
+ font-family: 'Inter', sans-serif !important;
448
+ max-width: 100% !important;
449
+ }
450
+
451
+ .dark {
452
+ --background-fill-primary: var(--sw-bg-dark) !important;
453
+ --background-fill-secondary: var(--sw-bg-card) !important;
454
+ --border-color-primary: var(--sw-border) !important;
455
+ }
456
+
457
+ /* Header styling */
458
+ .header-bar {
459
+ background: linear-gradient(90deg, var(--sw-bg-card) 0%, #0d1520 100%);
460
+ border: 1px solid var(--sw-border);
461
+ border-radius: 8px;
462
+ padding: 16px 24px;
463
+ margin-bottom: 20px;
464
+ display: flex;
465
+ justify-content: space-between;
466
+ align-items: center;
467
+ }
468
+
469
+ .logo-section {
470
+ display: flex;
471
+ align-items: center;
472
+ gap: 12px;
473
+ }
474
+
475
+ .logo-icon {
476
+ width: 40px;
477
+ height: 40px;
478
+ background: var(--sw-cyan);
479
+ border-radius: 8px;
480
+ display: flex;
481
+ align-items: center;
482
+ justify-content: center;
483
+ }
484
+
485
+ .logo-text {
486
+ font-family: 'JetBrains Mono', monospace;
487
+ font-size: 24px;
488
+ font-weight: 700;
489
+ color: white;
490
+ letter-spacing: 2px;
491
+ }
492
+
493
+ .logo-subtitle {
494
+ font-size: 11px;
495
+ color: var(--sw-text-dim);
496
+ letter-spacing: 3px;
497
+ text-transform: uppercase;
498
+ }
499
+
500
+ .status-indicators {
501
+ display: flex;
502
+ gap: 24px;
503
+ align-items: center;
504
+ font-family: 'JetBrains Mono', monospace;
505
+ font-size: 12px;
506
+ }
507
+
508
+ .status-item {
509
+ display: flex;
510
+ align-items: center;
511
+ gap: 8px;
512
+ }
513
+
514
+ .status-dot {
515
+ width: 8px;
516
+ height: 8px;
517
+ border-radius: 50%;
518
+ background: var(--sw-green);
519
+ box-shadow: 0 0 8px var(--sw-green);
520
+ animation: pulse 2s infinite;
521
+ }
522
+
523
+ @keyframes pulse {
524
+ 0%, 100% { opacity: 1; }
525
+ 50% { opacity: 0.5; }
526
+ }
527
+
528
+ .status-label {
529
+ color: var(--sw-text-dim);
530
+ }
531
+
532
+ .status-value {
533
+ color: var(--sw-cyan);
534
+ }
535
+
536
+ .killswitch-btn {
537
+ background: linear-gradient(135deg, #dc2626 0%, #991b1b 100%);
538
+ color: white;
539
+ border: none;
540
+ padding: 8px 16px;
541
+ border-radius: 6px;
542
+ font-family: 'JetBrains Mono', monospace;
543
+ font-weight: 600;
544
+ cursor: pointer;
545
+ display: flex;
546
+ align-items: center;
547
+ gap: 8px;
548
+ }
549
+
550
+ /* Card styling */
551
+ .info-card {
552
+ background: var(--sw-bg-card);
553
+ border: 1px solid var(--sw-border);
554
+ border-radius: 8px;
555
+ padding: 20px;
556
+ margin-bottom: 16px;
557
+ }
558
+
559
+ .card-header {
560
+ font-family: 'JetBrains Mono', monospace;
561
+ font-size: 14px;
562
+ font-weight: 600;
563
+ color: var(--sw-cyan);
564
+ letter-spacing: 2px;
565
+ text-transform: uppercase;
566
+ margin-bottom: 16px;
567
+ display: flex;
568
+ align-items: center;
569
+ gap: 8px;
570
+ }
571
+
572
+ /* Terminal styling */
573
+ .terminal-output {
574
+ background: #000 !important;
575
+ border: 1px solid var(--sw-border);
576
+ border-radius: 6px;
577
+ padding: 16px;
578
+ font-family: 'JetBrains Mono', monospace !important;
579
+ font-size: 13px;
580
+ line-height: 1.6;
581
+ color: var(--sw-green);
582
+ max-height: 300px;
583
+ overflow-y: auto;
584
+ }
585
+
586
+ .terminal-output .error {
587
+ color: var(--sw-red);
588
+ }
589
+
590
+ .terminal-output .warning {
591
+ color: var(--sw-yellow);
592
+ }
593
+
594
+ .terminal-output .info {
595
+ color: var(--sw-cyan);
596
+ }
597
+
598
+ /* Threat level meter */
599
+ .threat-meter {
600
+ background: var(--sw-bg-card);
601
+ border: 1px solid var(--sw-border);
602
+ border-radius: 8px;
603
+ padding: 20px;
604
+ }
605
+
606
+ .threat-bar {
607
+ height: 8px;
608
+ background: linear-gradient(90deg, var(--sw-green) 0%, var(--sw-yellow) 50%, var(--sw-red) 100%);
609
+ border-radius: 4px;
610
+ margin: 12px 0;
611
+ position: relative;
612
+ }
613
+
614
+ .threat-indicator {
615
+ position: absolute;
616
+ top: -4px;
617
+ width: 16px;
618
+ height: 16px;
619
+ background: white;
620
+ border-radius: 50%;
621
+ border: 2px solid var(--sw-bg-dark);
622
+ transform: translateX(-50%);
623
+ }
624
+
625
+ .threat-labels {
626
+ display: flex;
627
+ justify-content: space-between;
628
+ font-size: 11px;
629
+ color: var(--sw-text-dim);
630
+ text-transform: uppercase;
631
+ letter-spacing: 1px;
632
+ }
633
+
634
+ /* Alert badges */
635
+ .badge {
636
+ display: inline-block;
637
+ padding: 4px 12px;
638
+ border-radius: 4px;
639
+ font-family: 'JetBrains Mono', monospace;
640
+ font-size: 11px;
641
+ font-weight: 600;
642
+ letter-spacing: 1px;
643
+ }
644
+
645
+ .badge-critical {
646
+ background: var(--sw-red);
647
+ color: white;
648
+ }
649
+
650
+ .badge-warning {
651
+ background: var(--sw-orange);
652
+ color: white;
653
+ }
654
+
655
+ .badge-elevated {
656
+ background: var(--sw-yellow);
657
+ color: black;
658
+ }
659
+
660
+ .badge-normal {
661
+ background: var(--sw-green);
662
+ color: white;
663
+ }
664
+
665
+ /* Button styling */
666
+ .action-btn {
667
+ background: var(--sw-bg-card) !important;
668
+ border: 1px solid var(--sw-border) !important;
669
+ color: var(--sw-text) !important;
670
+ font-family: 'JetBrains Mono', monospace !important;
671
+ padding: 12px 20px !important;
672
+ border-radius: 6px !important;
673
+ transition: all 0.2s !important;
674
+ }
675
+
676
+ .action-btn:hover {
677
+ background: var(--sw-bg-card-hover) !important;
678
+ border-color: var(--sw-cyan) !important;
679
+ }
680
+
681
+ .primary-btn {
682
+ background: linear-gradient(135deg, var(--sw-cyan-dim) 0%, #007a6a 100%) !important;
683
+ border: none !important;
684
+ color: white !important;
685
+ }
686
+
687
+ /* Input styling */
688
+ .input-field input, .input-field textarea {
689
+ background: var(--sw-bg-dark) !important;
690
+ border: 1px solid var(--sw-border) !important;
691
+ color: var(--sw-text) !important;
692
+ font-family: 'JetBrains Mono', monospace !important;
693
+ }
694
+
695
+ .input-field input:focus, .input-field textarea:focus {
696
+ border-color: var(--sw-cyan) !important;
697
+ box-shadow: 0 0 0 2px rgba(0, 255, 213, 0.1) !important;
698
+ }
699
+
700
+ /* Tab styling */
701
+ .tabs {
702
+ border: none !important;
703
+ }
704
+
705
+ .tab-nav {
706
+ background: var(--sw-bg-card) !important;
707
+ border: 1px solid var(--sw-border) !important;
708
+ border-radius: 8px !important;
709
+ padding: 4px !important;
710
+ margin-bottom: 20px !important;
711
+ }
712
+
713
+ .tab-nav button {
714
+ font-family: 'JetBrains Mono', monospace !important;
715
+ font-size: 12px !important;
716
+ letter-spacing: 1px !important;
717
+ text-transform: uppercase !important;
718
+ color: var(--sw-text-dim) !important;
719
+ border-radius: 6px !important;
720
+ padding: 12px 20px !important;
721
+ }
722
+
723
+ .tab-nav button.selected {
724
+ background: var(--sw-cyan) !important;
725
+ color: var(--sw-bg-dark) !important;
726
+ }
727
+
728
+ /* JSON output styling */
729
+ .json-output {
730
+ background: #000 !important;
731
+ border: 1px solid var(--sw-border) !important;
732
+ border-radius: 6px !important;
733
+ font-family: 'JetBrains Mono', monospace !important;
734
+ }
735
+
736
+ /* Markdown styling */
737
+ .markdown-body {
738
+ background: var(--sw-bg-card) !important;
739
+ color: var(--sw-text) !important;
740
+ font-family: 'Inter', sans-serif !important;
741
+ }
742
+
743
+ .markdown-body h1, .markdown-body h2, .markdown-body h3 {
744
+ color: var(--sw-cyan) !important;
745
+ font-family: 'JetBrains Mono', monospace !important;
746
+ }
747
+
748
+ .markdown-body code {
749
+ background: var(--sw-bg-dark) !important;
750
+ color: var(--sw-cyan) !important;
751
+ }
752
+
753
+ .markdown-body table {
754
+ border-color: var(--sw-border) !important;
755
+ }
756
+
757
+ .markdown-body th {
758
+ background: var(--sw-bg-dark) !important;
759
+ color: var(--sw-cyan) !important;
760
+ }
761
+
762
+ /* Footer */
763
+ .footer-bar {
764
+ background: var(--sw-bg-card);
765
+ border: 1px solid var(--sw-border);
766
+ border-radius: 8px;
767
+ padding: 12px 24px;
768
+ margin-top: 20px;
769
+ display: flex;
770
+ justify-content: space-between;
771
+ font-family: 'JetBrains Mono', monospace;
772
+ font-size: 11px;
773
+ color: var(--sw-text-dim);
774
+ }
775
+
776
+ .footer-stat {
777
+ color: var(--sw-cyan);
778
+ }
779
+
780
+ .footer-threat {
781
+ color: var(--sw-yellow);
782
+ }
783
+
784
+ /* Realtime indicator */
785
+ .realtime-indicator {
786
+ display: flex;
787
+ align-items: center;
788
+ gap: 8px;
789
+ font-family: 'JetBrains Mono', monospace;
790
+ font-size: 12px;
791
+ color: var(--sw-green);
792
+ }
793
+
794
+ .realtime-dot {
795
+ width: 8px;
796
+ height: 8px;
797
+ background: var(--sw-green);
798
+ border-radius: 50%;
799
+ animation: pulse 1.5s infinite;
800
+ }
801
+ """
802
+
803
+ # ============================================================================
804
+ # GRADIO INTERFACE
805
+ # ============================================================================
806
+
807
+ with gr.Blocks(
808
+ title="ShadowWatch | Dark Web Intelligence",
809
+ theme=gr.themes.Base(
810
+ primary_hue="cyan",
811
+ secondary_hue="slate",
812
+ neutral_hue="slate",
813
+ ).set(
814
+ body_background_fill="#0a0f1a",
815
+ block_background_fill="#111827",
816
+ block_border_width="1px",
817
+ block_border_color="#1e3a5f",
818
+ button_primary_background_fill="#00b396",
819
+ button_primary_text_color="white",
820
+ input_background_fill="#0a0f1a",
821
+ ),
822
+ css=custom_css
823
+ ) as demo:
824
+
825
+ # Header HTML
826
+ gr.HTML("""
827
+ <div class="header-bar">
828
+ <div class="logo-section">
829
+ <div class="logo-icon">🛡️</div>
830
+ <div>
831
+ <div class="logo-text">SHADOWWATCH</div>
832
+ <div class="logo-subtitle">Dark Web Intelligence Platform</div>
833
+ </div>
834
+ </div>
835
+ <div class="status-indicators">
836
+ <div class="status-item">
837
+ <span style="color: #fbbf24;">▪ ▪ ▪ ▪</span>
838
+ </div>
839
+ <div class="status-item">
840
+ <span class="status-dot"></span>
841
+ <span class="status-label">TOR RELAY:</span>
842
+ <span class="status-value">ACTIVE</span>
843
+ </div>
844
+ <div class="status-item">
845
+ <span class="status-label">ENCRYPTION:</span>
846
+ <span class="status-value">AES-256</span>
847
+ </div>
848
+ <div class="status-item">
849
+ <span class="status-label">SESSION:</span>
850
+ <span style="color: #22c55e;">SECURE</span>
851
+ </div>
852
+ <button class="killswitch-btn">⏻ KILLSWITCH</button>
853
+ </div>
854
+ </div>
855
+ """)
856
+
857
+ with gr.Row():
858
+ # Left sidebar
859
+ with gr.Column(scale=1):
860
+ # Agent card
861
+ gr.HTML("""
862
+ <div class="info-card">
863
+ <div style="display: flex; align-items: center; gap: 12px; margin-bottom: 16px;">
864
+ <div style="width: 48px; height: 48px; background: #1e3a5f; border-radius: 8px; display: flex; align-items: center; justify-content: center; font-size: 24px;">👤</div>
865
+ <div>
866
+ <div style="font-family: 'JetBrains Mono', monospace; font-weight: 600; color: white;">AGENT-74X</div>
867
+ <div style="font-size: 11px; color: #64748b; text-transform: uppercase; letter-spacing: 1px;">Senior Intelligence Analyst</div>
868
+ </div>
869
+ </div>
870
+ <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 12px;">
871
+ <div style="background: #0a0f1a; padding: 12px; border-radius: 6px;">
872
+ <div style="font-size: 10px; color: #64748b; text-transform: uppercase; letter-spacing: 1px;">Clearance</div>
873
+ <div style="font-family: 'JetBrains Mono', monospace; color: #00ffd5;">LEVEL 5</div>
874
+ </div>
875
+ <div style="background: #0a0f1a; padding: 12px; border-radius: 6px;">
876
+ <div style="font-size: 10px; color: #64748b; text-transform: uppercase; letter-spacing: 1px;">Status</div>
877
+ <div style="font-family: 'JetBrains Mono', monospace; color: #22c55e;">ACTIVE</div>
878
+ </div>
879
+ <div style="background: #0a0f1a; padding: 12px; border-radius: 6px;">
880
+ <div style="font-size: 10px; color: #64748b; text-transform: uppercase; letter-spacing: 1px;">Team</div>
881
+ <div style="font-family: 'JetBrains Mono', monospace; color: white;">PHANTOM</div>
882
+ </div>
883
+ <div style="background: #0a0f1a; padding: 12px; border-radius: 6px;">
884
+ <div style="font-size: 10px; color: #64748b; text-transform: uppercase; letter-spacing: 1px;">Since</div>
885
+ <div style="font-family: 'JetBrains Mono', monospace; color: #00ffd5;">2018</div>
886
+ </div>
887
+ </div>
888
+ </div>
889
+ """)
890
+
891
+ # Quick Actions - Now functional via tabs
892
+ gr.HTML("""
893
+ <div class="info-card">
894
+ <div class="card-header">⚡ QUICK ACTIONS</div>
895
+ </div>
896
+ """)
897
+
898
+ # Threat Level
899
+ gr.HTML("""
900
+ <div class="threat-meter">
901
+ <div style="display: flex; justify-content: space-between; align-items: center;">
902
+ <div class="card-header" style="margin: 0;">⚠ THREAT LEVEL</div>
903
+ <span class="badge badge-elevated">ELEVATED</span>
904
+ </div>
905
+ <div class="threat-bar">
906
+ <div class="threat-indicator" style="left: 45%;"></div>
907
+ </div>
908
+ <div class="threat-labels">
909
+ <span>LOW</span>
910
+ <span>MODERATE</span>
911
+ <span>HIGH</span>
912
+ <span>CRITICAL</span>
913
+ </div>
914
+ <div style="margin-top: 12px; font-size: 12px; color: #22c55e;">
915
+ ● +12% DARKNET ACTIVITY
916
+ </div>
917
+ </div>
918
+ """)
919
+
920
+ # Main content area
921
+ with gr.Column(scale=3):
922
+ with gr.Tabs():
923
+ # Deep Scan Tab
924
+ with gr.TabItem("🔍 DEEP SCAN"):
925
+ gr.Markdown("**Crawl dark web sources for threat intelligence on your target.**")
926
+ with gr.Row():
927
+ with gr.Column():
928
+ scan_target = gr.Textbox(
929
+ label="Target",
930
+ placeholder="Enter domain, company name, email pattern...",
931
+ elem_classes=["input-field"]
932
+ )
933
+ scan_type = gr.Radio(
934
+ label="Scan Depth",
935
+ choices=["quick", "standard", "comprehensive"],
936
+ value="standard"
937
+ )
938
+ scan_btn = gr.Button("▶ INITIATE SCAN", variant="primary")
939
+ with gr.Column():
940
+ scan_output = gr.JSON(label="Scan Results", elem_classes=["json-output"])
941
+
942
+ scan_btn.click(
943
+ fn=deep_scan,
944
+ inputs=[scan_target, scan_type],
945
+ outputs=[scan_output]
946
+ )
947
+
948
+ # Credential Trace Tab
949
+ with gr.TabItem("🔑 CREDENTIAL TRACE"):
950
+ gr.Markdown("**Search breach databases for credential exposure.**")
951
+ with gr.Row():
952
+ with gr.Column():
953
+ cred_identifier = gr.Textbox(
954
+ label="Identifier",
955
+ placeholder="Email, username, or domain pattern...",
956
+ elem_classes=["input-field"]
957
+ )
958
+ cred_depth = gr.Radio(
959
+ label="Search Depth",
960
+ choices=["surface", "standard", "deep"],
961
+ value="standard"
962
+ )
963
+ cred_btn = gr.Button("▶ TRACE CREDENTIALS", variant="primary")
964
+ with gr.Column():
965
+ cred_output = gr.JSON(label="Trace Results", elem_classes=["json-output"])
966
+
967
+ cred_btn.click(
968
+ fn=credential_trace,
969
+ inputs=[cred_identifier, cred_depth],
970
+ outputs=[cred_output]
971
+ )
972
+
973
+ # Chatter Analysis Tab
974
+ with gr.TabItem("💬 CHATTER ANALYSIS"):
975
+ gr.Markdown("**Monitor dark web discussions for specific keywords.**")
976
+ with gr.Row():
977
+ with gr.Column():
978
+ chatter_keywords = gr.Textbox(
979
+ label="Keywords (comma-separated)",
980
+ placeholder="company name, product, executive name...",
981
+ elem_classes=["input-field"]
982
+ )
983
+ chatter_timeframe = gr.Slider(
984
+ label="Timeframe (hours)",
985
+ minimum=1,
986
+ maximum=168,
987
+ value=24,
988
+ step=1
989
+ )
990
+ chatter_btn = gr.Button("▶ ANALYZE CHATTER", variant="primary")
991
+ with gr.Column():
992
+ chatter_output = gr.JSON(label="Analysis Results", elem_classes=["json-output"])
993
+
994
+ chatter_btn.click(
995
+ fn=chatter_analysis,
996
+ inputs=[chatter_keywords, chatter_timeframe],
997
+ outputs=[chatter_output]
998
+ )
999
+
1000
+ # Identity Alert Tab
1001
+ with gr.TabItem("👤 IDENTITY ALERT"):
1002
+ gr.Markdown("**Check for identity exposure and impersonation attempts.**")
1003
+ with gr.Row():
1004
+ with gr.Column():
1005
+ identity_name = gr.Textbox(
1006
+ label="Full Name",
1007
+ placeholder="John Smith",
1008
+ elem_classes=["input-field"]
1009
+ )
1010
+ identity_extras = gr.Textbox(
1011
+ label="Additional Identifiers (optional)",
1012
+ placeholder="email@company.com, @twitter_handle",
1013
+ elem_classes=["input-field"]
1014
+ )
1015
+ identity_btn = gr.Button("▶ CHECK IDENTITY", variant="primary")
1016
+ with gr.Column():
1017
+ identity_output = gr.JSON(label="Alert Results", elem_classes=["json-output"])
1018
+
1019
+ identity_btn.click(
1020
+ fn=identity_alert,
1021
+ inputs=[identity_name, identity_extras],
1022
+ outputs=[identity_output]
1023
+ )
1024
+
1025
+ # Threat Report Tab
1026
+ with gr.TabItem("📊 THREAT REPORT"):
1027
+ gr.Markdown("**Generate comprehensive threat intelligence reports.**")
1028
+ with gr.Row():
1029
+ with gr.Column(scale=1):
1030
+ report_org = gr.Textbox(
1031
+ label="Organization",
1032
+ placeholder="Acme Corporation",
1033
+ elem_classes=["input-field"]
1034
+ )
1035
+ report_type = gr.Radio(
1036
+ label="Report Type",
1037
+ choices=["executive", "technical", "incident"],
1038
+ value="executive"
1039
+ )
1040
+ report_btn = gr.Button("▶ GENERATE REPORT", variant="primary")
1041
+ with gr.Column(scale=2):
1042
+ report_output = gr.Markdown(label="Threat Report")
1043
+
1044
+ report_btn.click(
1045
+ fn=generate_threat_report,
1046
+ inputs=[report_org, report_type],
1047
+ outputs=[report_output]
1048
+ )
1049
+
1050
+ # Footer
1051
+ gr.HTML("""
1052
+ <div class="footer-bar">
1053
+ <div>
1054
+ <span style="margin-right: 24px;">📊 DARK WEB ACTIVITY ANALYSIS</span>
1055
+ <span>LAST 24H: <span class="footer-stat">1,247 ALERTS</span></span>
1056
+ </div>
1057
+ <div>
1058
+ <span>TOP THREAT: <span class="footer-threat">CREDENTIAL LEAKS</span></span>
1059
+ </div>
1060
+ </div>
1061
+ """)
1062
+
1063
+ # MCP Integration info
1064
+ gr.HTML("""
1065
+ <div class="info-card" style="margin-top: 20px;">
1066
+ <div class="card-header">🔗 MCP INTEGRATION</div>
1067
+ <p style="color: #94a3b8; font-size: 13px; margin-bottom: 12px;">
1068
+ Connect this Space to Claude, Cursor, or any MCP client:
1069
+ </p>
1070
+ <pre style="background: #000; padding: 16px; border-radius: 6px; font-family: 'JetBrains Mono', monospace; font-size: 12px; color: #00ffd5; overflow-x: auto;">
1071
+ {
1072
+ "mcpServers": {
1073
+ "shadowwatch": {
1074
+ "url": "https://crypticallyrequie-shadowwatch.hf.space/gradio_api/mcp/sse"
1075
+ }
1076
+ }
1077
+ }</pre>
1078
+ <p style="color: #64748b; font-size: 11px; margin-top: 12px;">
1079
+ Built by <span style="color: #00ffd5;">Cogensec</span> | Part of the ARGUS AI Security Platform
1080
+ </p>
1081
+ </div>
1082
+ """)
1083
+
1084
+ # Launch with MCP server enabled
1085
+ if __name__ == "__main__":
1086
+ demo.launch(mcp_server=True)
requirements.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ gradio[mcp]>=5.0.0