Files
securelens-backend/app/services/ai.py
2026-04-07 18:13:43 +05:30

106 lines
4.2 KiB
Python

import json
import logging
from openai import AsyncOpenAI
from app.config import settings
logger = logging.getLogger(__name__)
api_key = settings.openai_api_key or "mock-key-for-testing"
client = AsyncOpenAI(api_key=api_key)
async def enhance_security_issues(issues: list[dict]) -> dict:
"""
Takes a list of basic security issues and uses an LLM to provide:
- Contextual severity
- Natural language explanations
- Auto-generated remediation code snippets
"""
if not settings.openai_api_key:
logger.warning("OPENAI_API_KEY is not set. AI enhancements are skipped.")
return {"enhanced_issues": issues}
prompt = (
"Analyze the following security vulnerabilities:\n"
f"{json.dumps(issues, indent=2)}\n\n"
"Return a JSON object with a single key 'enhanced_issues' containing a list of objects. "
"Each object MUST correspond to one of the original issues and have the following keys: "
"'issue' (exact string of the original issue), "
"'contextual_severity' (Low, Medium, High, Critical), "
"'explanation' (a 1-2 sentence non-technical explanation), "
"'remediation_snippet' (Actionable code snippet, e.g. Nginx config, or 'N/A')."
)
try:
response = await client.chat.completions.create(
model="gpt-3.5-turbo",
messages=[
{"role": "system", "content": "You are a senior cybersecurity automation agent. Always respond with valid JSON."},
{"role": "user", "content": prompt}
],
response_format={"type": "json_object"},
temperature=0.2,
)
content = response.choices[0].message.content
if not content:
return {"enhanced_issues": issues, "ai_error": "Empty response"}
return json.loads(content)
except Exception as e:
logger.error(f"AI Generation Error: {str(e)}")
return {"enhanced_issues": issues, "ai_error": str(e)}
async def chat_with_scan_context(scan_id: str, context_data: dict, user_message: str) -> str:
"""
Allows a user to ask a question about a specific scan's results.
"""
if not settings.openai_api_key:
return "AI Chat is disabled because OPENAI_API_KEY is not configured."
system_prompt = (
"You are SecureLens AI, an expert cybersecurity assistant. "
"You are helping a developer understand a security scan report for their website. "
f"Here is the context of the scan: {json.dumps(context_data)}"
)
try:
response = await client.chat.completions.create(
model="gpt-3.5-turbo",
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_message}
],
temperature=0.5,
)
return response.choices[0].message.content or "No response from AI."
except Exception as e:
logger.error(f"AI Chat Error: {str(e)}")
return "I encountered an error trying to process your request."
async def generate_threat_narrative(context_data: dict) -> str:
"""
Weaves multiple scan issues into a cohesive attack sequence.
"""
if not settings.openai_api_key:
return "AI Threat Narrative is disabled because OPENAI_API_KEY is not configured."
system_prompt = (
"You are a senior cybersecurity red-teamer. Analyze the following security scan results "
"and weave them into a single, cohesive 'Threat Narrative'. Explain how an attacker might "
"chain these specific vulnerabilities together to compromise the system. "
"Keep it professional, concise (2-3 paragraphs), and actionable."
)
try:
response = await client.chat.completions.create(
model="gpt-3.5-turbo",
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": json.dumps(context_data)}
],
temperature=0.7,
)
return response.choices[0].message.content or "Could not generate threat narrative."
except Exception as e:
logger.error(f"AI Narrative Error: {str(e)}")
return "I encountered an error trying to generate the threat narrative."