Skip to content

Instantly share code, notes, and snippets.

@mrrootsec
Created January 27, 2026 08:57
Show Gist options
  • Select an option

  • Save mrrootsec/b7f1554bc1a13d4d57968469ee05811c to your computer and use it in GitHub Desktop.

Select an option

Save mrrootsec/b7f1554bc1a13d4d57968469ee05811c to your computer and use it in GitHub Desktop.
Get rid of junk headers
# -*- coding: utf-8 -*-
"""
Burp Suite Extension (Jython / Python 2.7)
Adds a Repeater request-editor context menu item that removes "unnecessary"
browser/client-hint headers:
- Sec-Fetch-*
- Sec-CH-* (a.k.a. Sec-Ch-*)
How it integrates with Burp:
- Implements IBurpExtender to register with Burp
- Implements IContextMenuFactory to add a right-click menu item
- On click, reads the selected request, filters headers, rebuilds the message,
and writes the modified request back into Repeater.
"""
from burp import IBurpExtender, IContextMenuFactory
from javax.swing import JMenuItem
import re
class BurpExtender(IBurpExtender, IContextMenuFactory):
# Compile regexes once (fast + accurate). Anchored to header name only.
_UNWANTED_HEADER_NAME_REGEXES = [
re.compile(r"^Sec-Fetch-.*$", re.IGNORECASE),
re.compile(r"^Sec-CH-.*$", re.IGNORECASE), # covers Sec-CH-* canonical form
re.compile(r"^Sec-Ch-.*$", re.IGNORECASE), # covers mixed-case variants
]
def registerExtenderCallbacks(self, callbacks):
self._callbacks = callbacks
self._helpers = callbacks.getHelpers()
callbacks.setExtensionName("Repeater Header Cleanup (Sec-Fetch/Sec-CH)")
callbacks.registerContextMenuFactory(self)
self._callbacks.printOutput("[+] Repeater Header Cleanup loaded")
return
def createMenuItems(self, invocation):
"""
Called by Burp when building a right-click context menu.
We only show the menu item for:
- Request editor context (works in Repeater request editor)
- When there's at least one selected message
"""
try:
if invocation.getInvocationContext() != invocation.CONTEXT_MESSAGE_EDITOR_REQUEST:
return []
messages = invocation.getSelectedMessages()
if not messages or len(messages) == 0:
return []
item = JMenuItem("Remove Sec-Fetch-* and Sec-CH-* headers")
item.addActionListener(lambda event, msgs=messages: self._handle_click(msgs))
return [item]
except Exception as e:
self._callbacks.printError("Menu error: %s" % e)
return []
def _handle_click(self, messages):
"""
Handle menu click. We apply to ALL selected messages (Burp may allow multi-select).
"""
for msg in messages:
try:
original = msg.getRequest()
cleaned, removed = self._remove_unwanted_headers(original)
msg.setRequest(cleaned)
if removed:
self._callbacks.printOutput("[+] Removed headers: %s" % ", ".join(removed))
else:
self._callbacks.printOutput("[*] No matching headers found to remove")
except Exception as e:
self._callbacks.printError("Processing error: %s" % e)
def _remove_unwanted_headers(self, request_bytes):
"""
Parse request -> filter headers -> rebuild request.
Returns:
(new_request_bytes, removed_header_names_list)
"""
req_info = self._helpers.analyzeRequest(request_bytes)
headers = list(req_info.getHeaders())
body_offset = req_info.getBodyOffset()
body = request_bytes[body_offset:]
filtered_headers = []
removed_names = []
# Burp's headers list includes the request line as first entry: "GET / HTTP/1.1"
# Keep it as-is, only evaluate actual header lines with ":".
for h in headers:
if ":" not in h:
filtered_headers.append(h)
continue
name = h.split(":", 1)[0].strip()
if self._is_unwanted_header_name(name):
removed_names.append(name)
continue
filtered_headers.append(h)
new_request = self._helpers.buildHttpMessage(filtered_headers, body)
return new_request, removed_names
def _is_unwanted_header_name(self, header_name):
"""
Regex detection for unwanted header names. Only checks the header NAME (not value),
so we don't accidentally remove headers based on their content.
"""
for rx in self._UNWANTED_HEADER_NAME_REGEXES:
if rx.match(header_name):
return True
return False
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment