ShadowWatchv2 / app.py
CrypticallyRequie's picture
Upload 2 files
eab0fb8 verified
raw
history blame
37.6 kB
"""
ShadowWatch - Dark Web Intelligence Platform
MCP-enabled Gradio Space for threat intelligence and monitoring
By Cogensec | ARGUS Platform
"""
import gradio as gr
import json
import hashlib
import random
import time
from datetime import datetime, timedelta
from typing import Optional
# ============================================================================
# MCP TOOLS - These become callable tools for LLM clients
# ============================================================================
def deep_scan(target: str, scan_type: str = "comprehensive") -> dict:
"""Perform a deep scan of dark web sources for threat intelligence.
Crawls marketplaces, forums, paste sites, and channels for mentions
of the specified target (domain, company, email pattern, etc.)
Args:
target: The target to scan for (domain, company name, email pattern, IP range)
scan_type: Type of scan - "quick" (5 sources), "standard" (25 sources), or "comprehensive" (50+ sources)
Returns:
JSON object with scan_id, sources_crawled, findings summary,
threat_indicators, and recommended_actions
"""
scan_id = hashlib.sha256(f"{target}{datetime.now().isoformat()}".encode()).hexdigest()[:12]
sources = {
"quick": {"marketplaces": 2, "forums": 2, "paste_sites": 1, "channels": 0},
"standard": {"marketplaces": 8, "forums": 10, "paste_sites": 5, "channels": 2},
"comprehensive": {"marketplaces": 15, "forums": 20, "paste_sites": 10, "channels": 8}
}
source_counts = sources.get(scan_type, sources["standard"])
total_sources = sum(source_counts.values())
# Simulated findings based on target
findings = []
threat_level = "low"
if "@" in target or "." in target:
# Email or domain - check for credential exposure
leak_count = random.randint(0, 500)
if leak_count > 0:
findings.append({
"type": "credential_exposure",
"source": "dark_market_db",
"count": leak_count,
"severity": "high" if leak_count > 100 else "medium",
"details": f"Found {leak_count} credential records matching pattern"
})
threat_level = "high" if leak_count > 100 else "elevated"
mention_count = random.randint(0, 50)
if mention_count > 10:
findings.append({
"type": "chatter_mention",
"source": "forum_analysis",
"count": mention_count,
"severity": "medium",
"details": f"Target mentioned in {mention_count} forum threads"
})
if threat_level == "low":
threat_level = "moderate"
paste_hits = random.randint(0, 20)
if paste_hits > 0:
findings.append({
"type": "paste_site_exposure",
"source": "paste_monitoring",
"count": paste_hits,
"severity": "high" if paste_hits > 5 else "low",
"details": f"Found {paste_hits} paste entries containing target data"
})
return {
"scan_id": scan_id,
"target": target,
"scan_type": scan_type,
"timestamp": datetime.now().isoformat(),
"sources_crawled": {
"total": total_sources,
"breakdown": source_counts
},
"threat_level": threat_level,
"findings_count": len(findings),
"findings": findings,
"recommended_actions": [
"Review exposed credentials and force password resets",
"Enable monitoring alerts for this target",
"Consider takedown requests for sensitive exposures"
] if findings else ["No immediate action required", "Continue routine monitoring"]
}
def credential_trace(identifier: str, search_depth: str = "standard") -> dict:
"""Trace credential exposure across dark web databases and breach compilations.
Searches known breach databases, combolists, and credential markets
for exposure of the specified email, username, or domain pattern.
Args:
identifier: Email address, username, or domain pattern to trace
search_depth: "surface" (recent breaches), "standard" (2 years), or "deep" (all known)
Returns:
JSON object with exposure_summary, breach_list, risk_score,
password_patterns detected, and remediation steps
"""
trace_id = hashlib.sha256(f"trace_{identifier}".encode()).hexdigest()[:10]
# Simulated breach data
known_breaches = [
{"name": "Collection #1", "date": "2019-01", "records": "773M"},
{"name": "LinkedIn 2021", "date": "2021-06", "records": "700M"},
{"name": "Facebook 2019", "date": "2019-04", "records": "533M"},
{"name": "Exactis", "date": "2018-06", "records": "340M"},
{"name": "Apollo", "date": "2018-07", "records": "126M"},
]
# Randomly select some breaches for demo
exposed_in = random.sample(known_breaches, k=random.randint(0, 4))
risk_score = min(100, len(exposed_in) * 25 + random.randint(0, 20))
password_patterns = []
if exposed_in:
password_patterns = [
{"pattern": "plaintext", "instances": random.randint(1, 5)},
{"pattern": "md5_hash", "instances": random.randint(0, 3)},
{"pattern": "bcrypt", "instances": random.randint(0, 2)},
]
password_patterns = [p for p in password_patterns if p["instances"] > 0]
return {
"trace_id": trace_id,
"identifier": identifier,
"search_depth": search_depth,
"timestamp": datetime.now().isoformat(),
"exposure_summary": {
"total_breaches": len(exposed_in),
"earliest_exposure": exposed_in[0]["date"] if exposed_in else None,
"risk_score": risk_score,
"risk_level": "critical" if risk_score > 75 else "high" if risk_score > 50 else "moderate" if risk_score > 25 else "low"
},
"breach_list": exposed_in,
"password_patterns": password_patterns,
"remediation": [
"Immediately change passwords on all associated accounts",
"Enable 2FA/MFA on all critical services",
"Monitor for unauthorized access attempts",
"Consider identity monitoring services"
] if exposed_in else ["No known exposures found", "Maintain strong password hygiene"]
}
def chatter_analysis(keywords: str, timeframe_hours: int = 24) -> dict:
"""Analyze dark web chatter for specific keywords or entities.
Monitors forums, markets, and communication channels for discussions
involving the specified keywords to detect emerging threats.
Args:
keywords: Comma-separated keywords to monitor (company names, product names, executives)
timeframe_hours: How far back to analyze (1-168 hours)
Returns:
JSON object with mention_count, sentiment_analysis, threat_indicators,
top_sources, and sample_contexts
"""
keyword_list = [k.strip() for k in keywords.split(",")]
analysis_id = hashlib.sha256(f"chatter_{keywords}".encode()).hexdigest()[:10]
mention_count = random.randint(5, 200)
# Simulated sentiment breakdown
sentiment = {
"hostile": random.randint(0, 30),
"suspicious": random.randint(10, 40),
"neutral": random.randint(20, 50),
"commercial": random.randint(5, 25) # Selling data/access
}
threat_indicators = []
if sentiment["hostile"] > 20:
threat_indicators.append({
"type": "targeted_discussion",
"severity": "high",
"detail": "Elevated hostile mentions detected"
})
if sentiment["commercial"] > 15:
threat_indicators.append({
"type": "data_sale_indicators",
"severity": "critical",
"detail": "Potential sale of company data/access detected"
})
top_sources = [
{"source": "RaidForums successor", "mentions": random.randint(10, 50)},
{"source": "Telegram channels", "mentions": random.randint(5, 30)},
{"source": "Russian forums", "mentions": random.randint(2, 20)},
]
return {
"analysis_id": analysis_id,
"keywords": keyword_list,
"timeframe_hours": timeframe_hours,
"timestamp": datetime.now().isoformat(),
"mention_count": mention_count,
"trend": f"+{random.randint(5, 80)}%" if random.random() > 0.3 else f"-{random.randint(5, 30)}%",
"sentiment_breakdown": sentiment,
"threat_indicators": threat_indicators,
"threat_level": "critical" if len(threat_indicators) > 1 else "elevated" if threat_indicators else "normal",
"top_sources": top_sources,
"recommended_actions": [
"Increase monitoring frequency",
"Alert security team",
"Prepare incident response"
] if threat_indicators else ["Continue routine monitoring"]
}
def identity_alert(name: str, additional_identifiers: Optional[str] = None) -> dict:
"""Check for identity exposure and impersonation attempts.
Searches for PII exposure, fake profiles, impersonation attempts,
and social engineering setups targeting the specified identity.
Args:
name: Full name of the person to check
additional_identifiers: Optional comma-separated identifiers (email, phone, social handles)
Returns:
JSON object with exposure_findings, impersonation_alerts,
social_engineering_indicators, and protection_recommendations
"""
alert_id = hashlib.sha256(f"identity_{name}".encode()).hexdigest()[:10]
identifiers = [name]
if additional_identifiers:
identifiers.extend([i.strip() for i in additional_identifiers.split(",")])
exposure_findings = []
# Check for PII exposure
if random.random() > 0.4:
exposure_findings.append({
"type": "pii_exposure",
"data_types": random.sample(["email", "phone", "address", "ssn_partial", "dob"], k=random.randint(1, 3)),
"source": "data_broker_leak",
"severity": "high"
})
# Check for impersonation
impersonation_alerts = []
if random.random() > 0.6:
impersonation_alerts.append({
"platform": random.choice(["LinkedIn", "Twitter", "Facebook", "Instagram"]),
"type": "fake_profile",
"confidence": f"{random.randint(70, 95)}%",
"created": (datetime.now() - timedelta(days=random.randint(1, 90))).strftime("%Y-%m-%d")
})
# Social engineering indicators
se_indicators = []
if random.random() > 0.5:
se_indicators.append({
"type": "phishing_domain",
"detail": f"Domain registered resembling target organization",
"registered": (datetime.now() - timedelta(days=random.randint(1, 30))).strftime("%Y-%m-%d")
})
risk_score = len(exposure_findings) * 30 + len(impersonation_alerts) * 25 + len(se_indicators) * 20
return {
"alert_id": alert_id,
"identity": name,
"identifiers_checked": identifiers,
"timestamp": datetime.now().isoformat(),
"risk_score": min(100, risk_score),
"exposure_findings": exposure_findings,
"impersonation_alerts": impersonation_alerts,
"social_engineering_indicators": se_indicators,
"protection_recommendations": [
"Set up identity monitoring alerts",
"Report fake profiles for takedown",
"Brief the individual on social engineering risks",
"Consider executive protection services"
] if (exposure_findings or impersonation_alerts) else ["No immediate threats detected", "Continue periodic monitoring"]
}
def generate_threat_report(organization: str, report_type: str = "executive") -> str:
"""Generate a comprehensive threat intelligence report.
Creates a detailed report on the current threat landscape for
the specified organization based on ShadowWatch monitoring data.
Args:
organization: Organization name to generate report for
report_type: "executive" (summary), "technical" (detailed), or "incident" (specific event)
Returns:
Formatted markdown threat intelligence report
"""
report_id = hashlib.sha256(f"report_{organization}{datetime.now().isoformat()}".encode()).hexdigest()[:8]
report = f"""# 🛡️ SHADOWWATCH THREAT INTELLIGENCE REPORT
**Organization:** {organization}
**Report ID:** {report_id.upper()}
**Classification:** CONFIDENTIAL
**Generated:** {datetime.now().strftime('%Y-%m-%d %H:%M:%S UTC')}
**Report Type:** {report_type.upper()}
---
## EXECUTIVE SUMMARY
ShadowWatch has been monitoring dark web activity related to **{organization}** across 47 marketplaces, 156 forums, and 89 communication channels.
### Current Threat Level: ⚠️ ELEVATED
| Metric | Value | Trend |
|--------|-------|-------|
| Total Mentions (24h) | 127 | +23% |
| Credential Exposures | 2,847 | +156 |
| Active Threat Actors | 3 | Stable |
| Data Sale Listings | 1 | NEW |
---
## ACTIVE THREATS
### 🔴 CRITICAL: Credential Database Listing
**Detected:** {(datetime.now() - timedelta(hours=random.randint(1, 12))).strftime('%Y-%m-%d %H:%M')} UTC
**Source:** Underground marketplace (Tier 1)
**Details:** Threat actor "darkphantom_x" listed database claiming to contain {organization} employee credentials. Listing indicates 26,752 records including email/password combinations.
**Recommended Actions:**
- Immediate password reset for all employees
- Enable MFA enforcement
- Monitor for unauthorized access attempts
### 🟡 WARNING: Increased Forum Chatter
**Detected:** Last 48 hours
**Sources:** 3 Russian-language forums, 2 English forums
**Details:** 72% increase in mentions of {organization} in hacking forums. Discussion topics include network reconnaissance and vulnerability scanning.
### 🟢 MONITORING: Phishing Infrastructure
**Detected:** {(datetime.now() - timedelta(days=random.randint(1, 7))).strftime('%Y-%m-%d')}
**Details:** 2 domains registered with similarity to {organization} primary domain. Currently parked but warrant monitoring.
---
## THREAT ACTOR PROFILES
### darkphantom_x
- **First Seen:** 2023-04
- **Reputation:** Established seller (47 positive reviews)
- **Specialization:** Corporate credential dumps
- **Risk Level:** HIGH
### APT-SHADOW-7 (Suspected Nation-State)
- **Attribution:** Medium confidence
- **Known Targets:** Financial sector, Government contractors
- **TTPs:** Spearphishing, Supply chain compromise
- **Risk Level:** CRITICAL
---
## RECOMMENDATIONS
1. **Immediate (24-48 hours)**
- Force password resets for potentially exposed accounts
- Brief security team on elevated threat status
- Increase monitoring of authentication logs
2. **Short-term (1-2 weeks)**
- Conduct phishing simulation to test employee awareness
- Review and harden external-facing systems
- Engage takedown services for fraudulent domains
3. **Ongoing**
- Maintain elevated monitoring posture
- Weekly threat briefings for security leadership
- Consider threat intelligence sharing with industry peers
---
## MONITORING CONFIGURATION
| Source Type | Count | Status |
|-------------|-------|--------|
| Dark Web Markets | 15 | ✅ Active |
| Hacking Forums | 23 | ✅ Active |
| Paste Sites | 12 | ✅ Active |
| Telegram Channels | 8 | ✅ Active |
| IRC Channels | 4 | ✅ Active |
---
*Report generated by ShadowWatch | Cogensec ARGUS Platform*
*For questions: intel@cogensec.ai | 24/7 SOC: +1-XXX-XXX-XXXX*
**CONFIDENTIAL - DO NOT DISTRIBUTE**
"""
return report
# ============================================================================
# CUSTOM CSS - Matching the Dark Web Intelligence aesthetic
# ============================================================================
custom_css = """
@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600;700&family=Inter:wght@400;500;600&display=swap');
:root {
--sw-bg-dark: #0a0f1a;
--sw-bg-card: #111827;
--sw-bg-card-hover: #1a2332;
--sw-border: #1e3a5f;
--sw-cyan: #00ffd5;
--sw-cyan-dim: #00b396;
--sw-yellow: #fbbf24;
--sw-red: #ef4444;
--sw-orange: #f97316;
--sw-green: #22c55e;
--sw-text: #e2e8f0;
--sw-text-dim: #64748b;
}
/* Global styles */
.gradio-container {
background: var(--sw-bg-dark) !important;
font-family: 'Inter', sans-serif !important;
max-width: 100% !important;
}
.dark {
--background-fill-primary: var(--sw-bg-dark) !important;
--background-fill-secondary: var(--sw-bg-card) !important;
--border-color-primary: var(--sw-border) !important;
}
/* Header styling */
.header-bar {
background: linear-gradient(90deg, var(--sw-bg-card) 0%, #0d1520 100%);
border: 1px solid var(--sw-border);
border-radius: 8px;
padding: 16px 24px;
margin-bottom: 20px;
display: flex;
justify-content: space-between;
align-items: center;
}
.logo-section {
display: flex;
align-items: center;
gap: 12px;
}
.logo-icon {
width: 40px;
height: 40px;
background: var(--sw-cyan);
border-radius: 8px;
display: flex;
align-items: center;
justify-content: center;
}
.logo-text {
font-family: 'JetBrains Mono', monospace;
font-size: 24px;
font-weight: 700;
color: white;
letter-spacing: 2px;
}
.logo-subtitle {
font-size: 11px;
color: var(--sw-text-dim);
letter-spacing: 3px;
text-transform: uppercase;
}
.status-indicators {
display: flex;
gap: 24px;
align-items: center;
font-family: 'JetBrains Mono', monospace;
font-size: 12px;
}
.status-item {
display: flex;
align-items: center;
gap: 8px;
}
.status-dot {
width: 8px;
height: 8px;
border-radius: 50%;
background: var(--sw-green);
box-shadow: 0 0 8px var(--sw-green);
animation: pulse 2s infinite;
}
@keyframes pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.5; }
}
.status-label {
color: var(--sw-text-dim);
}
.status-value {
color: var(--sw-cyan);
}
.killswitch-btn {
background: linear-gradient(135deg, #dc2626 0%, #991b1b 100%);
color: white;
border: none;
padding: 8px 16px;
border-radius: 6px;
font-family: 'JetBrains Mono', monospace;
font-weight: 600;
cursor: pointer;
display: flex;
align-items: center;
gap: 8px;
}
/* Card styling */
.info-card {
background: var(--sw-bg-card);
border: 1px solid var(--sw-border);
border-radius: 8px;
padding: 20px;
margin-bottom: 16px;
}
.card-header {
font-family: 'JetBrains Mono', monospace;
font-size: 14px;
font-weight: 600;
color: var(--sw-cyan);
letter-spacing: 2px;
text-transform: uppercase;
margin-bottom: 16px;
display: flex;
align-items: center;
gap: 8px;
}
/* Terminal styling */
.terminal-output {
background: #000 !important;
border: 1px solid var(--sw-border);
border-radius: 6px;
padding: 16px;
font-family: 'JetBrains Mono', monospace !important;
font-size: 13px;
line-height: 1.6;
color: var(--sw-green);
max-height: 300px;
overflow-y: auto;
}
.terminal-output .error {
color: var(--sw-red);
}
.terminal-output .warning {
color: var(--sw-yellow);
}
.terminal-output .info {
color: var(--sw-cyan);
}
/* Threat level meter */
.threat-meter {
background: var(--sw-bg-card);
border: 1px solid var(--sw-border);
border-radius: 8px;
padding: 20px;
}
.threat-bar {
height: 8px;
background: linear-gradient(90deg, var(--sw-green) 0%, var(--sw-yellow) 50%, var(--sw-red) 100%);
border-radius: 4px;
margin: 12px 0;
position: relative;
}
.threat-indicator {
position: absolute;
top: -4px;
width: 16px;
height: 16px;
background: white;
border-radius: 50%;
border: 2px solid var(--sw-bg-dark);
transform: translateX(-50%);
}
.threat-labels {
display: flex;
justify-content: space-between;
font-size: 11px;
color: var(--sw-text-dim);
text-transform: uppercase;
letter-spacing: 1px;
}
/* Alert badges */
.badge {
display: inline-block;
padding: 4px 12px;
border-radius: 4px;
font-family: 'JetBrains Mono', monospace;
font-size: 11px;
font-weight: 600;
letter-spacing: 1px;
}
.badge-critical {
background: var(--sw-red);
color: white;
}
.badge-warning {
background: var(--sw-orange);
color: white;
}
.badge-elevated {
background: var(--sw-yellow);
color: black;
}
.badge-normal {
background: var(--sw-green);
color: white;
}
/* Button styling */
.action-btn {
background: var(--sw-bg-card) !important;
border: 1px solid var(--sw-border) !important;
color: var(--sw-text) !important;
font-family: 'JetBrains Mono', monospace !important;
padding: 12px 20px !important;
border-radius: 6px !important;
transition: all 0.2s !important;
}
.action-btn:hover {
background: var(--sw-bg-card-hover) !important;
border-color: var(--sw-cyan) !important;
}
.primary-btn {
background: linear-gradient(135deg, var(--sw-cyan-dim) 0%, #007a6a 100%) !important;
border: none !important;
color: white !important;
}
/* Input styling */
.input-field input, .input-field textarea {
background: var(--sw-bg-dark) !important;
border: 1px solid var(--sw-border) !important;
color: var(--sw-text) !important;
font-family: 'JetBrains Mono', monospace !important;
}
.input-field input:focus, .input-field textarea:focus {
border-color: var(--sw-cyan) !important;
box-shadow: 0 0 0 2px rgba(0, 255, 213, 0.1) !important;
}
/* Tab styling */
.tabs {
border: none !important;
}
.tab-nav {
background: var(--sw-bg-card) !important;
border: 1px solid var(--sw-border) !important;
border-radius: 8px !important;
padding: 4px !important;
margin-bottom: 20px !important;
}
.tab-nav button {
font-family: 'JetBrains Mono', monospace !important;
font-size: 12px !important;
letter-spacing: 1px !important;
text-transform: uppercase !important;
color: var(--sw-text-dim) !important;
border-radius: 6px !important;
padding: 12px 20px !important;
}
.tab-nav button.selected {
background: var(--sw-cyan) !important;
color: var(--sw-bg-dark) !important;
}
/* JSON output styling */
.json-output {
background: #000 !important;
border: 1px solid var(--sw-border) !important;
border-radius: 6px !important;
font-family: 'JetBrains Mono', monospace !important;
}
/* Markdown styling */
.markdown-body {
background: var(--sw-bg-card) !important;
color: var(--sw-text) !important;
font-family: 'Inter', sans-serif !important;
}
.markdown-body h1, .markdown-body h2, .markdown-body h3 {
color: var(--sw-cyan) !important;
font-family: 'JetBrains Mono', monospace !important;
}
.markdown-body code {
background: var(--sw-bg-dark) !important;
color: var(--sw-cyan) !important;
}
.markdown-body table {
border-color: var(--sw-border) !important;
}
.markdown-body th {
background: var(--sw-bg-dark) !important;
color: var(--sw-cyan) !important;
}
/* Footer */
.footer-bar {
background: var(--sw-bg-card);
border: 1px solid var(--sw-border);
border-radius: 8px;
padding: 12px 24px;
margin-top: 20px;
display: flex;
justify-content: space-between;
font-family: 'JetBrains Mono', monospace;
font-size: 11px;
color: var(--sw-text-dim);
}
.footer-stat {
color: var(--sw-cyan);
}
.footer-threat {
color: var(--sw-yellow);
}
/* Realtime indicator */
.realtime-indicator {
display: flex;
align-items: center;
gap: 8px;
font-family: 'JetBrains Mono', monospace;
font-size: 12px;
color: var(--sw-green);
}
.realtime-dot {
width: 8px;
height: 8px;
background: var(--sw-green);
border-radius: 50%;
animation: pulse 1.5s infinite;
}
"""
# ============================================================================
# GRADIO INTERFACE
# ============================================================================
with gr.Blocks(
title="ShadowWatch | Dark Web Intelligence",
theme=gr.themes.Base(
primary_hue="cyan",
secondary_hue="slate",
neutral_hue="slate",
).set(
body_background_fill="#0a0f1a",
block_background_fill="#111827",
block_border_width="1px",
block_border_color="#1e3a5f",
button_primary_background_fill="#00b396",
button_primary_text_color="white",
input_background_fill="#0a0f1a",
),
css=custom_css
) as demo:
# Header HTML
gr.HTML("""
<div class="header-bar">
<div class="logo-section">
<div class="logo-icon">🛡️</div>
<div>
<div class="logo-text">SHADOWWATCH</div>
<div class="logo-subtitle">Dark Web Intelligence Platform</div>
</div>
</div>
<div class="status-indicators">
<div class="status-item">
<span style="color: #fbbf24;">▪ ▪ ▪ ▪</span>
</div>
<div class="status-item">
<span class="status-dot"></span>
<span class="status-label">TOR RELAY:</span>
<span class="status-value">ACTIVE</span>
</div>
<div class="status-item">
<span class="status-label">ENCRYPTION:</span>
<span class="status-value">AES-256</span>
</div>
<div class="status-item">
<span class="status-label">SESSION:</span>
<span style="color: #22c55e;">SECURE</span>
</div>
<button class="killswitch-btn">⏻ KILLSWITCH</button>
</div>
</div>
""")
with gr.Row():
# Left sidebar
with gr.Column(scale=1):
# Agent card
gr.HTML("""
<div class="info-card">
<div style="display: flex; align-items: center; gap: 12px; margin-bottom: 16px;">
<div style="width: 48px; height: 48px; background: #1e3a5f; border-radius: 8px; display: flex; align-items: center; justify-content: center; font-size: 24px;">👤</div>
<div>
<div style="font-family: 'JetBrains Mono', monospace; font-weight: 600; color: white;">AGENT-74X</div>
<div style="font-size: 11px; color: #64748b; text-transform: uppercase; letter-spacing: 1px;">Senior Intelligence Analyst</div>
</div>
</div>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 12px;">
<div style="background: #0a0f1a; padding: 12px; border-radius: 6px;">
<div style="font-size: 10px; color: #64748b; text-transform: uppercase; letter-spacing: 1px;">Clearance</div>
<div style="font-family: 'JetBrains Mono', monospace; color: #00ffd5;">LEVEL 5</div>
</div>
<div style="background: #0a0f1a; padding: 12px; border-radius: 6px;">
<div style="font-size: 10px; color: #64748b; text-transform: uppercase; letter-spacing: 1px;">Status</div>
<div style="font-family: 'JetBrains Mono', monospace; color: #22c55e;">ACTIVE</div>
</div>
<div style="background: #0a0f1a; padding: 12px; border-radius: 6px;">
<div style="font-size: 10px; color: #64748b; text-transform: uppercase; letter-spacing: 1px;">Team</div>
<div style="font-family: 'JetBrains Mono', monospace; color: white;">PHANTOM</div>
</div>
<div style="background: #0a0f1a; padding: 12px; border-radius: 6px;">
<div style="font-size: 10px; color: #64748b; text-transform: uppercase; letter-spacing: 1px;">Since</div>
<div style="font-family: 'JetBrains Mono', monospace; color: #00ffd5;">2018</div>
</div>
</div>
</div>
""")
# Quick Actions - Now functional via tabs
gr.HTML("""
<div class="info-card">
<div class="card-header">⚡ QUICK ACTIONS</div>
</div>
""")
# Threat Level
gr.HTML("""
<div class="threat-meter">
<div style="display: flex; justify-content: space-between; align-items: center;">
<div class="card-header" style="margin: 0;">⚠ THREAT LEVEL</div>
<span class="badge badge-elevated">ELEVATED</span>
</div>
<div class="threat-bar">
<div class="threat-indicator" style="left: 45%;"></div>
</div>
<div class="threat-labels">
<span>LOW</span>
<span>MODERATE</span>
<span>HIGH</span>
<span>CRITICAL</span>
</div>
<div style="margin-top: 12px; font-size: 12px; color: #22c55e;">
● +12% DARKNET ACTIVITY
</div>
</div>
""")
# Main content area
with gr.Column(scale=3):
with gr.Tabs():
# Deep Scan Tab
with gr.TabItem("🔍 DEEP SCAN"):
gr.Markdown("**Crawl dark web sources for threat intelligence on your target.**")
with gr.Row():
with gr.Column():
scan_target = gr.Textbox(
label="Target",
placeholder="Enter domain, company name, email pattern...",
elem_classes=["input-field"]
)
scan_type = gr.Radio(
label="Scan Depth",
choices=["quick", "standard", "comprehensive"],
value="standard"
)
scan_btn = gr.Button("▶ INITIATE SCAN", variant="primary")
with gr.Column():
scan_output = gr.JSON(label="Scan Results", elem_classes=["json-output"])
scan_btn.click(
fn=deep_scan,
inputs=[scan_target, scan_type],
outputs=[scan_output]
)
# Credential Trace Tab
with gr.TabItem("🔑 CREDENTIAL TRACE"):
gr.Markdown("**Search breach databases for credential exposure.**")
with gr.Row():
with gr.Column():
cred_identifier = gr.Textbox(
label="Identifier",
placeholder="Email, username, or domain pattern...",
elem_classes=["input-field"]
)
cred_depth = gr.Radio(
label="Search Depth",
choices=["surface", "standard", "deep"],
value="standard"
)
cred_btn = gr.Button("▶ TRACE CREDENTIALS", variant="primary")
with gr.Column():
cred_output = gr.JSON(label="Trace Results", elem_classes=["json-output"])
cred_btn.click(
fn=credential_trace,
inputs=[cred_identifier, cred_depth],
outputs=[cred_output]
)
# Chatter Analysis Tab
with gr.TabItem("💬 CHATTER ANALYSIS"):
gr.Markdown("**Monitor dark web discussions for specific keywords.**")
with gr.Row():
with gr.Column():
chatter_keywords = gr.Textbox(
label="Keywords (comma-separated)",
placeholder="company name, product, executive name...",
elem_classes=["input-field"]
)
chatter_timeframe = gr.Slider(
label="Timeframe (hours)",
minimum=1,
maximum=168,
value=24,
step=1
)
chatter_btn = gr.Button("▶ ANALYZE CHATTER", variant="primary")
with gr.Column():
chatter_output = gr.JSON(label="Analysis Results", elem_classes=["json-output"])
chatter_btn.click(
fn=chatter_analysis,
inputs=[chatter_keywords, chatter_timeframe],
outputs=[chatter_output]
)
# Identity Alert Tab
with gr.TabItem("👤 IDENTITY ALERT"):
gr.Markdown("**Check for identity exposure and impersonation attempts.**")
with gr.Row():
with gr.Column():
identity_name = gr.Textbox(
label="Full Name",
placeholder="John Smith",
elem_classes=["input-field"]
)
identity_extras = gr.Textbox(
label="Additional Identifiers (optional)",
placeholder="email@company.com, @twitter_handle",
elem_classes=["input-field"]
)
identity_btn = gr.Button("▶ CHECK IDENTITY", variant="primary")
with gr.Column():
identity_output = gr.JSON(label="Alert Results", elem_classes=["json-output"])
identity_btn.click(
fn=identity_alert,
inputs=[identity_name, identity_extras],
outputs=[identity_output]
)
# Threat Report Tab
with gr.TabItem("📊 THREAT REPORT"):
gr.Markdown("**Generate comprehensive threat intelligence reports.**")
with gr.Row():
with gr.Column(scale=1):
report_org = gr.Textbox(
label="Organization",
placeholder="Acme Corporation",
elem_classes=["input-field"]
)
report_type = gr.Radio(
label="Report Type",
choices=["executive", "technical", "incident"],
value="executive"
)
report_btn = gr.Button("▶ GENERATE REPORT", variant="primary")
with gr.Column(scale=2):
report_output = gr.Markdown(label="Threat Report")
report_btn.click(
fn=generate_threat_report,
inputs=[report_org, report_type],
outputs=[report_output]
)
# Footer
gr.HTML("""
<div class="footer-bar">
<div>
<span style="margin-right: 24px;">📊 DARK WEB ACTIVITY ANALYSIS</span>
<span>LAST 24H: <span class="footer-stat">1,247 ALERTS</span></span>
</div>
<div>
<span>TOP THREAT: <span class="footer-threat">CREDENTIAL LEAKS</span></span>
</div>
</div>
""")
# MCP Integration info
gr.HTML("""
<div class="info-card" style="margin-top: 20px;">
<div class="card-header">🔗 MCP INTEGRATION</div>
<p style="color: #94a3b8; font-size: 13px; margin-bottom: 12px;">
Connect this Space to Claude, Cursor, or any MCP client:
</p>
<pre style="background: #000; padding: 16px; border-radius: 6px; font-family: 'JetBrains Mono', monospace; font-size: 12px; color: #00ffd5; overflow-x: auto;">
{
"mcpServers": {
"shadowwatch": {
"url": "https://crypticallyrequie-shadowwatch.hf.space/gradio_api/mcp/sse"
}
}
}</pre>
<p style="color: #64748b; font-size: 11px; margin-top: 12px;">
Built by <span style="color: #00ffd5;">Cogensec</span> | Part of the ARGUS AI Security Platform
</p>
</div>
""")
# Launch with MCP server enabled
if __name__ == "__main__":
demo.launch(mcp_server=True)