import os import re import socket import ssl import time from datetime import datetime, timezone from urllib.error import URLError from urllib.request import Request, urlopen import gradio as gr from huggingface_hub import InferenceClient INFERENCE_MODEL_ID = os.getenv( "INFERENCE_MODEL_ID", "empero-ai/Qwythos-9B-Claude-Mythos-5-1M", ) DEFAULT_SYSTEM = ( "You are Mythos, an elite cybersecurity AI assistant. " "Output ONLY the final answer in markdown. " "NEVER output reasoning, planning, or phrases like 'The user wants' or 'I need to'. " "If scan results are provided, summarize vulnerabilities with severity and fixes. " "Match the user's language. Be precise and actionable." ) QUICK_ACTIONS = { "🔍 OWASP Scan": "Run full OWASP security scan on yexa.pro and list all findings with severity.", "🌐 API Security": "Scan yexa.pro API endpoints and list security risks with mitigations.", "🧪 JWT Audit": "Audit JWT and authentication security for yexa.pro.", "📦 Headers Scan": "Check security headers and TLS configuration for yexa.pro.", "📄 Full Report": "Generate executive security report for yexa.pro based on live scan.", "🛡️ RBAC Review": "Review access control and exposure surface for yexa.pro.", } DOMAIN_RE = re.compile( r"(?:https?://)?(?:www\.)?" r"([a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?" r"(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+)", re.IGNORECASE, ) SCAN_TRIGGER_RE = re.compile( r"\b(test|scan|check|audit|pentest|فحص|اختبر|اختبار|افحص|تحقق|امسح)\b", re.IGNORECASE, ) REASONING_PREFIXES = ( "the user wants", "i need to", "i should", "i will", "i'll", "let me", "this is a", "the best way", "i can use", "i'm going to", "okay,", "since i", ) CUSTOM_CSS = """ @import url('https://fonts.googleapis.com/css2?family=IBM+Plex+Sans+Arabic:wght@400;500;600;700&family=JetBrains+Mono:wght@400;600&family=Inter:wght@400;500;600;700&display=swap'); :root { --bg: #05080d; --panel: #0b1220; --panel-2: #101a2b; --line: #1f3b34; --green: #10b981; --green-soft: #34d399; --text: #ecfdf5; --muted: #94a3b8; } html, body { overflow-x: hidden !important; width: 100% !important; } .gradio-container { max-width: 100% !important; width: 100% !important; margin: 0 auto !important; padding: 0.5rem 1rem 1rem !important; font-family: 'IBM Plex Sans Arabic', 'Inter', sans-serif !important; background: radial-gradient(circle at 20% 0%, #0a1a14 0%, var(--bg) 45%) !important; } .gradio-container .contain { max-width: 100% !important; } .gradio-container .block, .gradio-container .form, .gradio-container .panel { background: transparent !important; border-color: #1f3b34 !important; } .gradio-container .mythos-chatbot, .gradio-container .mythos-chatbot.block, .gradio-container .mythos-chatbot .block, .gradio-container .mythos-chatbot .wrap { background: #070d14 !important; } .gradio-container .block-label, .gradio-container label span { color: #cbd5e1 !important; } .mythos-topbar { display: flex; justify-content: space-between; align-items: center; background: linear-gradient(90deg, #07130f, #0b1a2f); border: 1px solid var(--line); border-radius: 14px; padding: 0.9rem 1.2rem; margin-bottom: 0.8rem; } .mythos-topbar .brand { display: flex; gap: 0.75rem; align-items: center; } .mythos-logo { width: 42px; height: 42px; border-radius: 10px; background: linear-gradient(135deg, #059669, #22d3ee); display: grid; place-items: center; font-weight: 800; color: #04120d; box-shadow: 0 0 20px rgba(16,185,129,.35); } .mythos-topbar h1 { margin: 0; color: var(--text); font-size: 1.35rem; } .mythos-topbar p { margin: 0; color: var(--muted); font-size: 0.82rem; } .mythos-status { display: flex; gap: 0.5rem; flex-wrap: wrap; justify-content: flex-end; } .status-pill { font-size: 0.72rem; padding: 0.28rem 0.6rem; border-radius: 999px; border: 1px solid var(--line); color: #a7f3d0; background: #0f1f2f; font-family: 'JetBrains Mono', monospace; } .gradio-container .contain > .mythos-shell, .gradio-container .mythos-shell { display: flex !important; flex-direction: row !important; flex-wrap: nowrap !important; align-items: flex-start !important; gap: 0.8rem !important; width: 100% !important; height: auto !important; } .gradio-container .mythos-shell > .column, .gradio-container .mythos-shell > .gap { height: auto !important; min-height: 0 !important; align-self: flex-start !important; } .gradio-container .mythos-shell > .column.mythos-sidebar, .gradio-container .mythos-sidebar { flex: 0 0 240px !important; width: 240px !important; min-width: 240px !important; max-width: 240px !important; } .gradio-container .mythos-shell > .column.mythos-main, .gradio-container .mythos-main { flex: 1 1 auto !important; min-width: 0 !important; width: auto !important; } .mythos-sidebar { background: var(--panel); border: 1px solid var(--line); border-radius: 14px; padding: 0.8rem; align-self: flex-start !important; } .mythos-sidebar .block, .mythos-sidebar .wrap, .mythos-sidebar fieldset { background: #0b1220 !important; border-color: #1f3b34 !important; box-shadow: none !important; } .mythos-sidebar .gr-radio label, .mythos-sidebar .gr-radio .wrap { background: #0d1f1a !important; color: #ecfdf5 !important; border: 1px solid #1f3b34 !important; } .mythos-sidebar .gr-radio input:checked + label, .mythos-sidebar .gr-radio .selected { background: linear-gradient(135deg, #064e3b, #0e7490) !important; border-color: #34d399 !important; color: #ecfdf5 !important; box-shadow: 0 0 12px rgba(16,185,129,.2) !important; } .mythos-sidebar .gr-button, .mythos-sidebar button { background: #0d1f1a !important; border: 1px solid #1f4d3f !important; color: #bbf7d0 !important; } .mythos-divider { height: 1px; background: #1f3b34; margin: 0.75rem 0; } .mythos-main { background: var(--panel); border: 1px solid var(--line); border-radius: 14px; padding: 0.75rem; max-width: 100% !important; height: auto !important; min-height: 0 !important; align-self: flex-start !important; } .chat-panel { width: 100% !important; display: block !important; height: auto !important; } .chat-panel > .gap { display: flex !important; flex-direction: column !important; gap: 0.5rem !important; height: auto !important; } .quick-chips { display: flex !important; flex-wrap: wrap !important; gap: 0.4rem !important; margin: 0.5rem 0 !important; } .quick-chips button { border: 1px solid #1f4d3f !important; background: #0d1f1a !important; color: #bbf7d0 !important; border-radius: 999px !important; font-size: 0.76rem !important; padding: 0.35rem 0.7rem !important; } .quick-chips button:hover { border-color: #34d399 !important; box-shadow: 0 0 12px rgba(16,185,129,.2) !important; } .quick-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0.5rem; margin: 0.6rem 0 0.8rem; } .metric-card { background: var(--panel-2); border: 1px solid var(--line); border-radius: 12px; padding: 0.8rem; } .metric-card .num { font-size: 1.5rem; font-weight: 700; color: var(--green-soft); } .metric-card .lbl { color: var(--muted); font-size: 0.78rem; margin-top: 0.2rem; } .metric-card.critical .num { color: #f87171; } .metric-card.high .num { color: #fb923c; } .metrics-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 0.7rem; margin-bottom: 0.8rem; } .quick-grid button { border: 1px solid #1f4d3f !important; background: #0d1f1a !important; color: #bbf7d0 !important; border-radius: 10px !important; } .quick-grid button:hover { border-color: #34d399 !important; box-shadow: 0 0 16px rgba(16,185,129,.25) !important; } .mythos-chatbot .chatbot-placeholder, .mythos-chatbot .placeholder { color: #6ee7b7 !important; padding: 2rem 1rem !important; text-align: center !important; font-size: 0.95rem !important; } .chat-panel .chatbot, .mythos-chatbot, .mythos-chatbot > .wrap, .mythos-chatbot .wrap, .mythos-chatbot .form, .mythos-chatbot .panel, .mythos-chatbot .message-wrap, .mythos-chatbot .component-wrap, .mythos-chatbot .scroll-hide, .mythos-chatbot .empty, .mythos-chatbot .chatbot-placeholder { background: #070d14 !important; background-color: #070d14 !important; color: #d9f99d !important; } .mythos-chatbot .chatbot-placeholder, .mythos-chatbot .placeholder { color: #6ee7b7 !important; padding: 2rem 1rem !important; text-align: center !important; font-size: 0.95rem !important; } .mythos-chatbot { --body-text-color: #d9f99d !important; --block-background-fill: #070d14 !important; --background-fill-primary: #070d14 !important; --background-fill-secondary: #0f1b2d !important; border: 1px solid #1e3a5f !important; border-radius: 12px !important; height: 420px !important; min-height: 420px !important; max-height: 420px !important; flex: 0 0 420px !important; } .mythos-chatbot > .wrap { height: 420px !important; max-height: 420px !important; } .mythos-chatbot .scroll-hide, .mythos-chatbot .message-wrap { overscroll-behavior: contain !important; } .chat-panel .chatbot { border: 1px solid #1e3a5f !important; border-radius: 12px !important; background: #070d14 !important; } .chat-panel .chatbot .label-wrap, .chat-panel .chatbot > label, .chat-panel .chatbot legend, .chat-panel .chatbot .block-label, .chat-panel .chatbot span[data-testid="block-info"], .mythos-chatbot .label-wrap, .mythos-chatbot .block-label { display: none !important; height: 0 !important; margin: 0 !important; padding: 0 !important; } .chat-panel .chatbot .wrap, .mythos-chatbot .wrap { border: none !important; padding: 0.5rem !important; } .mythos-chatbot .message { margin: 0.5rem 0 !important; padding: 0.75rem 1rem !important; border-radius: 12px !important; max-width: 92% !important; } .mythos-chatbot .message.user, .mythos-chatbot .message.assistant, .mythos-chatbot .message.bot, .chat-panel .chatbot .message-wrap .message.user, .chat-panel .chatbot .message-wrap .message.assistant, .chat-panel .chatbot .message-wrap .message.bot { display: block !important; visibility: visible !important; opacity: 1 !important; position: relative !important; z-index: 2 !important; } .mythos-chatbot .message.user, .chat-panel .chatbot .message-wrap .message.user { background: linear-gradient(135deg, #047857, #0e7490) !important; color: #ecfdf5 !important; border: 1px solid #34d399 !important; margin-left: auto !important; } .mythos-chatbot .message.assistant, .mythos-chatbot .message.bot, .chat-panel .chatbot .message-wrap .message.assistant, .chat-panel .chatbot .message-wrap .message.bot { background: #0f1b2d !important; color: #d9f99d !important; border: 1px solid #1f9d74 !important; margin-right: auto !important; } .mythos-chatbot:has(.message) .placeholder, .mythos-chatbot:has(.message) .chatbot-placeholder, .mythos-chatbot:has(.message) .empty { display: none !important; } .mythos-chatbot .message .md, .mythos-chatbot .message .prose, .mythos-chatbot .message .prose *, .mythos-chatbot .message p, .mythos-chatbot .message li, .mythos-chatbot .message span, .mythos-chatbot .message strong, .mythos-chatbot .message em, .mythos-chatbot .message h1, .mythos-chatbot .message h2, .mythos-chatbot .message h3, .mythos-chatbot .message code, .mythos-chatbot .message pre, .chat-panel .chatbot .message-wrap .message.user .prose, .chat-panel .chatbot .message-wrap .message.user .prose *, .chat-panel .chatbot .message-wrap .message.assistant .prose, .chat-panel .chatbot .message-wrap .message.assistant .prose * { color: inherit !important; background: transparent !important; } .mythos-chatbot .message.user .md, .mythos-chatbot .message.user .prose, .mythos-chatbot .message.user .prose * { color: #ecfdf5 !important; } .mythos-chatbot .message.assistant .md, .mythos-chatbot .message.assistant .prose, .mythos-chatbot .message.assistant .prose * { color: #d9f99d !important; } .mythos-chatbot .message pre, .mythos-chatbot .message code { background: #0a1520 !important; border: 1px solid #1f3b34 !important; color: #86efac !important; } .mythos-chatbot .avatar-container, .chat-panel .chatbot .avatar-container { display: none !important; } .mythos-chatbot .icon-button, .mythos-chatbot .copy-btn { background: #0d1f1a !important; border: 1px solid #1f4d3f !important; color: #bbf7d0 !important; } .chat-input-row { align-items: flex-end !important; gap: 0.6rem !important; margin-top: 0.5rem !important; } .chat-input-row > .block, .chat-input-row > .form, .chat-input-row .wrap { margin: 0 !important; background: transparent !important; border: none !important; box-shadow: none !important; } .chat-input-row textarea { border: 1px solid #1f9d74 !important; background: #0b1522 !important; color: var(--text) !important; border-radius: 12px !important; min-height: 64px !important; } .chat-input-row button { min-height: 64px !important; min-width: 110px !important; border-radius: 12px !important; background: linear-gradient(135deg, #059669, #047857) !important; border: 1px solid #34d399 !important; color: #ecfdf5 !important; font-weight: 600 !important; } .chat-input-row button:hover { box-shadow: 0 0 18px rgba(16,185,129,.35) !important; } .chat-panel textarea { border: 1px solid #1f9d74 !important; background: #0b1522 !important; color: var(--text) !important; border-radius: 12px !important; } .mythos-sidebar .status-box { background: #0a141f !important; border: 1px solid #1f9d74 !important; border-radius: 10px !important; padding: 0.65rem 0.75rem !important; text-align: center !important; font-family: 'JetBrains Mono', monospace !important; font-size: 0.88rem !important; color: #34d399 !important; margin-top: 0.5rem !important; } .mythos-sidebar .status-box p { margin: 0 !important; color: #34d399 !important; } .empty-state { border: 1px dashed #1f9d74; border-radius: 12px; padding: 1rem; color: #a7f3d0; text-align: center; margin-bottom: 0.7rem; background: #0a141f; } footer { display: none !important; } @media (max-width: 980px) { .gradio-container .mythos-shell { flex-direction: column !important; } .gradio-container .mythos-shell > .column.mythos-sidebar, .gradio-container .mythos-sidebar { flex: 1 1 auto !important; width: 100% !important; min-width: 0 !important; max-width: 100% !important; } .metrics-grid { grid-template-columns: repeat(2, 1fr); } .quick-grid { grid-template-columns: 1fr; } } """ THEME = gr.themes.Base( primary_hue=gr.themes.colors.emerald, secondary_hue=gr.themes.colors.cyan, neutral_hue=gr.themes.colors.slate, font=gr.themes.GoogleFont("Inter"), ).set( body_background_fill="#05080d", block_background_fill="#0b1220", block_border_color="#1f3b34", block_label_text_color="#cbd5e1", body_text_color="#ecfdf5", input_background_fill="#0b1522", input_border_color="#1f3b34", button_secondary_background_fill="#0d1f1a", button_secondary_text_color="#bbf7d0", button_primary_background_fill="#059669", button_primary_background_fill_hover="#047857", block_title_text_color="#ecfdf5", body_text_color_subdued="#94a3b8", ) DASHBOARD_HTML = """