SecretHound converts secret scanning results from various sources into a BloodHound OpenGraph format. You can read the associated blog here. It leverages @p0dalirius's bhopengraph library.
This project's primary goal is to expand the graph quickly using a single edge: ContainsCredentialsFor. Currently, SecretHound will map secrets to 141 technology subgraphs (using the default taxonomy/taxonomy.json system). This translates to potentially 141 possible hybrid attack paths. It includes existing subgraphs accessible through the kind array values of: AZBase for Azure/Entra ID, GHBase for GitHub, and GCPBase for Google Cloud Platform. Generic secrets get mapped to an abstract kind (i.e., StargateNetwork) that is a catchall. Most of my testing was around git repositories.
Please submit an issue, submit a PR, or reach out on X @c0kernel if you have issues / feedback👍
Supported Scanners:
- GitHub Secret Scanning
- NoseyParker
- TruffleHog
- Nemesis
git clone https://github.com/C0KERNEL/SecretHound.git
cd SecretHound
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt# Retrieve GitHub Secret Scanning alerts for an org:
gh api /orgs/ORG/secret-scanning/alerts > github_alerts.json
# Parse GitHub Secret Scanning alerts with SecretHound (redacts by default)
python secrethound.py -t github -i github_alerts.json -o og_secrets.json
# Register technology icons in BloodHound (one-time setup)
python custom_icons.py --token YOUR_BLOODHOUND_TOKEN
# Upload og_secrets.json to BloodHound via the UI# 1. Scan this repository with NoseyParker
git clone https://github.com/C0KERNEL/SecretHound.git
noseyparker scan --datastore np.db SecretHound
noseyparker report --datastore np.db --format json > noseyparker_output.json
# 2. Convert to BloodHound format
python secrethound.py -t noseyparker -i noseyparker_output.json -o bloodhound_secrets.json -v
# 3. Register technology icons in BloodHound (one-time setup)
python custom_icons.py --token YOUR_BLOODHOUND_TOKEN
# 4. Upload bloodhound_secrets.json to BloodHound CE via web UI
# 5. Query using Cypher in BloodHound interfacepython secrethound.py -t {github,noseyparker,trufflehog,nemesis} -i INPUT -o OUTPUT [OPTIONS]| Argument | Description |
|---|---|
-t, --type |
Scanner type: github, noseyparker, trufflehog, or nemesis (required) |
-i, --input |
Input file path (JSON or JSONL) (required) |
-o, --output |
Output BloodHound JSON file path (required) |
--taxonomy |
Taxonomy configuration file (default: taxonomy/taxonomy.json) |
--no-redact |
Include full secrets (DANGEROUS - use with caution as your nodes in BloodHound will contain the secrets) |
--source-kind |
Source kind for BloodHound OpenGraph (default: StargateNetwork) |
-v, --verbose |
Enable verbose logging |
SecretHound uses a centralized taxonomy system to automatically categorize secrets by technology with colors. The taxonomy maps scanner-specific rule IDs to BloodHound node types.
-
taxonomy.json - Comprehensive taxonomy (default)
- Covers 200+ TruffleHog detectors
- All NoseyParker and GitHub Secret Scanning rules mapped
- Ideal for detailed analysis
-
taxonomy_minimal.json - Minimal taxonomy highlighting ~25 major technologies
- Focuses on most common cloud providers and services
- Cleaner BloodHound graphs with less node kinds
-
taxonomy_flat.json - Flat taxonomy with no technology classification
- All secrets categorized as generic "Secret" kind
- Simplest graph structure
- Ideal for basic secret discovery without technology-specific analysis
See TAXONOMY_GUIDE.md for complete documentation.
# Use default comprehensive taxonomy
python secrethound.py -t trufflehog -i input.jsonl -o output.json
# Use minimal taxonomy for cleaner graphs
python secrethound.py -t noseyparker -i input.json -o output.json --taxonomy taxonomy/taxonomy_minimal.json
# Use flat taxonomy - all secrets as generic "Secret"
python secrethound.py -t github -i input.json -o output.json --taxonomy taxonomy/taxonomy_flat.jsonNodes and edges produced by this tool all have a StargateNetwork source_kind. I enjoyed the SG-1 TV show 🤓, and it felt like a nice analogy to describe the behavior. You find a credential-at-rest somewhere in an environment and it can be used to teleport you into another subgraph. This reminded me of the Stargate Network in the TV show. I might switch to an analogy involving the Valve game: Portal at somepoint. Either way, I needed to categorize everything that this tool produces. Secrets are assigned either a specific *Secret kind based on a *Base or generically a Secret kind.
Specific specific AWSSecret kind based on a AWSBase example:
{
"kinds": ["AWSSecret", "AWSBase"],
"properties": {
"secret_type": "AWS Secret Access Key",
"secret_value_redacted": "AKIA...KEY"
}
}Generic Secret example:
{
"kinds": ["Secret"],
"properties": {
"secret_type": "Generic Secret",
"secret_value_redacted": "pass...word"
}
}Note: StargateNetwork appears in the metadata.source_kind field of the OpenGraph JSON, not in individual node kinds.
This enables powerful Cypher queries across kind values:
MATCH (s:StargateNetwork) RETURN s- All nodes generated by this toolMATCH (s:Secret) RETURN s- All secretsMATCH (s:AWSBase) RETURN s- All AWS-related nodesMATCH (s:AWSSecret) RETURN s- Only AWS SecretsMATCH (s:GHBase) RETURN s- All GitHub nodesMATCH (s:GHSecret) RETURN s- All GitHub secrets
Each technology uses colors for visualization:
| Technology | Node Kinds | Hex Color |
|---|---|---|
| AWS | AWSSecret | #FF9900 |
| Azure | AZSecret | #0078D4 |
| GCP | GCPSecret | #4285F4 |
| GitHub | GHSecret | #181717 |
| ... | ... | ... |
| Default | Secret | #ffc800 |
See taxonomy/taxonomy.json for the complete list technologies.
After generating your BloodHound data, register the technology icons:
# Register icons from comprehensive taxonomy
python custom_icons.py --token YOUR_BLOODHOUND_TOKEN
# Register icons from minimal taxonomy
python custom_icons.py --token YOUR_TOKEN --taxonomy taxonomy/taxonomy_minimal.json
# Use custom BloodHound URL
python custom_icons.py --token YOUR_TOKEN --url http://bloodhound.local:8080/api/v2/custom-nodes# Export alerts from GitHub
gh api /orgs/YOUR_ORG/secret-scanning/alerts > github_alerts.json
# Convert to BloodHound OpenGraph
python secrethound.py -t github -i github_alerts.json -o og_secrets.json# Scan a repository
noseyparker scan --datastore np.db --git-url https://github.com/example/repo.git
# Generate JSON report
noseyparker report --datastore np.db --format json > noseyparker_output.json
# Convert to BloodHound OpenGraph
python secrethound.py -t noseyparker -i noseyparker_output.json -o og_secrets.json# Scan with TruffleHog
trufflehog git https://github.com/example/repo.git --json > trufflehog_output.jsonl
# Convert to BloodHound OpenGraph
python secrethound.py -t trufflehog -i trufflehog_output.jsonl -o og_secrets.json# Export data from Nemesis and convert
python scripts/fetch_nemesis_findings.py --api-key <Hasura GraphQL API key> > nemesis_export.json
# Convert to BloodHound OpenGraph
python secrethound.py -t nemesis -i nemesis_export.json -o og_secrets.jsonTaking advantage of the kind system:
// Find all secrets
MATCH (s:Secret) RETURN s
// Find only AWS Secret Access Keys
MATCH (s:AWSSecret) RETURN s
// Find nodes added by SecretHound
MATCH (s:StargateNetwork) RETURN s
// Find paths using secrets
MATCH p=(r:StargateNetwork)-[:ContainsCredentialsFor]->(s:StargateNetwork)
RETURN p
// Find hybrid attack paths to Azure
MATCH p=(s:StargateNetwork)-[r*..]->(t:AZBase)
RETURN p
// Find hybrid attack paths to AWS
MATCH p=(s:StargateNetwork)-[r*..]->(t:AWSBase)
RETURN p
// Find hybrid attack paths to GCP
MATCH p=(s:StargateNetwork)-[r*..]->(t:GCPBase)
RETURN pSecretHound is designed to be compatible with existing BloodHound OpenGraph extensions:
Compatible Extensions:
- GitHound - GitHub repository and user mapping (work in progress)
- GCP-Hound - GCP technology subgraph - Adds nodes with
GCPBasekind
- SpecterOps - BloodHound, OpenGraph, GitHound, Nemesis, and everyone that has let me bounce ideas off of them 😃
- Praetorian - NoseyParker
- TruffleSecurity - TruffleHog
- LeakTK - fake-leaks testing repository
- p0dalirius - bhopengraph library
