Skip to content

Instantly share code, notes, and snippets.

@gm3dmo
Created July 2, 2025 09:09
Show Gist options
  • Save gm3dmo/1988cf05ed6378781938940ba614148b to your computer and use it in GitHub Desktop.
Save gm3dmo/1988cf05ed6378781938940ba614148b to your computer and use it in GitHub Desktop.
redacts github secrets from clipboard
#!/usr/bin/env python
import re
import pyperclip
def redact_github_tokens(text):
# Patterns for GitHub tokens (Personal Access Tokens, fine-tuned tokens, etc.)
# Example formats:
# - ghp_xxx... (Personal Access Token)
# - github_pat_xxx... (Fine-grained)
# - gho_xxx..., ghs_xxx..., ghr_xxx..., etc.
token_patterns = [
r'(gh[pousr]_[A-Za-z0-9]{30,})',
r'(github_pat_[A-Za-z0-9_]{22,255})'
]
# Combine all patterns
combined_pattern = '|'.join(token_patterns)
regex = re.compile(combined_pattern)
def mask_token(match):
token = match.group(0)
underscore_indices = [i for i, c in enumerate(token) if c == '_']
if len(underscore_indices) >= 3:
prefix_end = underscore_indices[1] + 1 # preserve up to second underscore
elif len(underscore_indices) == 1:
prefix_end = 4 # preserve first 4 characters
else:
# default behavior: preserve up to last underscore
prefix_end = token.rfind('_') + 1 if '_' in token else 4
suffix_length = 8
if len(token) <= prefix_end + suffix_length:
return token # too short to mask
prefix = token[:prefix_end]
suffix = token[-suffix_length:]
masked_length = len(token) - len(prefix) - len(suffix)
return prefix + '*' * masked_length + suffix
# Substitute tokens with redacted version
return regex.sub(mask_token, text)
def main():
clipboard_content = pyperclip.paste()
redacted_content = redact_github_tokens(clipboard_content)
pyperclip.copy(redacted_content)
print("Clipboard content scanned and redacted (if any GitHub tokens were found).")
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment