ChienChung commited on
Commit
19949cf
·
verified ·
1 Parent(s): 14e5c29

Upload 10 files

Browse files
Files changed (10) hide show
  1. Dockerfile +37 -0
  2. api_client.py +27 -0
  3. app.py +26 -0
  4. cve_validator.py +18 -0
  5. llm_summarizer.py +36 -0
  6. main.py +87 -0
  7. requirements.txt +4 -0
  8. search.py +39 -0
  9. storage.py +38 -0
  10. web_ui.py +274 -0
Dockerfile ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Use Python 3.11 slim image
2
+ FROM python:3.11-slim
3
+
4
+ # Set working directory
5
+ WORKDIR /app
6
+
7
+ # Install system dependencies
8
+ RUN apt-get update && apt-get install -y \
9
+ curl \
10
+ && rm -rf /var/lib/apt/lists/*
11
+
12
+ # Copy requirements first for better caching
13
+ COPY requirements.txt .
14
+
15
+ # Install Python dependencies
16
+ RUN pip install --no-cache-dir -r requirements.txt
17
+
18
+ # Copy application code
19
+ COPY *.py ./
20
+ COPY README.md ./
21
+
22
+ # Create data directory
23
+ RUN mkdir -p data
24
+
25
+ # Create non-root user for security
26
+ RUN useradd -m -u 1000 cveuser && chown -R cveuser:cveuser /app
27
+ USER cveuser
28
+
29
+ # Expose port
30
+ EXPOSE 7860
31
+
32
+ # Health check
33
+ HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
34
+ CMD curl -f http://localhost:7860/ || exit 1
35
+
36
+ # Default command (can be overridden)
37
+ CMD ["python", "web_ui.py"]
api_client.py ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import requests
2
+
3
+ def fetch_cve_simple(cve_id):
4
+ """Fetch CVE data from NIST NVD API"""
5
+ url = f"https://services.nvd.nist.gov/rest/json/cves/2.0?cveId={cve_id}"
6
+
7
+ try:
8
+ response = requests.get(url, timeout=10)
9
+ if response.status_code == 200:
10
+ data = response.json()
11
+ if 'vulnerabilities' in data and data['vulnerabilities']:
12
+ return data['vulnerabilities'][0]
13
+ return None
14
+ except Exception as e:
15
+ print(f"Error: {e}")
16
+ return None
17
+
18
+ # Test
19
+ if __name__ == "__main__":
20
+ cve_data = fetch_cve_simple("CVE-2021-44228")
21
+ if cve_data:
22
+ print(" API test successful")
23
+ cve = cve_data['cve']
24
+ print(f"CVE ID: {cve['id']}")
25
+ print(f"Description: {cve['descriptions'][0]['value'][:100]}...")
26
+ else:
27
+ print(" API test failed")
app.py ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ HuggingFace Spaces deployment file
4
+ This file is specifically for deploying to HuggingFace Spaces
5
+ """
6
+
7
+ import os
8
+ import sys
9
+
10
+ # Add current directory to path
11
+ sys.path.append('.')
12
+
13
+ # Import the main web interface
14
+ from web_ui import interface
15
+
16
+ # Launch the interface
17
+ if __name__ == "__main__":
18
+ interface.launch(
19
+ server_name="0.0.0.0",
20
+ server_port=7860,
21
+ share=False,
22
+ show_error=True,
23
+ # HuggingFace specific settings
24
+ enable_queue=True,
25
+ show_api=False
26
+ )
cve_validator.py ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import re
2
+
3
+ def validate_cve_id(cve_id):
4
+ """Validate CVE ID format"""
5
+ pattern = r'^CVE-\d{4}-\d{4,}$'
6
+ return bool(re.match(pattern, cve_id.upper()))
7
+
8
+ # Test
9
+ if __name__ == "__main__":
10
+ test_cases = [
11
+ "CVE-2021-44228", # Should pass
12
+ "CVE-2020-1234", # Should pass
13
+ "invalid", # Should fail
14
+ ]
15
+
16
+ for cve in test_cases:
17
+ result = validate_cve_id(cve)
18
+ print(f"{cve}: {'✅' if result else '❌'}")
llm_summarizer.py ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import openai
2
+ import os
3
+
4
+ def summarize_cve(cve_data):
5
+ """Generate CVE summary using OpenAI"""
6
+ api_key = os.getenv('OPENAI_API_KEY')
7
+ if not api_key:
8
+ return "OPENAI_API_KEY environment variable required"
9
+
10
+ # Extract basic information
11
+ cve = cve_data['cve']
12
+ description = cve['descriptions'][0]['value']
13
+
14
+ # Create prompt in English
15
+ cve_id = cve['id']
16
+ prompt = f"Please provide a professional security analysis of this CVE vulnerability in English:\n\nCVE ID: {cve_id}\nDescription: {description}\n\nPlease provide:\n1. Vulnerability Summary\n2. Risk Assessment\n3. Recommended Mitigation Actions\n\nUse British English and security industry terminology."
17
+
18
+ try:
19
+ client = openai.OpenAI(api_key=api_key)
20
+ response = client.chat.completions.create(
21
+ model="gpt-4o-mini",
22
+ messages=[{"role": "user", "content": prompt}],
23
+ max_tokens=3000
24
+ )
25
+ return response.choices[0].message.content
26
+ except Exception as e:
27
+ return f"LLM error: {e}"
28
+
29
+ # Test
30
+ if __name__ == "__main__":
31
+ from api_client import fetch_cve_simple
32
+ cve_data = fetch_cve_simple("CVE-2021-44228")
33
+ if cve_data:
34
+ summary = summarize_cve(cve_data)
35
+ print("🤖 AI Summary:")
36
+ print(summary)
main.py ADDED
@@ -0,0 +1,87 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ import sys
3
+ import os
4
+ from cve_validator import validate_cve_id
5
+ from api_client import fetch_cve_simple
6
+ from storage import save_cve_analysis, load_cve_analysis
7
+
8
+ def analyze_cve(cve_id, use_cache=True):
9
+ """Analyze CVE with caching support"""
10
+
11
+ # Check if already analyzed
12
+ if use_cache:
13
+ cached = load_cve_analysis(cve_id)
14
+ if cached:
15
+ print(f" Loading from cache: {cve_id}")
16
+ return cached
17
+
18
+ print(f"🔍 Analyzing {cve_id}...")
19
+
20
+ # Fetch CVE data
21
+ cve_data = fetch_cve_simple(cve_id)
22
+ if not cve_data:
23
+ print(f" Unable to fetch data for {cve_id}")
24
+ return None
25
+
26
+ # Display basic information
27
+ cve = cve_data['cve']
28
+ print(f" {cve['id']}")
29
+ print(f"Published: {cve['published']}")
30
+ print(f"Description: {cve['descriptions'][0]['value'][:200]}...")
31
+
32
+ # Get CVSS score
33
+ if 'metrics' in cve and 'cvssMetricV31' in cve['metrics']:
34
+ cvss = cve['metrics']['cvssMetricV31'][0]['cvssData']
35
+ print(f"CVSS Score: {cvss['baseScore']}")
36
+ print(f"Severity: {cvss['baseSeverity']}")
37
+
38
+ # Try to generate AI summary
39
+ ai_summary = None
40
+ if os.getenv('OPENAI_API_KEY'):
41
+ print("\n Generating AI summary...")
42
+ try:
43
+ from llm_summarizer import summarize_cve
44
+ ai_summary = summarize_cve(cve_data)
45
+ print(ai_summary)
46
+ except Exception as e:
47
+ print(f"AI summary failed: {e}")
48
+ else:
49
+ print("\n OPENAI_API_KEY not set, skipping AI summary")
50
+
51
+ # Save analysis results
52
+ analysis = {
53
+ 'cve_id': cve_id,
54
+ 'cve_data': cve_data,
55
+ 'ai_summary': ai_summary
56
+ }
57
+
58
+ save_cve_analysis(cve_id, cve_data, ai_summary)
59
+
60
+ return analysis
61
+
62
+ def main():
63
+ if len(sys.argv) < 2:
64
+ print("Usage:")
65
+ print(" python main.py CVE-YYYY-NNNN # Analyze CVE")
66
+ print(" python main.py CVE-YYYY-NNNN --force # Force re-analysis")
67
+ sys.exit(1)
68
+
69
+ cve_id = sys.argv[1]
70
+ force = '--force' in sys.argv
71
+
72
+ # Validate CVE ID
73
+ if not validate_cve_id(cve_id):
74
+ print(f" Invalid CVE ID: {cve_id}")
75
+ sys.exit(1)
76
+
77
+ # Analyze CVE
78
+ result = analyze_cve(cve_id, use_cache=not force)
79
+
80
+ if result:
81
+ print(f"\n Analysis completed: {cve_id}")
82
+ else:
83
+ print(f"\n Analysis failed: {cve_id}")
84
+ sys.exit(1)
85
+
86
+ if __name__ == "__main__":
87
+ main()
requirements.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ requests>=2.31.0
2
+ openai>=1.3.0
3
+ gradio>=4.44.0
4
+ python-dotenv>=1.0.0
search.py ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import json
3
+
4
+ def search_cves(keyword):
5
+ """Search analyzed CVEs by keyword"""
6
+ if not os.path.exists('data'):
7
+ return []
8
+
9
+ results = []
10
+ for filename in os.listdir('data'):
11
+ if filename.endswith('.json'):
12
+ filepath = os.path.join('data', filename)
13
+ with open(filepath, 'r', encoding='utf-8') as f:
14
+ data = json.load(f)
15
+
16
+ # Search in description and AI summary
17
+ cve = data['cve_data']['cve']
18
+ description = cve['descriptions'][0]['value'].lower()
19
+ ai_summary = (data.get('ai_summary', '') or '').lower()
20
+
21
+ if keyword.lower() in description or keyword.lower() in ai_summary:
22
+ results.append({
23
+ 'cve_id': data['cve_id'],
24
+ 'analyzed_at': data.get('analyzed_at', ''),
25
+ 'description': cve['descriptions'][0]['value'][:100] + '...'
26
+ })
27
+
28
+ return results
29
+
30
+ if __name__ == "__main__":
31
+ import sys
32
+ if len(sys.argv) > 1:
33
+ keyword = sys.argv[1]
34
+ results = search_cves(keyword)
35
+ print(f"🔍 Search results for '{keyword}':")
36
+ for r in results:
37
+ print(f" • {r['cve_id']}: {r['description']}")
38
+ else:
39
+ print("Usage: python search.py <keyword>")
storage.py ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ import os
3
+ from datetime import datetime
4
+
5
+ def save_cve_analysis(cve_id, cve_data, summary=None):
6
+ """Save CVE analysis results to JSON file"""
7
+ if not os.path.exists('data'):
8
+ os.makedirs('data')
9
+
10
+ analysis = {
11
+ 'cve_id': cve_id,
12
+ 'analyzed_at': datetime.now().isoformat(),
13
+ 'cve_data': cve_data,
14
+ 'ai_summary': summary
15
+ }
16
+
17
+ filename = f"data/{cve_id}.json"
18
+ with open(filename, 'w', encoding='utf-8') as f:
19
+ json.dump(analysis, f, ensure_ascii=False, indent=2)
20
+
21
+ print(f" Saved to {filename}")
22
+
23
+ def load_cve_analysis(cve_id):
24
+ """Load analyzed CVE data"""
25
+ filename = f"data/{cve_id}.json"
26
+ if os.path.exists(filename):
27
+ with open(filename, 'r', encoding='utf-8') as f:
28
+ return json.load(f)
29
+ return None
30
+
31
+ # Test
32
+ if __name__ == "__main__":
33
+ from api_client import fetch_cve_simple
34
+ cve_data = fetch_cve_simple("CVE-2021-44228")
35
+ if cve_data:
36
+ save_cve_analysis("CVE-2021-44228", cve_data, "Test summary")
37
+ loaded = load_cve_analysis("CVE-2021-44228")
38
+ print(f" Load successful: {loaded['cve_id']}")
web_ui.py ADDED
@@ -0,0 +1,274 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import os
3
+ from main import analyze_cve
4
+ from cve_validator import validate_cve_id
5
+ from search import search_cves
6
+ from storage import load_cve_analysis
7
+
8
+ # Well-known CVE examples for quick testing
9
+ EXAMPLE_CVES = [
10
+ ("CVE-2021-44228", "Log4Shell - Apache Log4j RCE"),
11
+ ("CVE-2020-1472", "Zerologon - Windows Netlogon Vulnerability"),
12
+ ("CVE-2022-22965", "Spring4Shell - Spring Framework RCE"),
13
+ ("CVE-2021-34527", "PrintNightmare - Windows Print Spooler"),
14
+ ("CVE-2020-0601", "CurveBall - Windows CryptoAPI Spoofing"),
15
+ ]
16
+
17
+ def analyze_cve_handler(cve_input):
18
+ """Main CVE analysis function with intelligent caching"""
19
+ if not cve_input.strip():
20
+ return "Please enter a CVE ID", ""
21
+
22
+ # Smart input formatting
23
+ cve_id = cve_input.strip().upper()
24
+ if not cve_id.startswith('CVE-'):
25
+ # Auto-add CVE- prefix for formats like "2021-44228"
26
+ if '-' in cve_id and len(cve_id.split('-')) == 2:
27
+ cve_id = f"CVE-{cve_id}"
28
+
29
+ # Validate format
30
+ if not validate_cve_id(cve_id):
31
+ return f"Invalid CVE format: {cve_id}", ""
32
+
33
+ try:
34
+ # Check for cached analysis
35
+ cached = load_cve_analysis(cve_id)
36
+
37
+ if cached:
38
+ # Load from cache
39
+ cached_date = cached.get('analyzed_at', 'Unknown date')[:10]
40
+ source_info = f"**Source:** Local cache ({cached_date})"
41
+ result = cached
42
+ else:
43
+ # First time analysis
44
+ source_info = "**Source:** NIST API (fresh data)"
45
+ result = analyze_cve(cve_id, use_cache=False)
46
+
47
+ if result:
48
+ cve = result['cve_data']['cve']
49
+
50
+ # Format basic information
51
+ output = f"## {cve['id']}\n\n"
52
+ output += f"**Published:** {cve['published'][:10]}\n"
53
+ output += f"**Status:** {cve.get('vulnStatus', 'Unknown')}\n"
54
+
55
+ # CVSS information
56
+ if 'metrics' in cve and 'cvssMetricV31' in cve['metrics']:
57
+ cvss = cve['metrics']['cvssMetricV31'][0]['cvssData']
58
+ output += f"**CVSS Score:** {cvss['baseScore']}/10.0\n"
59
+ output += f"**Severity:** {cvss['baseSeverity']}\n"
60
+
61
+ # Description - show full description
62
+ description = cve['descriptions'][0]['value']
63
+ output += f"\n**Description:**\n{description}"
64
+
65
+ # Add source info at the bottom
66
+ output += f"\n\n{source_info}"
67
+
68
+ ai_summary = result.get('ai_summary', 'AI summary not available')
69
+
70
+ return output, ai_summary
71
+ else:
72
+ return "Failed to fetch CVE data", ""
73
+
74
+ except Exception as e:
75
+ return "Analysis error occurred", ""
76
+
77
+ def quick_example_handler(example_choice):
78
+ """Handle quick example selection"""
79
+ if example_choice:
80
+ cve_id = example_choice.split(" - ")[0]
81
+ return analyze_cve_handler(cve_id)
82
+ return "Please select an example", ""
83
+
84
+ def search_handler(keyword):
85
+ """Search previously analysed CVEs"""
86
+ if not keyword.strip():
87
+ return "Please enter search keywords"
88
+
89
+ try:
90
+ results = search_cves(keyword)
91
+ if results:
92
+ output = f"## Found {len(results)} results for '{keyword}'\n\n"
93
+
94
+ for i, r in enumerate(results[:8], 1):
95
+ output += f"**{i}. {r['cve_id']}**\n"
96
+ output += f" {r['description']}\n\n"
97
+
98
+ if len(results) > 8:
99
+ output += f"... and {len(results) - 8} more results"
100
+
101
+ return output
102
+ else:
103
+ return f"No results found for '{keyword}'"
104
+ except Exception as e:
105
+ return f"Search failed: {str(e)}"
106
+
107
+ # Custom CSS for beautiful styling
108
+ custom_css = """
109
+ #main-container {
110
+ max-width: 1200px;
111
+ margin: 0 auto;
112
+ padding: 20px;
113
+ }
114
+
115
+ #title-header {
116
+ text-align: center;
117
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
118
+ color: white;
119
+ padding: 30px;
120
+ border-radius: 15px;
121
+ margin-bottom: 30px;
122
+ box-shadow: 0 8px 32px rgba(0,0,0,0.1);
123
+ }
124
+
125
+ #main-input-card {
126
+ background: white;
127
+ padding: 25px;
128
+ border-radius: 12px;
129
+ box-shadow: 0 4px 20px rgba(0,0,0,0.08);
130
+ margin-bottom: 20px;
131
+ border: 1px solid #e1e8ed;
132
+ }
133
+
134
+ #results-container {
135
+ background: white;
136
+ padding: 20px;
137
+ border-radius: 12px;
138
+ box-shadow: 0 4px 20px rgba(0,0,0,0.08);
139
+ margin: 20px 0;
140
+ border: 1px solid #e1e8ed;
141
+ }
142
+
143
+ #analyse-btn {
144
+ background: linear-gradient(45deg, #667eea, #764ba2);
145
+ border: none;
146
+ color: white;
147
+ font-weight: 500;
148
+ height: 52px;
149
+ border-radius: 8px;
150
+ transition: all 0.3s ease;
151
+ margin-top: 20px;
152
+ }
153
+
154
+ #analyse-btn:hover {
155
+ transform: translateY(-2px);
156
+ box-shadow: 0 4px 15px rgba(102, 126, 234, 0.4);
157
+ }
158
+
159
+ .example-btn {
160
+ height: 52px !important;
161
+ margin-top: 16px !important;
162
+ }
163
+
164
+ .quick-examples {
165
+ background: #f8f9fa;
166
+ border-radius: 10px;
167
+ padding: 15px;
168
+ margin: 15px 0;
169
+ border: 1px solid #e9ecef;
170
+ }
171
+
172
+ .search-section {
173
+ background: #fff;
174
+ border-radius: 10px;
175
+ padding: 20px;
176
+ margin: 15px 0;
177
+ border: 1px solid #e1e8ed;
178
+ box-shadow: 0 2px 10px rgba(0,0,0,0.05);
179
+ }
180
+ """
181
+
182
+ # Main interface with beautiful styling
183
+ with gr.Blocks(css=custom_css, title="CVE Analysis Agent", theme=gr.themes.Soft()) as interface:
184
+
185
+ with gr.Column(elem_id="main-container"):
186
+ # Beautiful header - ONLY keep main title
187
+ with gr.Row(elem_id="title-header"):
188
+ gr.Markdown("""
189
+ # CVE Analysis Agent
190
+ """)
191
+
192
+ # Main input card
193
+ with gr.Column(elem_id="main-input-card"):
194
+ gr.Markdown("### Enter CVE ID for Analysis")
195
+
196
+ with gr.Row():
197
+ cve_input = gr.Textbox(
198
+ label="CVE Identifier",
199
+ placeholder="CVE-2021-44228 or 2021-44228",
200
+ info="Smart format detection - accepts both full and short formats",
201
+ scale=4,
202
+ container=True
203
+ )
204
+ analyse_btn = gr.Button(
205
+ "Analyse",
206
+ variant="primary",
207
+ scale=1,
208
+ elem_id="analyse-btn"
209
+ )
210
+
211
+ # Quick examples section
212
+ with gr.Row(elem_classes="quick-examples"):
213
+ gr.Markdown("**Quick Examples:**")
214
+ example_dropdown = gr.Dropdown(
215
+ choices=[f"{cve} - {desc}" for cve, desc in EXAMPLE_CVES],
216
+ label="Select a famous vulnerability",
217
+ value=None,
218
+ scale=3
219
+ )
220
+ example_btn = gr.Button("Try Example", variant="secondary", scale=1, elem_classes="example-btn")
221
+
222
+ # Results container
223
+ with gr.Column(elem_id="results-container"):
224
+ gr.Markdown("### Analysis Results")
225
+
226
+ # CVE Information on top
227
+ basic_output = gr.Markdown(
228
+ label="CVE Information",
229
+ value="*CVE information will appear here after analysis*"
230
+ )
231
+
232
+ # AI Analysis below
233
+ ai_output = gr.Markdown(
234
+ label="AI Security Analysis",
235
+ value="*AI-generated security analysis will appear here...*"
236
+ )
237
+
238
+ # Search section
239
+ with gr.Accordion("Search Previously Analysed CVEs", open=False):
240
+ with gr.Column(elem_classes="search-section"):
241
+ gr.Markdown("**Search through your analysed vulnerabilities**")
242
+ with gr.Row():
243
+ search_input = gr.Textbox(
244
+ label="Search Keywords",
245
+ placeholder="log4j, apache, spring, windows, print",
246
+ scale=3
247
+ )
248
+ search_btn = gr.Button("Search", scale=1)
249
+ search_output = gr.Markdown(
250
+ label="Search Results",
251
+ value="*Search results will appear here*"
252
+ )
253
+
254
+ # Event handlers
255
+ analyse_btn.click(
256
+ analyze_cve_handler,
257
+ inputs=cve_input,
258
+ outputs=[basic_output, ai_output]
259
+ )
260
+
261
+ example_btn.click(
262
+ quick_example_handler,
263
+ inputs=example_dropdown,
264
+ outputs=[basic_output, ai_output]
265
+ )
266
+
267
+ search_btn.click(
268
+ search_handler,
269
+ inputs=search_input,
270
+ outputs=search_output
271
+ )
272
+
273
+ if __name__ == "__main__":
274
+ interface.launch()