Skip to content

Commit 0e6acef

Browse files
authored
Merge pull request #136 from Muhammad-aa/http-branch
Added Http-headers
2 parents e56e82d + c10f5b2 commit 0e6acef

File tree

3 files changed

+152
-0
lines changed

3 files changed

+152
-0
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Grab your API key from Open Router:- https://openrouter.ai/
2+
Model is Used is DeepSeek: DeepSeek V3.1 (free). However, feel free to try others.
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
#!/usr/bin/env python3
2+
import requests
3+
import json
4+
import os
5+
import argparse
6+
from typing import Dict, List, Tuple
7+
from openai import OpenAI
8+
9+
class SecurityHeadersAnalyzer:
10+
def __init__(self, api_key: str = None, base_url: str = None, model: str = None):
11+
self.api_key = api_key or os.getenv('OPENROUTER_API_KEY') or os.getenv('OPENAI_API_KEY')
12+
self.base_url = base_url or os.getenv('OPENROUTER_BASE_URL', 'https://openrouter.ai/api/v1')
13+
self.model = model or os.getenv('LLM_MODEL', 'deepseek/deepseek-chat-v3.1:free')
14+
15+
if not self.api_key:
16+
raise ValueError("API key is required. Set OPENROUTER_API_KEY or provide --api-key")
17+
18+
self.client = OpenAI(base_url=self.base_url, api_key=self.api_key)
19+
20+
def fetch_headers(self, url: str, timeout: int = 10) -> Tuple[Dict[str, str], int]:
21+
"""Fetch HTTP headers from URL"""
22+
if not url.startswith(('http://', 'https://')):
23+
url = 'https://' + url
24+
25+
try:
26+
response = requests.get(url, timeout=timeout, allow_redirects=True)
27+
return dict(response.headers), response.status_code
28+
except requests.exceptions.RequestException as e:
29+
print(f"Error fetching {url}: {e}")
30+
return {}, 0
31+
32+
def analyze_headers(self, url: str, headers: Dict[str, str], status_code: int) -> str:
33+
"""Analyze headers using LLM"""
34+
prompt = f"""Analyze the HTTP security headers for {url} (Status: {status_code})
35+
36+
Headers:
37+
{json.dumps(headers, indent=2)}
38+
39+
Provide a comprehensive security analysis including:
40+
1. Security score (0-100) and overall assessment
41+
2. Critical security issues that need immediate attention
42+
3. Missing important security headers
43+
4. Analysis of existing security headers and their effectiveness
44+
5. Specific recommendations for improvement
45+
6. Potential security risks based on current configuration
46+
47+
Focus on practical, actionable advice following current web security best practices. Please do not include ** and #
48+
in the response except for specific references where necessary. use numbers, romans, alphabets instead Format the response well please. """
49+
50+
try:
51+
completion = self.client.chat.completions.create(
52+
model=self.model,
53+
messages=[{"role": "user", "content": prompt}],
54+
temperature=0.2
55+
)
56+
return completion.choices[0].message.content
57+
except Exception as e:
58+
return f"Analysis failed: {e}"
59+
60+
def analyze_url(self, url: str, timeout: int = 10) -> Dict:
61+
"""Analyze a single URL"""
62+
print(f"\nAnalyzing: {url}")
63+
print("-" * 50)
64+
65+
headers, status_code = self.fetch_headers(url, timeout)
66+
if not headers:
67+
return {"url": url, "error": "Failed to fetch headers"}
68+
69+
print(f"Status Code: {status_code}")
70+
print(f"\nHTTP Headers ({len(headers)} found):")
71+
print("-" * 30)
72+
for key, value in headers.items():
73+
print(f"{key}: {value}")
74+
75+
print(f"\nAnalyzing with AI...")
76+
analysis = self.analyze_headers(url, headers, status_code)
77+
78+
print("\nSECURITY ANALYSIS")
79+
print("=" * 50)
80+
print(analysis)
81+
82+
return {
83+
"url": url,
84+
"status_code": status_code,
85+
"headers_count": len(headers),
86+
"analysis": analysis,
87+
"raw_headers": headers
88+
}
89+
90+
def analyze_multiple_urls(self, urls: List[str], timeout: int = 10) -> List[Dict]:
91+
"""Analyze multiple URLs"""
92+
results = []
93+
for i, url in enumerate(urls, 1):
94+
print(f"\n[{i}/{len(urls)}]")
95+
result = self.analyze_url(url, timeout)
96+
results.append(result)
97+
return results
98+
99+
def export_results(self, results: List[Dict], filename: str):
100+
"""Export results to JSON"""
101+
with open(filename, 'w') as f:
102+
json.dump(results, f, indent=2, ensure_ascii=False)
103+
print(f"\nResults exported to: {filename}")
104+
105+
def main():
106+
parser = argparse.ArgumentParser(
107+
description='Analyze HTTP security headers using AI',
108+
formatter_class=argparse.RawDescriptionHelpFormatter,
109+
epilog='''Examples:
110+
python security_headers.py https://example.com
111+
python security_headers.py example.com google.com
112+
python security_headers.py example.com --export results.json
113+
114+
Environment Variables:
115+
OPENROUTER_API_KEY - API key for OpenRouter
116+
OPENAI_API_KEY - API key for OpenAI
117+
LLM_MODEL - Model to use (default: deepseek/deepseek-chat-v3.1:free)'''
118+
)
119+
120+
parser.add_argument('urls', nargs='+', help='URLs to analyze')
121+
parser.add_argument('--api-key', help='API key for LLM service')
122+
parser.add_argument('--base-url', help='Base URL for LLM API')
123+
parser.add_argument('--model', help='LLM model to use')
124+
parser.add_argument('--timeout', type=int, default=10, help='Request timeout (default: 10s)')
125+
parser.add_argument('--export', help='Export results to JSON file')
126+
127+
args = parser.parse_args()
128+
129+
try:
130+
analyzer = SecurityHeadersAnalyzer(
131+
api_key=args.api_key,
132+
base_url=args.base_url,
133+
model=args.model
134+
)
135+
136+
results = analyzer.analyze_multiple_urls(args.urls, args.timeout)
137+
138+
if args.export:
139+
analyzer.export_results(results, args.export)
140+
141+
except ValueError as e:
142+
print(f"Error: {e}")
143+
return 1
144+
except KeyboardInterrupt:
145+
print("\nAnalysis interrupted by user")
146+
return 1
147+
148+
if __name__ == '__main__':
149+
main()
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
openai

0 commit comments

Comments
 (0)