header-analyzer 1.0.0__tar.gz

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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Negrescu Alexandru Mihai
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,153 @@
1
+ Metadata-Version: 2.4
2
+ Name: header-analyzer
3
+ Version: 1.0.0
4
+ Summary: A CLI tool for analyzing HTTP security headers
5
+ Author: negoro26
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/negoro26/Header-analyzer
8
+ Project-URL: Repository, https://github.com/negoro26/Header-analyzer.git
9
+ Project-URL: Issues, https://github.com/negoro26/Header-analyzer/issues
10
+ Keywords: security,http,headers,infosec,cli,hsts
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Environment :: Console
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Intended Audience :: Information Technology
15
+ Classifier: Intended Audience :: System Administrators
16
+ Classifier: License :: OSI Approved :: MIT License
17
+ Classifier: Operating System :: OS Independent
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3.8
20
+ Classifier: Programming Language :: Python :: 3.9
21
+ Classifier: Programming Language :: Python :: 3.10
22
+ Classifier: Programming Language :: Python :: 3.11
23
+ Classifier: Programming Language :: Python :: 3.12
24
+ Classifier: Topic :: Security
25
+ Classifier: Topic :: Internet :: WWW/HTTP
26
+ Classifier: Topic :: Utilities
27
+ Requires-Python: >=3.8
28
+ Description-Content-Type: text/markdown
29
+ License-File: LICENSE
30
+ Requires-Dist: requests>=2.28.0
31
+ Dynamic: license-file
32
+
33
+ # Header-analyzer
34
+
35
+ A Python CLI tool for analyzing HTTP security headers. Scans target URLs, evaluates security posture, and provides a letter grade with detailed breakdown.
36
+
37
+ ## Features
38
+
39
+ - **Security Header Analysis** – Checks for HSTS, CSP, X-Frame-Options, X-Content-Type-Options, and more
40
+ - **Security Grading** – Letter grade (A+ to F) based on header configuration
41
+ - **HSTS Preload Detection** – Sites on browser preload lists get automatic A+ rating
42
+ - **Sensitive Header Detection** – Flags headers that may leak server/stack details
43
+ - **Flexible Requests** – Custom headers, User-Agent override, timeout, and SSL bypass options
44
+
45
+ ## Installation
46
+
47
+ ### Via pip (recommended)
48
+
49
+ ```bash
50
+ pip install git+https://github.com/negoro26/Header-analyzer.git
51
+ ```
52
+
53
+ This installs the `header-analyzer` command globally (or in your active virtual environment).
54
+
55
+ ### Development install (editable)
56
+
57
+ ```bash
58
+ git clone https://github.com/negoro26/Header-analyzer.git
59
+ cd Header-analyzer
60
+
61
+ # Windows
62
+ py -3 -m venv .venv && .\.venv\Scripts\Activate.ps1
63
+
64
+ # macOS/Linux
65
+ python3 -m venv .venv && source .venv/bin/activate
66
+
67
+ pip install -e .
68
+ ```
69
+
70
+ ## Usage
71
+
72
+ ```bash
73
+ header-analyzer <url> [options]
74
+ ```
75
+
76
+ ### Options
77
+
78
+ | Flag | Description |
79
+ |------|-------------|
80
+ | `-k, --insecure` | Skip SSL certificate verification |
81
+ | `--timeout <int>` | Request timeout in seconds (default: 10) |
82
+ | `--user-agent <string>` | Override User-Agent header |
83
+ | `-H, --header "Key: Value"` | Add custom request header (repeatable) |
84
+ | `--no-default-headers` | Start with empty header set |
85
+ | `--json` | Output headers as prettified JSON |
86
+
87
+ ### Examples
88
+
89
+ ```bash
90
+ # Basic scan
91
+ header-analyzer example.com
92
+
93
+ # Skip SSL verification with shorter timeout
94
+ header-analyzer https://example.com -k --timeout 5
95
+
96
+ # Custom headers
97
+ header-analyzer https://example.com --user-agent "MyScanner/1.0" \
98
+ -H "Accept-Language: en-US"
99
+ ```
100
+
101
+ ## Grading System
102
+
103
+ Sites are graded based on security header presence and configuration:
104
+
105
+ | Grade | Score | Description |
106
+ |-------|-------|-------------|
107
+ | A+ | — | Browser Trusted (HSTS preloaded) |
108
+ | A+ | 90%+ | Excellent |
109
+ | A | 75%+ | Very Good |
110
+ | B | 60%+ | Good |
111
+ | C | 45%+ | Acceptable |
112
+ | D | 30%+ | Poor |
113
+ | F | <30% | Critical |
114
+
115
+ ### Scoring Breakdown
116
+
117
+ - **HTTPS Baseline**: +25 pts
118
+ - **Strict-Transport-Security**: +25 pts
119
+ - **Content-Security-Policy**: +20 pts
120
+ - **X-Content-Type-Options**: +10 pts
121
+ - **X-Frame-Options**: +10 pts
122
+ - **Referrer-Policy**: +5 pts
123
+ - **Permissions-Policy**: +5 pts
124
+ - **Sensitive headers exposed**: -2 pts each (max -10)
125
+
126
+ Sites in the [HSTS Preload List](https://hstspreload.org/) receive automatic A+ since browsers enforce HTTPS at the protocol level.
127
+
128
+ ## Sample Output
129
+
130
+ ```
131
+ [+] Target: https://twitter.com
132
+ [+] Status Code: 200
133
+
134
+ ============================================================
135
+ [+] SECURITY GRADE
136
+ ============================================================
137
+
138
+ Grade: A+ (Browser Trusted)
139
+
140
+ ★ This site is in the HSTS Preload List (twitter.com)
141
+ ★ HSTS is built into all major browsers (Chrome, Firefox, Safari, Edge)
142
+ ★ Browsers will ALWAYS use HTTPS for this site, even on first visit
143
+ ★ Header analysis is not needed - browser-level trust is the gold standard
144
+ ```
145
+
146
+ ## Requirements
147
+
148
+ - Python 3.8+
149
+ - `requests>=2.28.0` (listed in `requirements.txt` and `pyproject.toml`)
150
+
151
+ ## License
152
+
153
+ MIT
@@ -0,0 +1,121 @@
1
+ # Header-analyzer
2
+
3
+ A Python CLI tool for analyzing HTTP security headers. Scans target URLs, evaluates security posture, and provides a letter grade with detailed breakdown.
4
+
5
+ ## Features
6
+
7
+ - **Security Header Analysis** – Checks for HSTS, CSP, X-Frame-Options, X-Content-Type-Options, and more
8
+ - **Security Grading** – Letter grade (A+ to F) based on header configuration
9
+ - **HSTS Preload Detection** – Sites on browser preload lists get automatic A+ rating
10
+ - **Sensitive Header Detection** – Flags headers that may leak server/stack details
11
+ - **Flexible Requests** – Custom headers, User-Agent override, timeout, and SSL bypass options
12
+
13
+ ## Installation
14
+
15
+ ### Via pip (recommended)
16
+
17
+ ```bash
18
+ pip install git+https://github.com/negoro26/Header-analyzer.git
19
+ ```
20
+
21
+ This installs the `header-analyzer` command globally (or in your active virtual environment).
22
+
23
+ ### Development install (editable)
24
+
25
+ ```bash
26
+ git clone https://github.com/negoro26/Header-analyzer.git
27
+ cd Header-analyzer
28
+
29
+ # Windows
30
+ py -3 -m venv .venv && .\.venv\Scripts\Activate.ps1
31
+
32
+ # macOS/Linux
33
+ python3 -m venv .venv && source .venv/bin/activate
34
+
35
+ pip install -e .
36
+ ```
37
+
38
+ ## Usage
39
+
40
+ ```bash
41
+ header-analyzer <url> [options]
42
+ ```
43
+
44
+ ### Options
45
+
46
+ | Flag | Description |
47
+ |------|-------------|
48
+ | `-k, --insecure` | Skip SSL certificate verification |
49
+ | `--timeout <int>` | Request timeout in seconds (default: 10) |
50
+ | `--user-agent <string>` | Override User-Agent header |
51
+ | `-H, --header "Key: Value"` | Add custom request header (repeatable) |
52
+ | `--no-default-headers` | Start with empty header set |
53
+ | `--json` | Output headers as prettified JSON |
54
+
55
+ ### Examples
56
+
57
+ ```bash
58
+ # Basic scan
59
+ header-analyzer example.com
60
+
61
+ # Skip SSL verification with shorter timeout
62
+ header-analyzer https://example.com -k --timeout 5
63
+
64
+ # Custom headers
65
+ header-analyzer https://example.com --user-agent "MyScanner/1.0" \
66
+ -H "Accept-Language: en-US"
67
+ ```
68
+
69
+ ## Grading System
70
+
71
+ Sites are graded based on security header presence and configuration:
72
+
73
+ | Grade | Score | Description |
74
+ |-------|-------|-------------|
75
+ | A+ | — | Browser Trusted (HSTS preloaded) |
76
+ | A+ | 90%+ | Excellent |
77
+ | A | 75%+ | Very Good |
78
+ | B | 60%+ | Good |
79
+ | C | 45%+ | Acceptable |
80
+ | D | 30%+ | Poor |
81
+ | F | <30% | Critical |
82
+
83
+ ### Scoring Breakdown
84
+
85
+ - **HTTPS Baseline**: +25 pts
86
+ - **Strict-Transport-Security**: +25 pts
87
+ - **Content-Security-Policy**: +20 pts
88
+ - **X-Content-Type-Options**: +10 pts
89
+ - **X-Frame-Options**: +10 pts
90
+ - **Referrer-Policy**: +5 pts
91
+ - **Permissions-Policy**: +5 pts
92
+ - **Sensitive headers exposed**: -2 pts each (max -10)
93
+
94
+ Sites in the [HSTS Preload List](https://hstspreload.org/) receive automatic A+ since browsers enforce HTTPS at the protocol level.
95
+
96
+ ## Sample Output
97
+
98
+ ```
99
+ [+] Target: https://twitter.com
100
+ [+] Status Code: 200
101
+
102
+ ============================================================
103
+ [+] SECURITY GRADE
104
+ ============================================================
105
+
106
+ Grade: A+ (Browser Trusted)
107
+
108
+ ★ This site is in the HSTS Preload List (twitter.com)
109
+ ★ HSTS is built into all major browsers (Chrome, Firefox, Safari, Edge)
110
+ ★ Browsers will ALWAYS use HTTPS for this site, even on first visit
111
+ ★ Header analysis is not needed - browser-level trust is the gold standard
112
+ ```
113
+
114
+ ## Requirements
115
+
116
+ - Python 3.8+
117
+ - `requests>=2.28.0` (listed in `requirements.txt` and `pyproject.toml`)
118
+
119
+ ## License
120
+
121
+ MIT
@@ -0,0 +1,153 @@
1
+ Metadata-Version: 2.4
2
+ Name: header-analyzer
3
+ Version: 1.0.0
4
+ Summary: A CLI tool for analyzing HTTP security headers
5
+ Author: negoro26
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/negoro26/Header-analyzer
8
+ Project-URL: Repository, https://github.com/negoro26/Header-analyzer.git
9
+ Project-URL: Issues, https://github.com/negoro26/Header-analyzer/issues
10
+ Keywords: security,http,headers,infosec,cli,hsts
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Environment :: Console
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Intended Audience :: Information Technology
15
+ Classifier: Intended Audience :: System Administrators
16
+ Classifier: License :: OSI Approved :: MIT License
17
+ Classifier: Operating System :: OS Independent
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3.8
20
+ Classifier: Programming Language :: Python :: 3.9
21
+ Classifier: Programming Language :: Python :: 3.10
22
+ Classifier: Programming Language :: Python :: 3.11
23
+ Classifier: Programming Language :: Python :: 3.12
24
+ Classifier: Topic :: Security
25
+ Classifier: Topic :: Internet :: WWW/HTTP
26
+ Classifier: Topic :: Utilities
27
+ Requires-Python: >=3.8
28
+ Description-Content-Type: text/markdown
29
+ License-File: LICENSE
30
+ Requires-Dist: requests>=2.28.0
31
+ Dynamic: license-file
32
+
33
+ # Header-analyzer
34
+
35
+ A Python CLI tool for analyzing HTTP security headers. Scans target URLs, evaluates security posture, and provides a letter grade with detailed breakdown.
36
+
37
+ ## Features
38
+
39
+ - **Security Header Analysis** – Checks for HSTS, CSP, X-Frame-Options, X-Content-Type-Options, and more
40
+ - **Security Grading** – Letter grade (A+ to F) based on header configuration
41
+ - **HSTS Preload Detection** – Sites on browser preload lists get automatic A+ rating
42
+ - **Sensitive Header Detection** – Flags headers that may leak server/stack details
43
+ - **Flexible Requests** – Custom headers, User-Agent override, timeout, and SSL bypass options
44
+
45
+ ## Installation
46
+
47
+ ### Via pip (recommended)
48
+
49
+ ```bash
50
+ pip install git+https://github.com/negoro26/Header-analyzer.git
51
+ ```
52
+
53
+ This installs the `header-analyzer` command globally (or in your active virtual environment).
54
+
55
+ ### Development install (editable)
56
+
57
+ ```bash
58
+ git clone https://github.com/negoro26/Header-analyzer.git
59
+ cd Header-analyzer
60
+
61
+ # Windows
62
+ py -3 -m venv .venv && .\.venv\Scripts\Activate.ps1
63
+
64
+ # macOS/Linux
65
+ python3 -m venv .venv && source .venv/bin/activate
66
+
67
+ pip install -e .
68
+ ```
69
+
70
+ ## Usage
71
+
72
+ ```bash
73
+ header-analyzer <url> [options]
74
+ ```
75
+
76
+ ### Options
77
+
78
+ | Flag | Description |
79
+ |------|-------------|
80
+ | `-k, --insecure` | Skip SSL certificate verification |
81
+ | `--timeout <int>` | Request timeout in seconds (default: 10) |
82
+ | `--user-agent <string>` | Override User-Agent header |
83
+ | `-H, --header "Key: Value"` | Add custom request header (repeatable) |
84
+ | `--no-default-headers` | Start with empty header set |
85
+ | `--json` | Output headers as prettified JSON |
86
+
87
+ ### Examples
88
+
89
+ ```bash
90
+ # Basic scan
91
+ header-analyzer example.com
92
+
93
+ # Skip SSL verification with shorter timeout
94
+ header-analyzer https://example.com -k --timeout 5
95
+
96
+ # Custom headers
97
+ header-analyzer https://example.com --user-agent "MyScanner/1.0" \
98
+ -H "Accept-Language: en-US"
99
+ ```
100
+
101
+ ## Grading System
102
+
103
+ Sites are graded based on security header presence and configuration:
104
+
105
+ | Grade | Score | Description |
106
+ |-------|-------|-------------|
107
+ | A+ | — | Browser Trusted (HSTS preloaded) |
108
+ | A+ | 90%+ | Excellent |
109
+ | A | 75%+ | Very Good |
110
+ | B | 60%+ | Good |
111
+ | C | 45%+ | Acceptable |
112
+ | D | 30%+ | Poor |
113
+ | F | <30% | Critical |
114
+
115
+ ### Scoring Breakdown
116
+
117
+ - **HTTPS Baseline**: +25 pts
118
+ - **Strict-Transport-Security**: +25 pts
119
+ - **Content-Security-Policy**: +20 pts
120
+ - **X-Content-Type-Options**: +10 pts
121
+ - **X-Frame-Options**: +10 pts
122
+ - **Referrer-Policy**: +5 pts
123
+ - **Permissions-Policy**: +5 pts
124
+ - **Sensitive headers exposed**: -2 pts each (max -10)
125
+
126
+ Sites in the [HSTS Preload List](https://hstspreload.org/) receive automatic A+ since browsers enforce HTTPS at the protocol level.
127
+
128
+ ## Sample Output
129
+
130
+ ```
131
+ [+] Target: https://twitter.com
132
+ [+] Status Code: 200
133
+
134
+ ============================================================
135
+ [+] SECURITY GRADE
136
+ ============================================================
137
+
138
+ Grade: A+ (Browser Trusted)
139
+
140
+ ★ This site is in the HSTS Preload List (twitter.com)
141
+ ★ HSTS is built into all major browsers (Chrome, Firefox, Safari, Edge)
142
+ ★ Browsers will ALWAYS use HTTPS for this site, even on first visit
143
+ ★ Header analysis is not needed - browser-level trust is the gold standard
144
+ ```
145
+
146
+ ## Requirements
147
+
148
+ - Python 3.8+
149
+ - `requests>=2.28.0` (listed in `requirements.txt` and `pyproject.toml`)
150
+
151
+ ## License
152
+
153
+ MIT
@@ -0,0 +1,10 @@
1
+ LICENSE
2
+ README.md
3
+ header_scanner.py
4
+ pyproject.toml
5
+ header_analyzer.egg-info/PKG-INFO
6
+ header_analyzer.egg-info/SOURCES.txt
7
+ header_analyzer.egg-info/dependency_links.txt
8
+ header_analyzer.egg-info/entry_points.txt
9
+ header_analyzer.egg-info/requires.txt
10
+ header_analyzer.egg-info/top_level.txt
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ header-analyzer = header_scanner:main
@@ -0,0 +1 @@
1
+ requests>=2.28.0
@@ -0,0 +1 @@
1
+ header_scanner
@@ -0,0 +1,525 @@
1
+ import sys
2
+ import requests
3
+ import argparse
4
+ import json
5
+ from urllib.parse import urlparse
6
+
7
+
8
+ class HeaderScanner:
9
+ DEFAULT_CLIENT_HEADERS = {
10
+ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0",
11
+ "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
12
+ "Accept-Language": "en-US,en;q=0.5",
13
+ "Upgrade-Insecure-Requests": "1",
14
+ }
15
+
16
+ SECURITY_HEADERS = {
17
+ "Strict-Transport-Security": "Enforces HTTPS (HSTS)",
18
+ "Content-Security-Policy": "Mitigates XSS and data injection",
19
+ "X-Content-Type-Options": 'Prevents MIME sniffing (should be "nosniff")',
20
+ "X-Frame-Options": 'Prevents clickjacking (should be "DENY" or "SAMEORIGIN")',
21
+ "X-XSS-Protection": "Legacy XSS protection (modern browsers ignore)",
22
+ "Referrer-Policy": "Controls referrer information",
23
+ "Permissions-Policy": "Controls browser feature access",
24
+ }
25
+
26
+ SENSITIVE_HEADERS = [
27
+ "Server",
28
+ "X-Powered-By",
29
+ "X-AspNet-Version",
30
+ "X-AspNetMvc-Version",
31
+ "X-Runtime",
32
+ "X-Version",
33
+ ]
34
+
35
+ # Grading system configuration
36
+ # Baseline points for using HTTPS (awarded automatically if URL is https)
37
+ HTTPS_BASELINE = 25
38
+ # HSTS preload API
39
+ HSTS_PRELOAD_API = "https://hstspreload.org/api/v2/status"
40
+
41
+ HEADER_WEIGHTS = {
42
+ "Strict-Transport-Security": 25, # Critical - enforces HTTPS
43
+ "Content-Security-Policy": 20, # Critical - XSS/injection protection
44
+ "X-Content-Type-Options": 10, # Important - MIME sniffing
45
+ "X-Frame-Options": 10, # Important - clickjacking
46
+ "Referrer-Policy": 5, # Moderate - privacy
47
+ "Permissions-Policy": 5, # Moderate - feature access
48
+ "X-XSS-Protection": 0, # Deprecated - browsers ignore this
49
+ }
50
+
51
+ EXPECTED_VALUES = {
52
+ "X-Content-Type-Options": lambda v: v.lower() == "nosniff",
53
+ "X-Frame-Options": lambda v: v.upper() in ("DENY", "SAMEORIGIN"),
54
+ "Referrer-Policy": lambda v: v.lower()
55
+ in (
56
+ "no-referrer",
57
+ "no-referrer-when-downgrade",
58
+ "origin",
59
+ "origin-when-cross-origin",
60
+ "same-origin",
61
+ "strict-origin",
62
+ "strict-origin-when-cross-origin",
63
+ ),
64
+ }
65
+
66
+ # Reduced penalty - Server header is common and low-risk
67
+ SENSITIVE_PENALTY = 2 # Points deducted per sensitive header exposed
68
+
69
+ GRADE_THRESHOLDS = [
70
+ (90, "A+", "Excellent"),
71
+ (75, "A", "Very Good"),
72
+ (60, "B", "Good"),
73
+ (45, "C", "Acceptable"),
74
+ (30, "D", "Poor"),
75
+ (0, "F", "Critical"),
76
+ ]
77
+
78
+ def __init__(self, url, args):
79
+ self.args = args
80
+ self.url = self._validate_url(url)
81
+ self.headers = self._build_client_headers()
82
+ self.response = None
83
+ self._hsts_preload_status = None # Cached result
84
+
85
+ def _validate_url(self, url):
86
+ if not url.startswith(("http://", "https://")):
87
+ url = f"https://{url}"
88
+ return url
89
+
90
+ def _build_client_headers(self):
91
+ if self.args.no_default_headers:
92
+ headers = {}
93
+ else:
94
+ headers = dict(self.DEFAULT_CLIENT_HEADERS)
95
+
96
+ if getattr(self.args, "user_agent", None):
97
+ headers["User-Agent"] = self.args.user_agent
98
+
99
+ for item in getattr(self.args, "header", []) or []:
100
+ if ":" not in item:
101
+ print(
102
+ f"[!] Ignoring invalid header (expected 'Key: Value'): {item}",
103
+ file=sys.stderr,
104
+ )
105
+ continue
106
+ key, value = item.split(":", 1)
107
+ key = key.strip()
108
+ value = value.strip()
109
+ if not key:
110
+ print(f"[!] Ignoring header with empty key: {item}", file=sys.stderr)
111
+ continue
112
+ headers[key] = value
113
+ return headers
114
+
115
+ def _extract_domain(self, url):
116
+ """Extract the registrable domain from a URL."""
117
+ parsed = urlparse(url)
118
+ hostname = parsed.netloc or parsed.path
119
+ # Remove port if present
120
+ hostname = hostname.split(":")[0]
121
+ # Get the main domain (e.g., www.google.com -> google.com)
122
+ parts = hostname.split(".")
123
+ if len(parts) >= 2:
124
+ return ".".join(parts[-2:])
125
+ return hostname
126
+
127
+ def check_hsts_preload(self):
128
+ """Check if domain is in browser HSTS preload list.
129
+
130
+ Checks both the original requested domain and the final redirected domain,
131
+ since sites like twitter.com may redirect to x.com but still be preloaded.
132
+ """
133
+ if self._hsts_preload_status is not None:
134
+ return self._hsts_preload_status
135
+
136
+ # Check both original domain and final domain (after redirects)
137
+ original_domain = self._extract_domain(self.url)
138
+ final_domain = (
139
+ self._extract_domain(self.response.url)
140
+ if self.response
141
+ else original_domain
142
+ )
143
+
144
+ domains_to_check = [original_domain]
145
+ if final_domain != original_domain:
146
+ domains_to_check.append(final_domain)
147
+
148
+ for domain in domains_to_check:
149
+ try:
150
+ resp = requests.get(
151
+ self.HSTS_PRELOAD_API, params={"domain": domain}, timeout=5
152
+ )
153
+ if resp.ok:
154
+ data = resp.json()
155
+ status = data.get("status", "")
156
+ if status == "preloaded":
157
+ self._hsts_preload_status = {
158
+ "domain": domain,
159
+ "preloaded": True,
160
+ "status": status,
161
+ }
162
+ return self._hsts_preload_status
163
+ except requests.exceptions.RequestException:
164
+ continue
165
+
166
+ # Neither domain is preloaded
167
+ self._hsts_preload_status = {
168
+ "domain": original_domain,
169
+ "preloaded": False,
170
+ "status": "unknown",
171
+ }
172
+ return self._hsts_preload_status
173
+
174
+ def make_request(self):
175
+ timeout = self.args.timeout
176
+ insecure = self.args.insecure
177
+
178
+ try:
179
+ response = requests.head(
180
+ self.url,
181
+ headers=self.headers,
182
+ timeout=timeout,
183
+ verify=not insecure,
184
+ allow_redirects=True,
185
+ )
186
+ if not response.ok:
187
+ raise requests.exceptions.RequestException(
188
+ f"HEAD not OK: {response.status_code}"
189
+ )
190
+ self.response = response
191
+ return response
192
+ except (requests.exceptions.RequestException, requests.exceptions.HTTPError):
193
+ try:
194
+ response = requests.get(
195
+ self.url,
196
+ headers=self.headers,
197
+ timeout=timeout,
198
+ verify=not insecure,
199
+ allow_redirects=True,
200
+ )
201
+ self.response = response
202
+ return response
203
+ except requests.exceptions.RequestException:
204
+ raise
205
+
206
+ def analyze_security_headers(self):
207
+ print("\n" + "=" * 60)
208
+ print("[+] Analyzing security headers...")
209
+ print("=" * 60)
210
+
211
+ present = []
212
+ missing = []
213
+ headers = self.response.headers
214
+
215
+ for header, description in self.SECURITY_HEADERS.items():
216
+ if header in headers:
217
+ present.append((header, headers[header]))
218
+ else:
219
+ missing.append((header, description))
220
+
221
+ if present:
222
+ print("Security headers present:")
223
+ for header, value in present:
224
+ if header == "X-Content-Type-Options" and value.lower() != "nosniff":
225
+ print(f" • {header} → {value} (should be 'nosniff')")
226
+ elif header == "X-Frame-Options" and value.upper() not in (
227
+ "DENY",
228
+ "SAMEORIGIN",
229
+ ):
230
+ print(f" • {header} → {value} (should be 'DENY' or 'SAMEORIGIN')")
231
+ else:
232
+ print(f" • {header} → {value}")
233
+ else:
234
+ print("All security headers missing")
235
+
236
+ if missing:
237
+ print("Security headers missing:")
238
+ for header, description in missing:
239
+ print(f" • {header} → {description}")
240
+ else:
241
+ print("All security headers present")
242
+
243
+ def analyze_sensitive_headers(self):
244
+ print("\n" + "=" * 60)
245
+ print("[+] Analyzing sensitive headers...")
246
+ print("=" * 60)
247
+
248
+ found = []
249
+ headers = self.response.headers
250
+ for header in self.SENSITIVE_HEADERS:
251
+ if header in headers:
252
+ found.append((header, headers[header]))
253
+
254
+ if found:
255
+ print("Potentially sensitive headers found:")
256
+ for header, value in found:
257
+ print(f" • {header}: {value}")
258
+ print("These headers might reveal technology, version or framework details")
259
+ else:
260
+ print("[+] No sensitive headers present")
261
+
262
+ def calculate_grade(self):
263
+ """Calculate security grade based on headers analysis."""
264
+ headers = self.response.headers
265
+
266
+ # Calculate total possible (HTTPS baseline + header weights, excluding 0-weight headers)
267
+ header_points_possible = sum(w for w in self.HEADER_WEIGHTS.values() if w > 0)
268
+ total_possible = self.HTTPS_BASELINE + header_points_possible
269
+
270
+ score_details = {
271
+ "header_scores": [],
272
+ "value_bonuses": [],
273
+ "penalties": [],
274
+ "https_baseline": 0,
275
+ "total_possible": total_possible,
276
+ }
277
+
278
+ earned_points = 0
279
+
280
+ # Baseline points for HTTPS
281
+ if self.response.url.startswith("https://"):
282
+ earned_points += self.HTTPS_BASELINE
283
+ score_details["https_baseline"] = self.HTTPS_BASELINE
284
+
285
+ # Check if site is HSTS preloaded - if so, automatic A+ (browser already trusts it)
286
+ hsts_preload = self.check_hsts_preload()
287
+ if hsts_preload.get("preloaded"):
288
+ return {
289
+ "score": 100,
290
+ "max_score": 100,
291
+ "percentage": 100,
292
+ "grade": "A+",
293
+ "description": "Browser Trusted",
294
+ "hsts_preloaded": True,
295
+ "hsts_domain": hsts_preload["domain"],
296
+ "details": None,
297
+ }
298
+
299
+ # Score for security headers present and their values
300
+ for header, weight in self.HEADER_WEIGHTS.items():
301
+ if weight == 0: # Skip deprecated headers with 0 weight
302
+ continue
303
+ if header in headers:
304
+ value = headers[header]
305
+ earned_points += weight
306
+ score_details["header_scores"].append((header, weight, True))
307
+
308
+ # Check for correct value (bonus: no deduction)
309
+ if header in self.EXPECTED_VALUES:
310
+ validator = self.EXPECTED_VALUES[header]
311
+ if validator(value):
312
+ score_details["value_bonuses"].append((header, "correct"))
313
+ else:
314
+ # Partial credit - header present but misconfigured
315
+ penalty = weight // 4 # Reduced penalty for misconfiguration
316
+ earned_points -= penalty
317
+ score_details["value_bonuses"].append(
318
+ (header, f"misconfigured (-{penalty})")
319
+ )
320
+ else:
321
+ score_details["header_scores"].append((header, weight, False))
322
+
323
+ # Penalty for sensitive headers exposed (capped to avoid crushing the score)
324
+ sensitive_count = 0
325
+ for header in self.SENSITIVE_HEADERS:
326
+ if header in headers:
327
+ sensitive_count += 1
328
+ score_details["penalties"].append((header, self.SENSITIVE_PENALTY))
329
+
330
+ total_penalty = min(
331
+ sensitive_count * self.SENSITIVE_PENALTY, 10
332
+ ) # Cap at 10 pts
333
+ earned_points = max(0, earned_points - total_penalty)
334
+
335
+ # Calculate percentage
336
+ percentage = (earned_points / total_possible) * 100
337
+ percentage = min(100, max(0, percentage)) # Clamp to 0-100
338
+
339
+ # Determine letter grade
340
+ grade = "F"
341
+ description = "Critical"
342
+ for threshold, letter, desc in self.GRADE_THRESHOLDS:
343
+ if percentage >= threshold:
344
+ grade = letter
345
+ description = desc
346
+ break
347
+
348
+ return {
349
+ "score": round(earned_points, 1),
350
+ "max_score": score_details["total_possible"],
351
+ "percentage": round(percentage, 1),
352
+ "grade": grade,
353
+ "description": description,
354
+ "details": score_details,
355
+ }
356
+
357
+ def display_grade(self):
358
+ """Display the security grade with breakdown."""
359
+ result = self.calculate_grade()
360
+
361
+ print("\n" + "=" * 60)
362
+ print("[+] SECURITY GRADE")
363
+ print("=" * 60)
364
+
365
+ # Special case: HSTS preloaded sites
366
+ if result.get("hsts_preloaded"):
367
+ print(f"\n Grade: {result['grade']} ({result['description']})")
368
+ print(
369
+ f"\n ★ This site is in the HSTS Preload List ({result['hsts_domain']})"
370
+ )
371
+ print(
372
+ " ★ HSTS is built into all major browsers (Chrome, Firefox, Safari, Edge)"
373
+ )
374
+ print(
375
+ " ★ Browsers will ALWAYS use HTTPS for this site, even on first visit"
376
+ )
377
+ print(
378
+ " ★ Header analysis is not needed - browser-level trust is the gold standard"
379
+ )
380
+ return result
381
+
382
+ # Normal grading display
383
+ grade_bar = self._create_grade_bar(result["percentage"])
384
+ print(f"\n Grade: {result['grade']} ({result['description']})")
385
+ print(
386
+ f" Score: {result['score']}/{result['max_score']} ({result['percentage']}%)"
387
+ )
388
+ print(f" {grade_bar}")
389
+
390
+ # Breakdown
391
+ details = result["details"]
392
+
393
+ # Show HTTPS baseline if earned
394
+ if details.get("https_baseline", 0) > 0:
395
+ print(f"\n HTTPS Baseline: +{details['https_baseline']} pts")
396
+
397
+ print("\n Header Scores:")
398
+ for header, weight, present in details["header_scores"]:
399
+ status = "✓" if present else "✗"
400
+ points = f"+{weight}" if present else f" 0"
401
+ print(f" {status} {header}: {points} pts")
402
+
403
+ if details["value_bonuses"]:
404
+ print("\n Value Validation:")
405
+ for header, status in details["value_bonuses"]:
406
+ icon = "✓" if status == "correct" else "⚠"
407
+ print(f" {icon} {header}: {status}")
408
+
409
+ if details["penalties"]:
410
+ print("\n Penalties (Sensitive Headers Exposed):")
411
+ for header, penalty in details["penalties"]:
412
+ print(f" ✗ {header}: -{penalty} pts")
413
+
414
+ return result
415
+
416
+ def _create_grade_bar(self, percentage):
417
+ """Create a visual progress bar for the grade."""
418
+ bar_length = 30
419
+ filled = int(bar_length * percentage / 100)
420
+ empty = bar_length - filled
421
+
422
+ # Color coding based on percentage
423
+ if percentage >= 80:
424
+ fill_char = "█"
425
+ elif percentage >= 60:
426
+ fill_char = "▓"
427
+ elif percentage >= 40:
428
+ fill_char = "▒"
429
+ else:
430
+ fill_char = "░"
431
+
432
+ bar = fill_char * filled + "░" * empty
433
+ return f" [{bar}]"
434
+
435
+ def print_headers(self, as_json=False):
436
+ if as_json:
437
+ print("\n" + "=" * 60)
438
+ print("[+] RAW RESPONSE HEADERS (AS JSON)")
439
+ print("=" * 60)
440
+
441
+ headers_dict = dict(self.response.headers)
442
+ print(json.dumps(headers_dict, indent=4, sort_keys=True))
443
+ else:
444
+ print("\n" + "=" * 60)
445
+ print("[+] RAW RESPONSE HEADERS")
446
+ print("=" * 60)
447
+ for key, value in self.response.headers.items():
448
+ print(f"{key}: {value}")
449
+
450
+ def scan(self):
451
+ self.make_request()
452
+
453
+ print(f"[+] Target: {self.url}")
454
+ print(f"[+] Status Code: {self.response.status_code}")
455
+ if self.response.history:
456
+ print(f"[+] Redirected {len(self.response.history)} times")
457
+ print(f" Final URL: {self.response.url}")
458
+
459
+ self.print_headers(as_json=self.args.json)
460
+ self.analyze_security_headers()
461
+ self.analyze_sensitive_headers()
462
+ self.display_grade()
463
+
464
+ print("\n" + "=" * 60)
465
+ print("[+] Scan completed successfully!")
466
+ print("=" * 60)
467
+
468
+
469
+ def main():
470
+ parser = argparse.ArgumentParser(
471
+ formatter_class=argparse.RawTextHelpFormatter,
472
+ description="HTTP Header Security Analyzer",
473
+ )
474
+ parser.add_argument("url", help="Target URL to scan")
475
+ parser.add_argument(
476
+ "--insecure",
477
+ "-k",
478
+ action="store_true",
479
+ help="Skip SSL certificate verification",
480
+ )
481
+ parser.add_argument(
482
+ "--timeout",
483
+ type=int,
484
+ default=10,
485
+ help="Request timeout in seconds (default: 10)",
486
+ )
487
+ parser.add_argument(
488
+ "--user-agent", dest="user_agent", help="Override User-Agent header"
489
+ )
490
+ parser.add_argument(
491
+ "--header",
492
+ "-H",
493
+ action="append",
494
+ default=[],
495
+ help='Custom request header, e.g., -H "Key: Value". Repeat to add multiple.',
496
+ )
497
+ parser.add_argument(
498
+ "--no-default-headers",
499
+ action="store_true",
500
+ help="Do not include built-in client headers (start from empty set)",
501
+ )
502
+ parser.add_argument("--json", action="store_true", help="Output results as JSON")
503
+
504
+ args = parser.parse_args()
505
+
506
+ try:
507
+ scanner = HeaderScanner(args.url.strip(), args)
508
+ scanner.scan()
509
+ except KeyboardInterrupt:
510
+ sys.exit("\n[!] Scan interrupted by user")
511
+ except requests.exceptions.RequestException as e:
512
+ if isinstance(e, requests.exceptions.SSLError):
513
+ sys.exit(
514
+ f"[!] SSL Error: {e}\n Use --insecure to bypass certificate validation"
515
+ )
516
+ elif isinstance(e, requests.exceptions.Timeout):
517
+ sys.exit(f"[!] Request timed out after {args.timeout} seconds")
518
+ elif isinstance(e, requests.exceptions.ConnectionError):
519
+ sys.exit("[!] Failed to connect to the server")
520
+ else:
521
+ sys.exit(f"[!] Request failed: {e}")
522
+
523
+
524
+ if __name__ == "__main__":
525
+ main()
@@ -0,0 +1,47 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "header-analyzer"
7
+ version = "1.0.0"
8
+ description = "A CLI tool for analyzing HTTP security headers"
9
+ readme = "README.md"
10
+ license = { text = "MIT" }
11
+ requires-python = ">=3.8"
12
+ dependencies = [
13
+ "requests>=2.28.0",
14
+ ]
15
+ keywords = ["security", "http", "headers", "infosec", "cli", "hsts"]
16
+ authors = [
17
+ { name = "negoro26" },
18
+ ]
19
+ classifiers = [
20
+ "Development Status :: 4 - Beta",
21
+ "Environment :: Console",
22
+ "Intended Audience :: Developers",
23
+ "Intended Audience :: Information Technology",
24
+ "Intended Audience :: System Administrators",
25
+ "License :: OSI Approved :: MIT License",
26
+ "Operating System :: OS Independent",
27
+ "Programming Language :: Python :: 3",
28
+ "Programming Language :: Python :: 3.8",
29
+ "Programming Language :: Python :: 3.9",
30
+ "Programming Language :: Python :: 3.10",
31
+ "Programming Language :: Python :: 3.11",
32
+ "Programming Language :: Python :: 3.12",
33
+ "Topic :: Security",
34
+ "Topic :: Internet :: WWW/HTTP",
35
+ "Topic :: Utilities",
36
+ ]
37
+
38
+ [project.urls]
39
+ Homepage = "https://github.com/negoro26/Header-analyzer"
40
+ Repository = "https://github.com/negoro26/Header-analyzer.git"
41
+ Issues = "https://github.com/negoro26/Header-analyzer/issues"
42
+
43
+ [project.scripts]
44
+ header-analyzer = "header_scanner:main"
45
+
46
+ [tool.setuptools]
47
+ py-modules = ["header_scanner"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+