Ensuring website security is a top priority in our increasingly digital world. Security headers play a crucial role in protecting websites from various threats, such as cross-site scripting (XSS) and clickjacking. They act as guidelines for web browsers, dictating how they should handle interactions with your site. Understanding these headers and how to implement them can make a significant difference in safeguarding user data and maintaining the integrity of your website.
Today, you’ll learn how to check website security headers using Python. This tutorial will guide you through building a Python application with a Tkinter GUI to analyze security headers like Content-Security-Policy, X-Frame-Options, and Strict-Transport-Security. We’ll cover how to identify missing or misconfigured headers and provide recommendations to improve your site’s security. By the end of this tutorial, you’ll have a practical tool to help enhance your website’s security posture. Let’s get started!
Table of Contents
- Disclaimer
- Necessary Libraries
- Imports
- Understanding Security Headers
- Checking Security Headers
- Analyzing Headers Function
- Displaying Results
- Highlighting Status Function
- Saving Results as CSV
- Parsing and Writing Results Function
- Show Help Function
- Main Tkinter Application
- Example
- Full Code
Disclaimer
Please note: This tool is intended for educational purposes only. Use it responsibly on websites you own or have permission to test. The developers are not liable for any misuse or resulting issues.
Necessary Libraries
For the code to function properly, Install these libraries by running the following commands:
$ pip install tk
$ pip install requests
Imports
import tkinter as tk
from tkinter import ttk, messagebox, scrolledtext, filedialog
import requests
import csv
Before diving into today’s challenge, let’s get our toolkit ready. Here’s what we’ll be working with:
- First up,
tkinter
: This nifty library helps us create a graphical user interface (GUI) that looks great and functions smoothly. We’ll usettk
for themed widgets, display messages in handy little message boxes, and usescrolledtext
to make text widgets scrollable. Plus,filedialog
will allow users to save files with ease. - Next,
requests
: This powerful library is our go-to for interacting with the web. Whether we’re sending GET requests to fetch data, POST requests to submit data, or even PUT and DELETE requests to update or remove resources,requests
has us covered. - Finally,
csv
: This module is used to read from and write to CSV files, allowing us to organize data like a pro.
Understanding Security Headers
With our tools assembled, it’s time to introduce the heroes that help secure our web applications and ensure safe interactions with users. Let’s get to know these guardians of security, presented in our SECURITY_HEADERS_INFO
dictionary:
- Strict-Transport-Security (HSTS): This header ensures that every interaction with the server happens through HTTPS. It’s like a security blanket for your data, keeping everything safe from prying eyes.
- Content-Security-Policy (CSP): Think of CSP as a gatekeeper that only lets in the content you trust. It shields your site from code injection attacks and cross-site scripting (XSS) by specifying which content is allowed to load.
- X-Content-Type-Options: This header makes sure browsers don’t play tricks by interpreting files as something they’re not. It stops MIME-type confusion, ensuring files are handled as intended.
- X-Frame-Options: No one likes an uninvited guest, and this header makes sure your site can’t be embedded in iframes on other pages. This prevents sneaky clickjacking attacks.
- X-XSS-Protection: Built into modern browsers, this header acts like a bodyguard against cross-site scripting (XSS). It enables XSS filters to offer an extra layer of protection.
- Referrer-Policy: When users move from one page to another, this header manages what information gets shared. It’s all about protecting user privacy while browsing.
- Permissions-Policy: Think of this as your website’s control panel for deciding which features and APIs, like camera access, can be used. It’s a great way to enhance security and control user data.
- Expect-CT: Transparency is key, and this header ensures that SSL/TLS certificates are logged and monitored. It helps detect any unauthorized certificates and keeps everything above board.
# Security Headers Information
SECURITY_HEADERS_INFO = {
'Strict-Transport-Security': {
'description': 'Ensures HTTPS is used.',
'expected': 'max-age=63072000; includeSubDomains; preload',
'recommendation': 'Add Strict-Transport-Security to enforce HTTPS.',
'advice': 'This header is critical for enforcing HTTPS across your site. It helps prevent man-in-the-middle attacks.'
},
'Content-Security-Policy': {
'description': 'Prevents cross-site scripting attacks.',
'expected': None,
'recommendation': 'Add Content-Security-Policy to control resource loading.',
'advice': 'Implementing a strong CSP can significantly reduce XSS vulnerabilities by controlling resource loading.'
},
'X-Content-Type-Options': {
'description': 'Prevents MIME-type sniffing.',
'expected': 'nosniff',
'recommendation': 'Add X-Content-Type-Options with nosniff value.',
'advice': 'This header prevents browsers from interpreting files as something else, reducing the risk of malicious code execution.'
},
'X-Frame-Options': {
'description': 'Prevents clickjacking.',
'expected': 'DENY',
'recommendation': 'Add X-Frame-Options to prevent clickjacking.',
'advice': 'Clickjacking protection ensures your site is not embedded in iframes, avoiding potential clickjacking attacks.'
},
'X-XSS-Protection': {
'description': 'Enables XSS filtering.',
'expected': '1; mode=block',
'recommendation': 'Add X-XSS-Protection with mode=block.',
'advice': 'While modern browsers handle XSS well, this header can offer additional protection for older browsers.'
},
'Referrer-Policy': {
'description': 'Controls referrer information.',
'expected': 'no-referrer',
'recommendation': 'Add Referrer-Policy with no-referrer value.',
'advice': 'A strict referrer policy protects user privacy by minimizing the information shared with third parties.'
},
'Permissions-Policy': {
'description': 'Manages permissions like geolocation.',
'expected': None,
'recommendation': 'Add Permissions-Policy to control feature permissions.',
'advice': 'This policy helps you control which features and APIs your site can access, protecting user data.'
},
'Expect-CT': {
'description': 'Ensures valid certificate transparency.',
'expected': 'max-age=86400, enforce',
'recommendation': 'Add Expect-CT for certificate transparency.',
'advice': 'Using Expect-CT ensures that your site’s certificates are logged, helping to detect unauthorized certificates.'
}
}
Checking Security Headers
Now that we’ve introduced the security headers, let’s dive into how we can fetch and analyze them using our check_security_headers()
function. Here’s how it works:
- Getting the URLs: The function starts by grabbing the URLs you’ve entered in the input field using
url_entry.get()
. You can input multiple URLs by separating them with commas. The function splits these URLs usingsplit(',')
and removes any extra spaces withurl.strip()
.
urls = [url.strip() for url in url_entry.get().split(',') if url.strip()]
- Checking the URLs: Once the URLs are ready, the function checks to see if you’ve entered at least one valid URL. If not, it pops up a message box to let you know there’s an input error.
if not urls:
messagebox.showwarning("Input Error", "Please enter one valid URL at least.")
return
- Clearing Old Results: Before doing anything new, the function clears out any old text from the results display. This ensures that the next batch of results starts with a clean slate.
results_text.delete(1.0, tk.END)
- Fetching Headers: The function loops through each URL you’ve entered. For each one, it sends a GET request to fetch the headers from the website’s HTTP response.
for url in urls:
try:
response = requests.get(url, timeout=10)
headers = response.headers
- Analyzing Headers: With the headers in hand, the function passes them to
analyze_headers()
, which does the heavy lifting of analyzing the security headers. The results are then saved in a variable calledresults
.
results = analyze_headers(headers)
- Showing Results: After analyzing, the function calls
display_results()
to show you the findings for each URL. You’ll see what headers are present and any recommendations for improvement.
display_results(url, results)
- Handling Errors: If something goes wrong during this process, like a network issue, the function will display an error message to keep you informed.
except requests.RequestException as e:
messagebox.showerror("Request Error", f"Failed to reach {url}: {e}")
Analyzing Headers Function
Above, we discussed the importance of analyzing security headers. Now, let’s take a closer look at the analyze_headers()
function, which handles this critical task. This function is like a detective, meticulously going through each security header to determine if it meets the necessary standards and offers recommendations for improvements.
def analyze_headers(headers):
results = {}
The process begins by creating an empty dictionary called results
. This dictionary will store all the findings from our header analysis. The function then iterates over the headers defined in the SECURITY_HEADERS_INFO
dictionary, which serves as our guidebook for what we expect from each header.
for header, details in SECURITY_HEADERS_INFO.items():
actual_value = headers.get(header)
expected_value = details['expected']
For each header, the function retrieves its actual value from the HTTP response using headers.get()
. It also grabs the expected value from our SECURITY_HEADERS_INFO
dictionary. This step is crucial because it helps us determine if the header is present and whether it matches the expected value.
results[header] = {
'status': 'Present' if actual_value else 'Missing',
'actual_value': actual_value or 'None',
'match': actual_value == expected_value if expected_value else 'N/A',
Next, the function evaluates each header’s presence and value. It adds an entry for every evaluated header in the results
dictionary. This entry includes key details like whether the header is present or missing, its actual value, and a comparison to the expected value. It also provides a description of the header, along with recommendations and advice on how to address any issues.
'description': details['description'],
'recommendation': details['recommendation'] if actual_value != expected_value else None,
'advice': details['advice']
}
As the function continues, it fills the results
dictionary with a comprehensive analysis of each header. This analysis is vital for understanding how well the headers are protecting your website and what improvements might be needed. Lastly, the function returns the results
dictionary, providing valuable insights that can be used by the rest of the script.
return results
Displaying Results
Now that we’ve analyzed the headers, let’s move on to the exciting part—displaying the results! The display_results()
function does this beautifully by first inserting a heading to show that we’re analyzing the URL’s security headers.
It then dives into the results
dictionary and goes through each analyzed header, revealing important details like the actual value, description, whether the value matches what we expected, any recommendations, and some helpful advice. This is all achieved using results_text.insert()
.
To wrap it up, the function calls highlight_status()
to add a splash of color, making it easy to see which headers are present and which might need some attention.
def display_results(url, results):
results_text.insert(tk.END, f"Security Headers for {url}:\n\n")
for header, info in results.items():
results_text.insert(tk.END, f"Header: {header}\nStatus: {info['status']}\nActual Value: {info['actual_value']}\n")
results_text.insert(tk.END, f"Match Expected: {info['match']}\nDescription: {info['description']}\n")
if info['recommendation']:
results_text.insert(tk.END, f"Recommendation: {info['recommendation']}\n")
results_text.insert(tk.END, f"Advice: {info['advice']}\n" + "-" * 80 + "\n")
highlight_status(info['status'])
Highlighting Status Function
def highlight_status(status):
start_index, end_index = 'end-7l', 'end-1l'
tag, color = ('missing', 'red') if status == "Missing" else ('present', 'green')
results_text.tag_add(tag, start_index, end_index)
results_text.tag_config(tag, background=color, foreground='white')
To make our program visually appealing, we added a touch of color with the highlight_status()
function. This function starts by figuring out where to apply the highlight in the text area by determining the start and end indices. Then, it checks the status of each security header. If the header is present, it gives it a nice green highlight; if it’s missing, it gets a red highlight to catch your attention.
Once we’ve got the details sorted out, the function uses results_text.tag_add()
to apply the highlight to the right part of the text. We also use results_text.tag_config()
to set the background and foreground colors, making sure everything stands out just right. This way, you can quickly see which headers are good to go and which ones need some attention.
Saving Results as CSV
For those of you who love keeping track of your findings, our program has a nifty feature that lets you save your results in a CSV file. This is made possible by the save_results_csv()
function, which simplifies the process of organizing and preserving your data.
def save_results_csv():
results = results_text.get(1.0, tk.END).strip()
First things first, the function checks if there are any results to save. It does this by retrieving the text using results_text.get()
and stripping any whitespace or trailing characters with .strip()
. If the results are empty, it politely lets you know with a friendly warning message—after all, we don’t want you to accidentally save a blank file!
if not results:
messagebox.showwarning("Save Error", "No results to save.")
return
But if you’ve got results ready to go, the function will prompt you with a file dialog, giving you the freedom to choose where you’d like to save your CSV file and what you’d like to name it. It even takes care of adding a “.csv” extension for you, so you don’t have to worry about the format.
filename = filedialog.asksaveasfilename(defaultextension=".csv", filetypes=[("CSV files", "*.csv")])
Once you’ve selected a name and location, the function gets to work opening the file in writing mode with UTF-8 encoding. It uses csv.writer()
to jot down the header row, setting the stage for your data to be neatly organized.
if filename:
try:
with open(filename, 'w', newline='', encoding='utf-8') as csvfile:
csvwriter = csv.writer(csvfile)
csvwriter.writerow(['URL', 'Header', 'Status', 'Actual Value', 'Match Expected', 'Description', 'Recommendation', 'Advice'])
With everything set up, the function calls parse_and_write_results()
to transfer your analysis results into the CSV file. This ensures that all your hard-earned data is stored safely and ready for future reference.
parse_and_write_results(csvwriter, results)
And finally, when everything’s wrapped up, you’ll be greeted with a celebratory message box confirming that your results have been saved successfully. Of course, if anything goes awry during the process, the function will display an error message to keep you informed and troubleshoot any issues.
messagebox.showinfo("Success", "Results saved successfully as CSV")
except Exception as e:
messagebox.showerror("File Error", f"Failed to save the results: {e}")
Parsing and Writing Results Function
Previously, we mentioned the parse_and_write_results()
function but didn’t discuss how it works. Let’s fix that! This function is responsible for taking the text results and writing them into a CSV file.
The first step is to split the result text into individual lines. This is accomplished using the split()
method, which separates the text at each newline. We also initialize a variable called current_url
to keep track of the URL being processed.
def parse_and_write_results(csvwriter, results):
lines = results.split("\n")
current_url = ""
Next, the function iterates through each line in the split text. When it encounters a line that starts with “Security Headers for” it recognizes this as the beginning of a new URL. The URL is extracted from the line and stored in the current_url
variable.
for line in lines:
if line.startswith("Security Headers for"):
current_url = line.split(" ")[-1].strip(':')
When the function identifies a line starting with “Header:“, it knows that this line contains information about a specific security header. It then extracts various details, such as the header’s status, actual value, whether it matches the expected value, a description, any recommendations, and advice. Each of these values is parsed from the subsequent lines using indexing and string manipulation.
elif line.startswith("Header:"):
try:
header = line.split(": ")[1]
status = lines[lines.index(line) + 1].split(": ")[1]
actual_value = lines[lines.index(line) + 2].split(": ")[1]
match_expected = lines[lines.index(line) + 3].split(": ")[1]
description = lines[lines.index(line) + 4].split(": ")[1]
To handle the recommendations and advice sections, the function checks whether these lines exist. It does this by verifying if the “Recommendation:” string is present in the expected line, and if not, it adjusts the index accordingly. This ensures that the extraction process is robust, even if some headers lack specific sections.
# Check if the recommendation line is present
recommendation_line = lines[lines.index(line) + 5]
recommendation = recommendation_line.split(": ")[1] if "Recommendation:" in recommendation_line else ""
# Ensure advice line exists
advice_line = lines[lines.index(line) + 5] if not recommendation else lines[lines.index(line) + 6]
advice = advice_line.split(": ")[1] if "Advice:" in advice_line else ""
Once all relevant information is extracted, the function uses csvwriter.writerow()
to write the data into the CSV file. The information is neatly organized into a row format, starting with the current_url
and followed by the header details.
csvwriter.writerow([current_url, header, status, actual_value, match_expected, description, recommendation, advice])
If there is any missing information or an error occurs during the extraction process, the function handles it gracefully with an except
block. This catches IndexError
exceptions and prints an error message, allowing the function to continue processing subsequent headers without crashing.
except IndexError:
print(f"Error: Missing information for header {header}")
continue
Show Help Function
def show_help():
help_text = (
"Security Header Checker Help\n\n"
"1. Enter URLs: If you You Input one or more URLs Make Sure They are separated by commas.\n"
"2. Check Security Headers: Simply Click the button to analyze the security headers.\n"
"3. Save Results: Save the analysis results as CSV files.\n\n"
"Security Headers:\n"
"- Strict-Transport-Security: Enforces HTTPS.\n"
"- Content-Security-Policy: Controls resource loading.\n"
"- X-Content-Type-Options: Prevents MIME-type sniffing.\n"
"- X-Frame-Options: Prevents clickjacking.\n"
"- X-XSS-Protection: Enables XSS filtering.\n"
"- Referrer-Policy: Controls referrer information.\n"
"- Permissions-Policy: Manages permissions.\n"
"- Expect-CT: Ensures certificate transparency.\n\n"
"Advice:\n"
"For each header, Please follow the given advice to improve The security settings.\n"
"Use the recommendations to implement the missing headers for enhanced protection."
)
messagebox.showinfo("Help", help_text)
To make things easier for the user, it’s important to provide a manual on how to use the program we’ve built. This responsibility falls upon the show_help()
function, which displays essential information such as how to enter URLs, save results in a CSV file, and more. Essentially, it explains how to use the application and what to expect from it, all presented in a user-friendly message box.
Main Tkinter Application
Now we have reached the grand finale, where we gather all the previous elements into one cohesive graphical interface. Since this program is a bit sensitive, we’ve ensured that it can only run directly and not be imported as a module. First, we create the main window using Tkinter’s tk
module, set its title, and define its geometry.
# Main Tkinter Application
if __name__ == "__main__":
root = tk.Tk()
root.title("Security Header Checker - The Pycodes")
root.geometry("1000x700")
Next, we create a frame where we place the URL entry widget and a label for user instructions.
# Frame for URL input and buttons
frame = ttk.Frame(root)
frame.pack(pady=10)
# URL Entry
ttk.Label(frame, text="Enter URLs (comma-separated):").grid(row=0, column=0, padx=5)
url_entry = ttk.Entry(frame, width=80)
url_entry.grid(row=0, column=1, padx=5)
Within this frame, we also add the “Check Security Headers” button, which calls the check_security_headers()
function when clicked.
# Check Button
ttk.Button(frame, text="Check Security Headers", command=check_security_headers).grid(row=0, column=2, padx=5)
Additionally, we include a scrollable text widget called results_text
to display the results.
# Results Display
results_text = scrolledtext.ScrolledText(root, width=120, height=25, wrap=tk.WORD)
results_text.pack(pady=10)
After that, we create another frame called save_frame
to hold the “Save Results as CSV” button, which calls the save_results_csv()
function, and the “Help” button, which calls the show_help()
function.
# Save Buttons Frame
save_frame = ttk.Frame(root)
save_frame.pack(pady=10)
# Save as CSV Button
ttk.Button(save_frame, text="Save Results as CSV", command=save_results_csv).grid(row=0, column=0, padx=5)
# Help Button
ttk.Button(save_frame, text="Help", command=show_help).grid(row=0, column=1, padx=5)
Finally, we start the main event loop with the mainloop()
method, ensuring that the main window remains active and responsive to the user.
root.mainloop()
Example
As you can see below, I checked the security of my website’s headers:
Also on a Windows system:
Full Code
import tkinter as tk
from tkinter import ttk, messagebox, scrolledtext, filedialog
import requests
import csv
# Security Headers Information
SECURITY_HEADERS_INFO = {
'Strict-Transport-Security': {
'description': 'Ensures HTTPS is used.',
'expected': 'max-age=63072000; includeSubDomains; preload',
'recommendation': 'Add Strict-Transport-Security to enforce HTTPS.',
'advice': 'This header is critical for enforcing HTTPS across your site. It helps prevent man-in-the-middle attacks.'
},
'Content-Security-Policy': {
'description': 'Prevents cross-site scripting attacks.',
'expected': None,
'recommendation': 'Add Content-Security-Policy to control resource loading.',
'advice': 'Implementing a strong CSP can significantly reduce XSS vulnerabilities by controlling resource loading.'
},
'X-Content-Type-Options': {
'description': 'Prevents MIME-type sniffing.',
'expected': 'nosniff',
'recommendation': 'Add X-Content-Type-Options with nosniff value.',
'advice': 'This header prevents browsers from interpreting files as something else, reducing the risk of malicious code execution.'
},
'X-Frame-Options': {
'description': 'Prevents clickjacking.',
'expected': 'DENY',
'recommendation': 'Add X-Frame-Options to prevent clickjacking.',
'advice': 'Clickjacking protection ensures your site is not embedded in iframes, avoiding potential clickjacking attacks.'
},
'X-XSS-Protection': {
'description': 'Enables XSS filtering.',
'expected': '1; mode=block',
'recommendation': 'Add X-XSS-Protection with mode=block.',
'advice': 'While modern browsers handle XSS well, this header can offer additional protection for older browsers.'
},
'Referrer-Policy': {
'description': 'Controls referrer information.',
'expected': 'no-referrer',
'recommendation': 'Add Referrer-Policy with no-referrer value.',
'advice': 'A strict referrer policy protects user privacy by minimizing the information shared with third parties.'
},
'Permissions-Policy': {
'description': 'Manages permissions like geolocation.',
'expected': None,
'recommendation': 'Add Permissions-Policy to control feature permissions.',
'advice': 'This policy helps you control which features and APIs your site can access, protecting user data.'
},
'Expect-CT': {
'description': 'Ensures valid certificate transparency.',
'expected': 'max-age=86400, enforce',
'recommendation': 'Add Expect-CT for certificate transparency.',
'advice': 'Using Expect-CT ensures that your site’s certificates are logged, helping to detect unauthorized certificates.'
}
}
def check_security_headers():
urls = [url.strip() for url in url_entry.get().split(',') if url.strip()]
if not urls:
messagebox.showwarning("Input Error", "Please enter one valid URL at least.")
return
results_text.delete(1.0, tk.END)
for url in urls:
try:
response = requests.get(url, timeout=10)
headers = response.headers
results = analyze_headers(headers)
display_results(url, results)
except requests.RequestException as e:
messagebox.showerror("Request Error", f"Failed to reach {url}: {e}")
def analyze_headers(headers):
results = {}
for header, details in SECURITY_HEADERS_INFO.items():
actual_value = headers.get(header)
expected_value = details['expected']
results[header] = {
'status': 'Present' if actual_value else 'Missing',
'actual_value': actual_value or 'None',
'match': actual_value == expected_value if expected_value else 'N/A',
'description': details['description'],
'recommendation': details['recommendation'] if actual_value != expected_value else None,
'advice': details['advice']
}
return results
def display_results(url, results):
results_text.insert(tk.END, f"Security Headers for {url}:\n\n")
for header, info in results.items():
results_text.insert(tk.END, f"Header: {header}\nStatus: {info['status']}\nActual Value: {info['actual_value']}\n")
results_text.insert(tk.END, f"Match Expected: {info['match']}\nDescription: {info['description']}\n")
if info['recommendation']:
results_text.insert(tk.END, f"Recommendation: {info['recommendation']}\n")
results_text.insert(tk.END, f"Advice: {info['advice']}\n" + "-" * 80 + "\n")
highlight_status(info['status'])
def highlight_status(status):
start_index, end_index = 'end-7l', 'end-1l'
tag, color = ('missing', 'red') if status == "Missing" else ('present', 'green')
results_text.tag_add(tag, start_index, end_index)
results_text.tag_config(tag, background=color, foreground='white')
def save_results_csv():
results = results_text.get(1.0, tk.END).strip()
if not results:
messagebox.showwarning("Save Error", "No results to save.")
return
filename = filedialog.asksaveasfilename(defaultextension=".csv", filetypes=[("CSV files", "*.csv")])
if filename:
try:
with open(filename, 'w', newline='', encoding='utf-8') as csvfile:
csvwriter = csv.writer(csvfile)
csvwriter.writerow(['URL', 'Header', 'Status', 'Actual Value', 'Match Expected', 'Description', 'Recommendation', 'Advice'])
parse_and_write_results(csvwriter, results)
messagebox.showinfo("Success", "Results saved successfully as CSV")
except Exception as e:
messagebox.showerror("File Error", f"Failed to save the results: {e}")
def parse_and_write_results(csvwriter, results):
lines = results.split("\n")
current_url = ""
for line in lines:
if line.startswith("Security Headers for"):
current_url = line.split(" ")[-1].strip(':')
elif line.startswith("Header:"):
try:
header = line.split(": ")[1]
status = lines[lines.index(line) + 1].split(": ")[1]
actual_value = lines[lines.index(line) + 2].split(": ")[1]
match_expected = lines[lines.index(line) + 3].split(": ")[1]
description = lines[lines.index(line) + 4].split(": ")[1]
# Check if the recommendation line is present
recommendation_line = lines[lines.index(line) + 5]
recommendation = recommendation_line.split(": ")[1] if "Recommendation:" in recommendation_line else ""
# Ensure advice line exists
advice_line = lines[lines.index(line) + 5] if not recommendation else lines[lines.index(line) + 6]
advice = advice_line.split(": ")[1] if "Advice:" in advice_line else ""
csvwriter.writerow([current_url, header, status, actual_value, match_expected, description, recommendation, advice])
except IndexError:
print(f"Error: Missing information for header {header}")
continue
def show_help():
help_text = (
"Security Header Checker Help\n\n"
"1. Enter URLs: If you You Input one or more URLs Make Sure They are separated by commas.\n"
"2. Check Security Headers: Simply Click the button to analyze the security headers.\n"
"3. Save Results: Save the analysis results as CSV files.\n\n"
"Security Headers:\n"
"- Strict-Transport-Security: Enforces HTTPS.\n"
"- Content-Security-Policy: Controls resource loading.\n"
"- X-Content-Type-Options: Prevents MIME-type sniffing.\n"
"- X-Frame-Options: Prevents clickjacking.\n"
"- X-XSS-Protection: Enables XSS filtering.\n"
"- Referrer-Policy: Controls referrer information.\n"
"- Permissions-Policy: Manages permissions.\n"
"- Expect-CT: Ensures certificate transparency.\n\n"
"Advice:\n"
"For each header, Please follow the given advice to improve The security settings.\n"
"Use the recommendations to implement the missing headers for enhanced protection."
)
messagebox.showinfo("Help", help_text)
# Main Tkinter Application
if __name__ == "__main__":
root = tk.Tk()
root.title("Security Header Checker - The Pycodes")
root.geometry("1000x700")
# Frame for URL input and buttons
frame = ttk.Frame(root)
frame.pack(pady=10)
# URL Entry
ttk.Label(frame, text="Enter URLs (comma-separated):").grid(row=0, column=0, padx=5)
url_entry = ttk.Entry(frame, width=80)
url_entry.grid(row=0, column=1, padx=5)
# Check Button
ttk.Button(frame, text="Check Security Headers", command=check_security_headers).grid(row=0, column=2, padx=5)
# Results Display
results_text = scrolledtext.ScrolledText(root, width=120, height=25, wrap=tk.WORD)
results_text.pack(pady=10)
# Save Buttons Frame
save_frame = ttk.Frame(root)
save_frame.pack(pady=10)
# Save as CSV Button
ttk.Button(save_frame, text="Save Results as CSV", command=save_results_csv).grid(row=0, column=0, padx=5)
# Help Button
ttk.Button(save_frame, text="Help", command=show_help).grid(row=0, column=1, padx=5)
root.mainloop()
Happy Coding!