Introducing PurpleRepo, a curated list of repositories for offensive and defensive cyber tradecraft π
You know how tedious it is to find that one awesome GitHub Project that exploited vulnerability XYZ, or allowed you to collect DFIR data for a new artifact, or a package that orchestrates a boring task specific to a technology or platform. π
It's hard to keep track of it all, even when encapsulated in "awesome" style repos. π€―
π PurpleRepo helps you by allowing you to:
ππΌ capture repos on the fly in different ways ππΌ capture their metadata using the GitHub API ππΌ summarize their READMEs using Cloudflare AI ππΌ Sync and Update based on cron schedules or specific triggers ππΌ Keep them up to date to understand which ones are active or not.
This was all built on free-tier Cloudflare infrastructure, it's all workers in the backend. βοΈ
The API will be made available soon so it can be integrated into automation or agentic workflows. π€
This repository hosts the curated list of cybersecurity-related GitHub projects (repo-list.yaml) that powers the PurpleRepo application. Your contributions here directly enhance the data available through hunt.quasarops.com.
Working Examples of a Python and a Typescript Cloudflare Worker to fetch and summarise GitHub files.
Inside the workers folder you will find two example workers, one that exemplifies how to fetch metadata from GitHub Repos using a Cloudflare Python Worker, and another one that encapsulates a file upload and summarisation workflow with an included Swagger API. Note: These workers resemble the ones in production but are not the ones directly employed by PurpleRepo.
The file called repo-list.yaml contains the list of repos displayed by the live PurpleRepo, a series of github actions and a cloudflare worker help automate the ingestion of changes to this file.
We welcome contributions to expand and improve our curated list of cybersecurity repositories! π
# Clone your fork
git clone https://github.com/YOUR_USERNAME/purplerepo.git
cd purplerepo
# Install dependencies (includes pre-commit hooks)
uv sync --dev
# Install pre-commit hooks
uv run pre-commit installEdit repo-list.yaml and add your entry:
- repo_url: https://github.com/user/repository
tags:
- github-repo
- offensive-tradecraft
- relevant-category
contributor_name: YourGitHubUsername# Run validation checks
uv run pre-commit run --all-files
# If all checks pass, commit your changes
git add repo-list.yaml
git commit -m "Add awesome-security-tool repository"
git push origin your-branch-nameYour contributions must follow these rules (automatically enforced):
- β
repo_url: Valid GitHub or Gist HTTPS URL - β
tags: List of 1-6 descriptive tags - β
contributor_name: Your GitHub username (required)
- β
Format: Single word or phrase in lowercase with hyphens (e.g.,
offensive-tradecraft) - β Count: Maximum 6 tags per repository (these represent your OWN tags, not the repository "topics", the topics are added later by the automation)
- β
Examples:
.net,pentesting,defensive-tradecraft,malware-analysis,cloud-security
- β Maximum 15 repositories can be added/removed per Pull Request
- β No duplicate URLs allowed
- β Valid YAML syntax required
Use these standardized tags to categorize repositories:
Primary Categories:
offensive-tradecraft- Red team, penetration testing, attack toolsdefensive-tradecraft- Blue team, detection, defense toolsthreat-hunting- Threat hunting methodologies and toolsdfir- Digital forensics and incident responsemalware-analysis- Malware analysis and reverse engineeringosint- Open source intelligence gatheringcloud-security- Cloud security tools and resources
Technology/Platform:
azure,aws-cloud,kubernetes,dockerwindows,linux,macospowershell,python,golang
Tool Types:
tradecraft-tool,detection-engineering,automationai-llm,machine-learning,data-analytics
- Fork the repository
- Create a feature branch:
git checkout -b add-security-tool - Add your repositories to
repo-list.yaml - Test locally:
uv run pre-commit run --all-files - Commit with clear message:
git commit -m "Add XYZ security tool" - Push to your fork:
git push origin add-security-tool - Open a Pull Request with description of changes
Every Pull Request automatically validates:
- YAML syntax validation
- Required fields check
- Tag format validation
- Duplicate URL detection
- File formatting
- All pre-commit validations
- Change limit enforcement (max 5 changes)
- Detailed error reporting in PR comments
# Fix validation errors and try again
uv run pre-commit run --all-files
# Skip hooks only if absolutely necessary
git commit --no-verify -m "Emergency commit"- "Too many tags": Reduce to 6 or fewer tags
- "Invalid tag format": Use lowercase with hyphens
- "Duplicate URL": Check if repository already exists
- "Missing contributor_name": Add your GitHub username
- "Too many changes": Split into multiple PRs with β€5 changes each
# Test specific file
uv run pre-commit run --files repo-list.yaml
# Test all files
uv run pre-commit run --all-files
# Update pre-commit hooks
uv run pre-commit autoupdateRepositories should be relevant to:
- Cybersecurity (offensive/defensive)
- Digital forensics and incident response
- Threat intelligence and hunting
- Security automation and tooling
- AI/ML for security applications
- Cloud security and DevSecOps
- Active or historically significant projects
- Clear documentation and README
- Legitimate security research/tools
- No malicious or illegal content
- Be respectful and professional in all interactions
- Provide constructive feedback and suggestions
- Help maintain high-quality, relevant content
- Follow the established contribution guidelines
- Validation Issues: Check the PR comments for detailed error messages
- Questions: Open an issue with the
questionlabel - Bug Reports: Open an issue with the
buglabel - Feature Requests: Open an issue with the
enhancementlabel
Thank you for helping make PurpleRepo a valuable resource for the cybersecurity community! π‘οΈβοΈ
This system automatically detects when new repositories are added to repo-list.yaml and sends JSON payloads to a Cloudflare Worker for processing.
The main script that:
- Uses GitPython to fetch
repo-list.yamlcontent from two different commit SHAs - Compares the files to identify new repository entries
- Converts new entries to JSON format for the Cloudflare Worker
Automatically runs when:
- There's a push to the
mainbranch - The
repo-list.yamlfile has been modified
The workflow:
- Checks out the repository with
fetch-depth: 2to get current and previous commits - Determines the old and new commit SHAs using git commands
- Runs the Python script to detect changes using local git repository
- Sends JSON payloads to the Cloudflare Worker
Provides unit tests for the core functionality.
Add these secrets to your GitHub repository:
CLOUDFLARE_WORKER_URL: The URL of your Cloudflare Worker endpointCLOUDFLARE_WORKER_TOKEN: Authentication token for your Cloudflare Worker
Your Cloudflare Worker should expect JSON payloads in this format:
{
"repo_url": "https://github.com/example/repo",
"initial_tags": ["tag1", "tag2"],
"contributor_name": "contributor_name"
}Or:
{
"repo_url": "https://github.com/example/repo",
"tags": ["tag1", "tag2"],
"contributor_name": "contributor_name"
}-
Install dependencies:
pip install -r requirements.txt
-
Run tests:
python test_detect_changes.py
-
Test with real data (requires being in a git repository):
python detect_repo_changes.py --old-sha <old_commit> --new-sha <new_commit> # Or use relative references: python detect_repo_changes.py --old-sha HEAD~1 --new-sha HEAD
- Trigger: Push to main branch with changes to
repo-list.yaml - Checkout: GitHub Action checks out repository with
fetch-depth: 2 - Fetch: Python script uses GitPython to read file content from both commits
- Parse: Convert YAML to structured data
- Compare: Identify repositories that exist in new version but not in old
- Convert: Transform new entries to JSON format
- Send: POST each payload to the Cloudflare Worker
- No GitHub Token Required: Uses local git repository instead of GitHub API
- Pythonic: Uses GitPython library instead of subprocess calls
- Efficient: Only fetches the commits needed (fetch-depth: 2)
- Reliable: Direct git operations are more reliable than API calls
The script handles these fields:
repos:
- repo_url: https://github.com/example/repo1
tags:
- pentesting
- security
contributor_name: contributor1
- repo_url: https://github.com/example/repo2
tags:
- defensive-tradecraft
- offensive-tradecraft
- tools
contributor_name: contributor2Each new repository entry becomes a separate JSON payload:
{
"repo_url": "https://github.com/example/repo",
"tags": ["github-repo", "security"],
"contributor_name": "contributor_name"
}- PyYAML: For parsing YAML files
- GitPython: For git operations (replaces subprocess calls)
-
GitPython Installation: Ensure GitPython is installed:
pip install GitPython -
Git Repository: The script must be run in a valid git repository
-
Missing Commits: Ensure the specified commit SHAs exist in the repository
-
Missing Secrets: If
CLOUDFLARE_WORKER_URLis not set, the workflow will skip sending payloads but still detect changes -
YAML Parsing Errors: Check that your
repo-list.yamlfollows the expected structure
Enable debug output by running tests:
python test_detect_changes.pyCheck the Actions tab in your repository for detailed logs of each workflow run.
- File Path: Use
--file-pathparameter to specify a different YAML file - Repository Path: Use
--repo-pathparameter if running from outside the git repository - Output Format: Modify the
to_dict()method inRepoEntryclass to change JSON structure - Additional Fields: Add new fields to the
RepoEntrydataclass as needed
- Trigger Conditions: Modify the
onsection to change when the workflow runs - Worker Authentication: Adjust the curl command to match your worker's authentication requirements
- Error Handling: Add additional error handling steps as needed
- No GitHub tokens required for basic operation
- Store sensitive tokens in GitHub Secrets, not in code
- Validate input data before sending to external services
- Consider rate limiting for the Cloudflare Worker endpoint
- Faster: No API rate limits since we use local git
- More Reliable: Direct git operations vs HTTP requests
- Simpler: No authentication required for reading local repository
- Efficient: Only fetches the specific commits needed