argus-header 0.5.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- argus_header/__init__.py +3 -0
- argus_header/analyzer.py +99 -0
- argus_header/cli.py +138 -0
- argus_header/reporter.py +70 -0
- argus_header/requester.py +83 -0
- argus_header/schemas.py +14 -0
- argus_header/utils.py +9 -0
- argus_header-0.5.0.dist-info/METADATA +402 -0
- argus_header-0.5.0.dist-info/RECORD +13 -0
- argus_header-0.5.0.dist-info/WHEEL +5 -0
- argus_header-0.5.0.dist-info/entry_points.txt +2 -0
- argus_header-0.5.0.dist-info/licenses/LICENSE +21 -0
- argus_header-0.5.0.dist-info/top_level.txt +1 -0
argus_header/__init__.py
ADDED
argus_header/analyzer.py
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
def analyze_headers(headers_data):
|
|
2
|
+
"""
|
|
3
|
+
Analyzes the raw headers and returns a list of findings.
|
|
4
|
+
"""
|
|
5
|
+
if not headers_data.get("success"):
|
|
6
|
+
return []
|
|
7
|
+
|
|
8
|
+
headers = {k.lower(): v for k, v in headers_data["headers"].items()}
|
|
9
|
+
findings = []
|
|
10
|
+
|
|
11
|
+
# --- 1. Security Headers Analysis ---
|
|
12
|
+
|
|
13
|
+
# Content-Security-Policy
|
|
14
|
+
if "content-security-policy" not in headers:
|
|
15
|
+
findings.append({
|
|
16
|
+
"category": "Security",
|
|
17
|
+
"issue": "Missing Content-Security-Policy",
|
|
18
|
+
"severity": "HIGH",
|
|
19
|
+
"risk": "XSS (Cross-Site Scripting) attacks are easier to exploit.",
|
|
20
|
+
"fix": "Add a 'Content-Security-Policy' header defining allowed content sources."
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
# Strict-Transport-Security (HSTS)
|
|
24
|
+
if "strict-transport-security" not in headers:
|
|
25
|
+
findings.append({
|
|
26
|
+
"category": "Security",
|
|
27
|
+
"issue": "Missing Strict-Transport-Security",
|
|
28
|
+
"severity": "HIGH",
|
|
29
|
+
"risk": "Susceptible to Man-in-the-Middle (MITM) protocol downgrade attacks.",
|
|
30
|
+
"fix": "Add 'Strict-Transport-Security: max-age=63072000; includeSubDomains'."
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
# X-Frame-Options
|
|
34
|
+
if "x-frame-options" not in headers and "content-security-policy" not in headers:
|
|
35
|
+
findings.append({
|
|
36
|
+
"category": "Security",
|
|
37
|
+
"issue": "Missing X-Frame-Options",
|
|
38
|
+
"severity": "HIGH",
|
|
39
|
+
"risk": "Vulnerable to Clickjacking attacks.",
|
|
40
|
+
"fix": "Add 'X-Frame-Options: DENY' or 'SAMEORIGIN'."
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
# X-Content-Type-Options
|
|
44
|
+
if "x-content-type-options" not in headers:
|
|
45
|
+
findings.append({
|
|
46
|
+
"category": "Security",
|
|
47
|
+
"issue": "Missing X-Content-Type-Options",
|
|
48
|
+
"severity": "MEDIUM",
|
|
49
|
+
"risk": "Browsers may MIME-sniff the response body, leading to XSS.",
|
|
50
|
+
"fix": "Add 'X-Content-Type-Options: nosniff'."
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
# --- 2. Information Leakage ---
|
|
54
|
+
|
|
55
|
+
# Server Header
|
|
56
|
+
if "server" in headers:
|
|
57
|
+
findings.append({
|
|
58
|
+
"category": "Leakage",
|
|
59
|
+
"issue": f"Server Header Leaked: {headers['server']}",
|
|
60
|
+
"severity": "LOW",
|
|
61
|
+
"risk": "Reveals server technology, helping attackers verify CVEs.",
|
|
62
|
+
"fix": "Configure server to suppress or obfuscate the 'Server' header."
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
# X-Powered-By
|
|
66
|
+
if "x-powered-by" in headers:
|
|
67
|
+
findings.append({
|
|
68
|
+
"category": "Leakage",
|
|
69
|
+
"issue": f"X-Powered-By Leaked: {headers['x-powered-by']}",
|
|
70
|
+
"severity": "MEDIUM",
|
|
71
|
+
"risk": "Reveals specific framework/version info.",
|
|
72
|
+
"fix": "Remove the 'X-Powered-By' header in server config."
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
# --- 3. CORS Misconfiguration ---
|
|
76
|
+
|
|
77
|
+
if "access-control-allow-origin" in headers:
|
|
78
|
+
if headers["access-control-allow-origin"] == "*":
|
|
79
|
+
findings.append({
|
|
80
|
+
"category": "CORS",
|
|
81
|
+
"issue": "CORS Access-Control-Allow-Origin is '*'",
|
|
82
|
+
"severity": "MEDIUM",
|
|
83
|
+
"risk": "Allows any domain to access resources (dangerous if auth is used).",
|
|
84
|
+
"fix": "Restrict to specific trusted domains."
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
# --- 4. Performance ---
|
|
88
|
+
|
|
89
|
+
# Cache-Control
|
|
90
|
+
if "cache-control" not in headers:
|
|
91
|
+
findings.append({
|
|
92
|
+
"category": "Performance",
|
|
93
|
+
"issue": "Missing Cache-Control Header",
|
|
94
|
+
"severity": "LOW",
|
|
95
|
+
"risk": "Browser may not cache resources efficiently, slowing load times.",
|
|
96
|
+
"fix": "Add 'Cache-Control' header (e.g., max-age=3600)."
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
return findings
|
argus_header/cli.py
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
import sys
|
|
3
|
+
from concurrent.futures import ThreadPoolExecutor
|
|
4
|
+
|
|
5
|
+
from rich.console import Console
|
|
6
|
+
|
|
7
|
+
from argus_header import __version__
|
|
8
|
+
from .requester import fetch_headers
|
|
9
|
+
from .analyzer import analyze_headers
|
|
10
|
+
from .reporter import print_report, save_json
|
|
11
|
+
|
|
12
|
+
console = Console()
|
|
13
|
+
|
|
14
|
+
BANNER = r"""
|
|
15
|
+
___
|
|
16
|
+
/ _ | _______ _____ _____ _____
|
|
17
|
+
/ __ |/ __/ _ `/ // (_-</(_-<(_-<
|
|
18
|
+
/_/ |_/_/ \_, /\_,_/___/___/___/
|
|
19
|
+
/_/
|
|
20
|
+
|
|
21
|
+
Argus Header
|
|
22
|
+
HTTP Header Security Analyzer
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
def print_banner():
|
|
26
|
+
console.print(f"[bold cyan]{BANNER}[/bold cyan]")
|
|
27
|
+
console.print(f"[bold]Version:[/bold] {__version__}\n")
|
|
28
|
+
|
|
29
|
+
def scan_target(url: str, args):
|
|
30
|
+
response_data = fetch_headers(
|
|
31
|
+
url,
|
|
32
|
+
method=args.method,
|
|
33
|
+
follow_redirects=not args.no_redirect,
|
|
34
|
+
timeout=args.timeout,
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
findings = analyze_headers(response_data)
|
|
38
|
+
print_report(response_data, findings)
|
|
39
|
+
|
|
40
|
+
if args.json and len(args.url) == 1:
|
|
41
|
+
save_json(response_data, findings, args.json)
|
|
42
|
+
|
|
43
|
+
def main():
|
|
44
|
+
parser = argparse.ArgumentParser(
|
|
45
|
+
prog="argus-header",
|
|
46
|
+
description="Argus Header - HTTP Header Security Analyzer",
|
|
47
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
48
|
+
epilog="""
|
|
49
|
+
Examples:
|
|
50
|
+
argus-header https://example.com
|
|
51
|
+
argus-header https://example.com --method HEAD
|
|
52
|
+
argus-header https://example.com --json report.json
|
|
53
|
+
argus-header https://google.com https://github.com --parallel
|
|
54
|
+
argus-header --version
|
|
55
|
+
""",
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
parser.add_argument(
|
|
59
|
+
"-v",
|
|
60
|
+
"--version",
|
|
61
|
+
action="version",
|
|
62
|
+
version=f"Argus Header {__version__}",
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
parser.add_argument(
|
|
66
|
+
"url",
|
|
67
|
+
nargs="+",
|
|
68
|
+
help="One or more target URLs to analyze.",
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
parser.add_argument(
|
|
72
|
+
"--method",
|
|
73
|
+
choices=["GET", "HEAD"],
|
|
74
|
+
default="GET",
|
|
75
|
+
help="HTTP request method (default: GET).",
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
parser.add_argument(
|
|
79
|
+
"--no-redirect",
|
|
80
|
+
action="store_true",
|
|
81
|
+
help="Disable HTTP redirect following.",
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
parser.add_argument(
|
|
85
|
+
"--timeout",
|
|
86
|
+
type=int,
|
|
87
|
+
default=10,
|
|
88
|
+
help="Request timeout in seconds (default: 10).",
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
parser.add_argument(
|
|
92
|
+
"--json",
|
|
93
|
+
metavar="FILE",
|
|
94
|
+
help="Save the report to a JSON file.",
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
parser.add_argument(
|
|
98
|
+
"--parallel",
|
|
99
|
+
action="store_true",
|
|
100
|
+
help="Scan multiple URLs concurrently.",
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
parser.add_argument(
|
|
104
|
+
"--verbose",
|
|
105
|
+
action="store_true",
|
|
106
|
+
help="Reserved for future verbose output.",
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
args = parser.parse_args()
|
|
110
|
+
|
|
111
|
+
print_banner()
|
|
112
|
+
|
|
113
|
+
try:
|
|
114
|
+
if args.parallel and len(args.url) > 1:
|
|
115
|
+
console.print(
|
|
116
|
+
f"[bold green][*][/bold green] Scanning {len(args.url)} targets in parallel...\n"
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
with ThreadPoolExecutor(max_workers=5) as executor:
|
|
120
|
+
list(executor.map(lambda u: scan_target(u, args), args.url))
|
|
121
|
+
else:
|
|
122
|
+
for url in args.url:
|
|
123
|
+
scan_target(url, args)
|
|
124
|
+
console.rule()
|
|
125
|
+
|
|
126
|
+
sys.exit(0)
|
|
127
|
+
|
|
128
|
+
except KeyboardInterrupt:
|
|
129
|
+
console.print("\n[bold yellow]Scan cancelled by user.[/bold yellow]")
|
|
130
|
+
sys.exit(130)
|
|
131
|
+
|
|
132
|
+
except Exception as exc:
|
|
133
|
+
console.print(f"\n[bold red]Unexpected error:[/bold red] {exc}")
|
|
134
|
+
sys.exit(1)
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
if __name__ == "__main__":
|
|
138
|
+
main()
|
argus_header/reporter.py
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from rich.console import Console
|
|
3
|
+
from rich.table import Table
|
|
4
|
+
from rich.panel import Panel
|
|
5
|
+
from rich.text import Text
|
|
6
|
+
|
|
7
|
+
console = Console()
|
|
8
|
+
|
|
9
|
+
def print_report(response_data, findings):
|
|
10
|
+
"""Prints a pretty CLI report."""
|
|
11
|
+
|
|
12
|
+
# 1. Status Section
|
|
13
|
+
if not response_data["success"]:
|
|
14
|
+
console.print(f"[bold red]Error connecting to {response_data['url']}: {response_data.get('error')}[/bold red]")
|
|
15
|
+
return
|
|
16
|
+
|
|
17
|
+
console.print(Panel(
|
|
18
|
+
f"[bold green]Target:[/bold green] {response_data['url']}\n"
|
|
19
|
+
f"[bold blue]Status:[/bold blue] {response_data['status_code']}\n"
|
|
20
|
+
f"[bold]Headers Found:[/bold] {len(response_data['headers'])}",
|
|
21
|
+
title="Scan Summary",
|
|
22
|
+
expand=False
|
|
23
|
+
))
|
|
24
|
+
|
|
25
|
+
# 2. Findings Table
|
|
26
|
+
if findings:
|
|
27
|
+
table = Table(title="Analysis Findings", show_header=True, header_style="bold magenta")
|
|
28
|
+
table.add_column("Severity", style="dim", width=12)
|
|
29
|
+
table.add_column("Issue", style="cyan")
|
|
30
|
+
table.add_column("Risk")
|
|
31
|
+
table.add_column("Recommendation", style="green")
|
|
32
|
+
|
|
33
|
+
# Sort findings: HIGH -> MEDIUM -> LOW
|
|
34
|
+
severity_map = {"HIGH": 0, "MEDIUM": 1, "LOW": 2}
|
|
35
|
+
sorted_findings = sorted(findings, key=lambda x: severity_map.get(x["severity"], 3))
|
|
36
|
+
|
|
37
|
+
for f in sorted_findings:
|
|
38
|
+
severity_color = "red" if f["severity"] == "HIGH" else "yellow" if f["severity"] == "MEDIUM" else "blue"
|
|
39
|
+
|
|
40
|
+
table.add_row(
|
|
41
|
+
f"[{severity_color}]{f['severity']}[/{severity_color}]",
|
|
42
|
+
f["issue"],
|
|
43
|
+
f["risk"],
|
|
44
|
+
f["fix"]
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
console.print(table)
|
|
48
|
+
else:
|
|
49
|
+
console.print("[bold green]No significant issues found![/bold green]")
|
|
50
|
+
|
|
51
|
+
# 3. Raw Headers (Optional or summarized)
|
|
52
|
+
console.print("\n[dim]Run with --verbose to see full header dump (not implemented in basic guide).[/dim]")
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def save_json(response_data, findings, filepath):
|
|
56
|
+
"""Saves the report to a JSON file."""
|
|
57
|
+
output = {
|
|
58
|
+
"target": response_data.get("url"),
|
|
59
|
+
"status": response_data.get("status_code"),
|
|
60
|
+
"scan_time": "Now", # You can use datetime here
|
|
61
|
+
"headers": response_data.get("headers"),
|
|
62
|
+
"findings": findings
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
try:
|
|
66
|
+
with open(filepath, 'w') as f:
|
|
67
|
+
json.dump(output, f, indent=4)
|
|
68
|
+
console.print(f"[bold green]✔ Report saved to {filepath}[/bold green]")
|
|
69
|
+
except Exception as e:
|
|
70
|
+
console.print(f"[bold red]Failed to save JSON:[/bold red] {e}")
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import requests
|
|
2
|
+
from requests.adapters import HTTPAdapter
|
|
3
|
+
from urllib3.util.retry import Retry
|
|
4
|
+
from .utils import normalize_url
|
|
5
|
+
|
|
6
|
+
def fetch_headers(url: str, method="GET", follow_redirects=True, timeout=10):
|
|
7
|
+
"""
|
|
8
|
+
Fetches headers from the target URL.
|
|
9
|
+
Returns a dictionary containing headers, status code, and URL.
|
|
10
|
+
"""
|
|
11
|
+
target_url = normalize_url(url)
|
|
12
|
+
|
|
13
|
+
# Configure retry logic (3 attempts)
|
|
14
|
+
retry_strategy = Retry(
|
|
15
|
+
total=3,
|
|
16
|
+
backoff_factor=1,
|
|
17
|
+
status_forcelist=[429, 500, 502, 503, 504]
|
|
18
|
+
)
|
|
19
|
+
adapter = HTTPAdapter(max_retries=retry_strategy)
|
|
20
|
+
session = requests.Session()
|
|
21
|
+
session.mount("https://", adapter)
|
|
22
|
+
session.mount("http://", adapter)
|
|
23
|
+
|
|
24
|
+
try:
|
|
25
|
+
response = session.request(
|
|
26
|
+
method=method,
|
|
27
|
+
url=target_url,
|
|
28
|
+
allow_redirects=follow_redirects,
|
|
29
|
+
timeout=timeout,
|
|
30
|
+
headers={"User-Agent": "HeaderScan-Tool/1.0"} # Polite User-Agent
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
return {
|
|
34
|
+
"success": True,
|
|
35
|
+
"url": response.url,
|
|
36
|
+
"status_code": response.status_code,
|
|
37
|
+
"headers": dict(response.headers),
|
|
38
|
+
"http_version": response.raw.version
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
except requests.exceptions.Timeout:
|
|
42
|
+
return {
|
|
43
|
+
"success": False,
|
|
44
|
+
"url": target_url,
|
|
45
|
+
"error": "Request timed out. The server took too long to respond."
|
|
46
|
+
}
|
|
47
|
+
except requests.exceptions.SSLError:
|
|
48
|
+
return {
|
|
49
|
+
"success": False,
|
|
50
|
+
"url": target_url,
|
|
51
|
+
"error": "SSL verification failed. The certificate might be invalid."
|
|
52
|
+
}
|
|
53
|
+
except requests.exceptions.ConnectionError:
|
|
54
|
+
return {
|
|
55
|
+
"success": False,
|
|
56
|
+
"url": target_url,
|
|
57
|
+
"error": "Failed to connect to the server. Please check the URL and your internet connection."
|
|
58
|
+
}
|
|
59
|
+
except requests.exceptions.TooManyRedirects:
|
|
60
|
+
return {
|
|
61
|
+
"success": False,
|
|
62
|
+
"url": target_url,
|
|
63
|
+
"error": "Too many redirects. The URL might be in a redirect loop."
|
|
64
|
+
}
|
|
65
|
+
except requests.exceptions.MissingSchema:
|
|
66
|
+
return {
|
|
67
|
+
"success": False,
|
|
68
|
+
"url": target_url,
|
|
69
|
+
"error": "Invalid URL format. Missing schema (http:// or https://)."
|
|
70
|
+
}
|
|
71
|
+
except requests.exceptions.InvalidURL:
|
|
72
|
+
return {
|
|
73
|
+
"success": False,
|
|
74
|
+
"url": target_url,
|
|
75
|
+
"error": "Invalid URL. Please check the URL and try again."
|
|
76
|
+
}
|
|
77
|
+
except requests.exceptions.RequestException as e:
|
|
78
|
+
return {
|
|
79
|
+
"success": False,
|
|
80
|
+
"url": target_url,
|
|
81
|
+
"error": f"An error occurred: {str(e)}"
|
|
82
|
+
}
|
|
83
|
+
|
argus_header/schemas.py
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from pydantic import BaseModel, HttpUrl
|
|
2
|
+
from typing import Dict, List
|
|
3
|
+
|
|
4
|
+
class AnalysisSummary(BaseModel):
|
|
5
|
+
total_checked: int
|
|
6
|
+
missing: int
|
|
7
|
+
risk_level: str
|
|
8
|
+
|
|
9
|
+
class AnalysisResult(BaseModel):
|
|
10
|
+
summary: AnalysisSummary
|
|
11
|
+
details: List[Dict]
|
|
12
|
+
|
|
13
|
+
class AnalyzeRequest(BaseModel):
|
|
14
|
+
url: HttpUrl
|
argus_header/utils.py
ADDED
|
@@ -0,0 +1,402 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: argus-header
|
|
3
|
+
Version: 0.5.0
|
|
4
|
+
Summary: A Python CLI tool for analyzing HTTP response headers and identifying security issues.
|
|
5
|
+
Author-email: Sriram <sriram060106@gmail.com>
|
|
6
|
+
License: MIT License
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2025 sriram
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
|
18
|
+
copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
+
SOFTWARE.
|
|
27
|
+
|
|
28
|
+
Project-URL: Homepage, https://github.com/heyshreee/argus-header
|
|
29
|
+
Project-URL: Repository, https://github.com/heyshreee/argus-header
|
|
30
|
+
Project-URL: Issues, https://github.com/heyshreee/argus-header/issues
|
|
31
|
+
Keywords: http,https,headers,security,cybersecurity,cli,pentesting,web-security,header-analysis
|
|
32
|
+
Classifier: Development Status :: 4 - Beta
|
|
33
|
+
Classifier: Environment :: Console
|
|
34
|
+
Classifier: Intended Audience :: Developers
|
|
35
|
+
Classifier: Intended Audience :: Information Technology
|
|
36
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
37
|
+
Classifier: Operating System :: OS Independent
|
|
38
|
+
Classifier: Programming Language :: Python :: 3
|
|
39
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
40
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
41
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
42
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
43
|
+
Classifier: Topic :: Internet :: WWW/HTTP
|
|
44
|
+
Classifier: Topic :: Security
|
|
45
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
46
|
+
Requires-Python: >=3.9
|
|
47
|
+
Description-Content-Type: text/markdown
|
|
48
|
+
License-File: LICENSE
|
|
49
|
+
Requires-Dist: requests>=2.32.0
|
|
50
|
+
Requires-Dist: rich>=13.7.0
|
|
51
|
+
Dynamic: license-file
|
|
52
|
+
|
|
53
|
+
# 🛡️ Argus Header
|
|
54
|
+
|
|
55
|
+
> Fast, lightweight HTTP security header analyzer built for developers, security engineers, and penetration testers.
|
|
56
|
+
|
|
57
|
+

|
|
58
|
+

|
|
59
|
+

|
|
60
|
+
|
|
61
|
+
Argus Header is a command-line tool that analyzes HTTP response headers and identifies common security misconfigurations, information leakage, and header-related best practice issues.
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## ✨ Features
|
|
66
|
+
|
|
67
|
+
### HTTP Request Engine
|
|
68
|
+
|
|
69
|
+
- GET and HEAD request support
|
|
70
|
+
- Configurable request timeout
|
|
71
|
+
- Redirect support
|
|
72
|
+
- Retry mechanism for temporary failures
|
|
73
|
+
- Multiple URL scanning
|
|
74
|
+
- Parallel scanning
|
|
75
|
+
|
|
76
|
+
### Security Analysis
|
|
77
|
+
|
|
78
|
+
Detects missing security headers including:
|
|
79
|
+
|
|
80
|
+
- Content-Security-Policy (CSP)
|
|
81
|
+
- Strict-Transport-Security (HSTS)
|
|
82
|
+
- X-Frame-Options
|
|
83
|
+
- X-Content-Type-Options
|
|
84
|
+
|
|
85
|
+
### Information Disclosure Detection
|
|
86
|
+
|
|
87
|
+
Checks for exposed:
|
|
88
|
+
|
|
89
|
+
- Server
|
|
90
|
+
- X-Powered-By
|
|
91
|
+
|
|
92
|
+
### CORS Analysis
|
|
93
|
+
|
|
94
|
+
Detects:
|
|
95
|
+
|
|
96
|
+
- Access-Control-Allow-Origin: *
|
|
97
|
+
|
|
98
|
+
### Performance Checks
|
|
99
|
+
|
|
100
|
+
Checks:
|
|
101
|
+
|
|
102
|
+
- Cache-Control
|
|
103
|
+
|
|
104
|
+
### Reports
|
|
105
|
+
|
|
106
|
+
- Beautiful Rich CLI output
|
|
107
|
+
- JSON report export
|
|
108
|
+
- Severity levels
|
|
109
|
+
- Recommendations
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
# Installation
|
|
114
|
+
|
|
115
|
+
## From Source
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
git clone https://github.com/heyshreee/argus-header.git
|
|
119
|
+
|
|
120
|
+
cd argus-header
|
|
121
|
+
|
|
122
|
+
python -m venv .venv
|
|
123
|
+
|
|
124
|
+
source .venv/bin/activate
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Windows
|
|
128
|
+
|
|
129
|
+
```powershell
|
|
130
|
+
.venv\Scripts\activate
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Install
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
pip install -e .
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
## Verify Installation
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
argus-header --version
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
Expected output
|
|
148
|
+
|
|
149
|
+
```text
|
|
150
|
+
argus-header 0.5.0
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
# Usage
|
|
156
|
+
|
|
157
|
+
Basic scan
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
argus-header https://example.com
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
HEAD request
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
argus-header https://example.com --method HEAD
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
Custom timeout
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
argus-header https://example.com --timeout 5
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
Multiple URLs
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
argus-header https://google.com https://github.com --parallel
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
Disable redirects
|
|
182
|
+
|
|
183
|
+
```bash
|
|
184
|
+
argus-header https://example.com --no-redirect
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
Export JSON
|
|
188
|
+
|
|
189
|
+
```bash
|
|
190
|
+
argus-header https://example.com --json report.json
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
Help
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
argus-header --help
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
# Command Line Options
|
|
202
|
+
|
|
203
|
+
| Option | Description |
|
|
204
|
+
|---------|-------------|
|
|
205
|
+
| --method | HTTP Method (GET / HEAD) |
|
|
206
|
+
| --timeout | Request timeout |
|
|
207
|
+
| --parallel | Scan multiple URLs concurrently |
|
|
208
|
+
| --json FILE | Save report as JSON |
|
|
209
|
+
| --no-redirect | Disable redirect following |
|
|
210
|
+
| --verbose | Verbose output |
|
|
211
|
+
| --version | Display version |
|
|
212
|
+
| --help | Show help |
|
|
213
|
+
|
|
214
|
+
---
|
|
215
|
+
|
|
216
|
+
# Example Output
|
|
217
|
+
|
|
218
|
+
```text
|
|
219
|
+
Target
|
|
220
|
+
https://example.com
|
|
221
|
+
|
|
222
|
+
Status
|
|
223
|
+
200
|
|
224
|
+
|
|
225
|
+
Headers Found
|
|
226
|
+
18
|
|
227
|
+
|
|
228
|
+
HIGH
|
|
229
|
+
Missing Content-Security-Policy
|
|
230
|
+
|
|
231
|
+
HIGH
|
|
232
|
+
Missing Strict-Transport-Security
|
|
233
|
+
|
|
234
|
+
MEDIUM
|
|
235
|
+
X-Powered-By Header Exposed
|
|
236
|
+
|
|
237
|
+
LOW
|
|
238
|
+
Missing Cache-Control
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
---
|
|
242
|
+
|
|
243
|
+
# Project Structure
|
|
244
|
+
|
|
245
|
+
```
|
|
246
|
+
argus-header/
|
|
247
|
+
|
|
248
|
+
src/
|
|
249
|
+
└── argus_header/
|
|
250
|
+
├── __init__.py
|
|
251
|
+
├── cli.py
|
|
252
|
+
├── requester.py
|
|
253
|
+
├── analyzer.py
|
|
254
|
+
├── reporter.py
|
|
255
|
+
└── utils.py
|
|
256
|
+
|
|
257
|
+
tests/
|
|
258
|
+
|
|
259
|
+
README.md
|
|
260
|
+
LICENSE
|
|
261
|
+
pyproject.toml
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
---
|
|
265
|
+
|
|
266
|
+
# Current Checks
|
|
267
|
+
|
|
268
|
+
## Security Headers
|
|
269
|
+
|
|
270
|
+
- Content-Security-Policy
|
|
271
|
+
- Strict-Transport-Security
|
|
272
|
+
- X-Frame-Options
|
|
273
|
+
- X-Content-Type-Options
|
|
274
|
+
|
|
275
|
+
## Information Leakage
|
|
276
|
+
|
|
277
|
+
- Server
|
|
278
|
+
- X-Powered-By
|
|
279
|
+
|
|
280
|
+
## CORS
|
|
281
|
+
|
|
282
|
+
- Wildcard Access-Control-Allow-Origin
|
|
283
|
+
|
|
284
|
+
## Performance
|
|
285
|
+
|
|
286
|
+
- Cache-Control
|
|
287
|
+
|
|
288
|
+
---
|
|
289
|
+
|
|
290
|
+
# Roadmap
|
|
291
|
+
|
|
292
|
+
## v0.6.0
|
|
293
|
+
|
|
294
|
+
- Security score
|
|
295
|
+
- Grade (A–F)
|
|
296
|
+
- Cookie analysis
|
|
297
|
+
- CSP validation
|
|
298
|
+
- HSTS validation
|
|
299
|
+
|
|
300
|
+
## v0.7.0
|
|
301
|
+
|
|
302
|
+
- HTML reports
|
|
303
|
+
- Markdown reports
|
|
304
|
+
- Response time
|
|
305
|
+
- Redirect chain
|
|
306
|
+
- HTTP version display
|
|
307
|
+
|
|
308
|
+
## v0.8.0
|
|
309
|
+
|
|
310
|
+
- Unit tests
|
|
311
|
+
- GitHub Actions
|
|
312
|
+
- Documentation improvements
|
|
313
|
+
- Better architecture
|
|
314
|
+
|
|
315
|
+
## v0.9.0
|
|
316
|
+
|
|
317
|
+
- TLS inspection
|
|
318
|
+
- Certificate analysis
|
|
319
|
+
- HTTP/2 detection
|
|
320
|
+
- Advanced CORS analysis
|
|
321
|
+
|
|
322
|
+
## v1.0.0
|
|
323
|
+
|
|
324
|
+
- Stable public release
|
|
325
|
+
- Complete security analysis
|
|
326
|
+
- Production-ready documentation
|
|
327
|
+
- Comprehensive testing
|
|
328
|
+
|
|
329
|
+
---
|
|
330
|
+
|
|
331
|
+
# Development
|
|
332
|
+
|
|
333
|
+
Clone
|
|
334
|
+
|
|
335
|
+
```bash
|
|
336
|
+
git clone https://github.com/heyshreee/argus-header.git
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
Install development version
|
|
340
|
+
|
|
341
|
+
```bash
|
|
342
|
+
pip install -e .
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
Run
|
|
346
|
+
|
|
347
|
+
```bash
|
|
348
|
+
argus-header https://example.com
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
---
|
|
352
|
+
|
|
353
|
+
# Contributing
|
|
354
|
+
|
|
355
|
+
Contributions are welcome.
|
|
356
|
+
|
|
357
|
+
1. Fork the repository
|
|
358
|
+
2. Create a feature branch
|
|
359
|
+
|
|
360
|
+
```bash
|
|
361
|
+
git checkout -b feature/my-feature
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
3. Commit
|
|
365
|
+
|
|
366
|
+
```bash
|
|
367
|
+
git commit -m "feat: add awesome feature"
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
4. Push
|
|
371
|
+
|
|
372
|
+
```bash
|
|
373
|
+
git push origin feature/my-feature
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
5. Open a Pull Request
|
|
377
|
+
|
|
378
|
+
---
|
|
379
|
+
|
|
380
|
+
# License
|
|
381
|
+
|
|
382
|
+
Released under the MIT License.
|
|
383
|
+
|
|
384
|
+
See LICENSE for details.
|
|
385
|
+
|
|
386
|
+
---
|
|
387
|
+
|
|
388
|
+
# Author
|
|
389
|
+
|
|
390
|
+
**Sriram**
|
|
391
|
+
|
|
392
|
+
GitHub
|
|
393
|
+
|
|
394
|
+
https://github.com/heyshreee
|
|
395
|
+
|
|
396
|
+
---
|
|
397
|
+
|
|
398
|
+
## Disclaimer
|
|
399
|
+
|
|
400
|
+
Argus Header is intended for defensive security, security auditing, learning, and authorized penetration testing only.
|
|
401
|
+
|
|
402
|
+
Only scan systems that you own or have explicit permission to assess.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
argus_header/__init__.py,sha256=uQVjPzsddEJGsZjXUB0SHzx9tAoc0of3C58EGEfc8oU,50
|
|
2
|
+
argus_header/analyzer.py,sha256=bnWgGBNnw_5oEIG908A8UJxdVoB3ri-p05KyZYsvDh8,3747
|
|
3
|
+
argus_header/cli.py,sha256=V0jmBZFLqJGhBBt_SwfUwXlF197iTRNCb5Eat5ZXHKA,3578
|
|
4
|
+
argus_header/reporter.py,sha256=0pLQw5b4amUGAGswyh4SJSHDgy9klJbV_Sj05lTIPt8,2605
|
|
5
|
+
argus_header/requester.py,sha256=C3s5KjiTaUUH7fqZtTSf7u9X2d4ePWji_7-jkUCb0JI,2795
|
|
6
|
+
argus_header/schemas.py,sha256=PmZdt2qasD1g1Ro_wUPODP3WCix15ZaN4VKBPJDFaSI,315
|
|
7
|
+
argus_header/utils.py,sha256=v7W6XE04DY7obHgvySu5OJPw_9OTJaFw2CXjAseSxlo,235
|
|
8
|
+
argus_header-0.5.0.dist-info/licenses/LICENSE,sha256=MURT6Y_IYDbgb8tnFKQG68FzIpFANsOdsueZDdMX_50,1084
|
|
9
|
+
argus_header-0.5.0.dist-info/METADATA,sha256=AhMwwTA6VRpMHAYyD0IRCFT3F4_3ZJ2VpgvvaZdTchQ,7579
|
|
10
|
+
argus_header-0.5.0.dist-info/WHEEL,sha256=K260EYznzXsJYBQGqmI8VTxEdiZYNvDZwW9cBh9-_MA,91
|
|
11
|
+
argus_header-0.5.0.dist-info/entry_points.txt,sha256=k5foSrq495f7voIC_gC7TQHXcqmrap3a49lb330DYBA,55
|
|
12
|
+
argus_header-0.5.0.dist-info/top_level.txt,sha256=M7zERlzbzua16PH1OvPAWR0zowIjFFwVnygXKtVnOA0,13
|
|
13
|
+
argus_header-0.5.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 sriram
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
argus_header
|