This workflow performs automated recon and subdomain takeover checks every time there's a push to the main branch. All results are stored in the results/ directory and automatically committed back to the repo.
- Runs on:
ubuntu-latest - Trigger:
pushto themainbranch
subfinderβ Passive subdomain enumerationassetfinderβ Subdomain finder by TomNomNomhttpxβ Probe for live hosts + HTTP metadatadnsxβ DNS resolver for A/CNAME recordssubzyβ Subdomain takeover detectionnucleiβ Vulnerability scanner using templatesqsreplace,gau,dig, etc.
For each domain defined in the ${{ secrets.DOMAIN }} (multiline secret):
subfinder + assetfinder
β results/${TARGET}-subdomains.txthttpx with multiple ports (80,443,8080, etc.)
β results/${TARGET}-live.txtawk 'SUCCESS' from httpx output
β results/${TARGET}-httpx-success.txtdnsx -a -cname -resp
β results/${TARGET}-resolved.txtif dig returns empty for CNAME
β results/${TARGET}-dangling-cname.txt-
Run subzy on:
- Full subdomain list
- DNS-resolved hostnames
β results/subzy-takeover-${TARGET}.json
β results/dnsx-takeover-${TARGET}.jsonnuclei -l httpx-success.txt
β results/nuclei-${TARGET}.txt| Secret Name | Purpose |
|---|---|
DOMAIN |
Newline-separated domains to scan |
EMAIL_ADDRESS |
Git commit identity |
USER_NAME |
Git commit identity |
- Git is configured in the workflow
- All results are committed and pushed to the repo (
results/folder)
name: Recon & Takeover
on:
push:
branches: [main]
jobs:
full-recon:
runs-on: ubuntu-latest
steps:
- name: Setup Go 1.23
uses: actions/setup-go@v5
with:
go-version: '1.23'
- name: Checkout code
uses: actions/checkout@v3
- name: Install Dependencies & Tools
run: |
set -e
sudo apt-get update
sudo apt-get install -y wget unzip jq git curl dnsutils
# Install Go tools
go install github.com/projectdiscovery/httpx/cmd/httpx@latest && sudo mv ~/go/bin/httpx /usr/bin/
go install github.com/projectdiscovery/subfinder/v2/cmd/subfinder@latest && sudo mv ~/go/bin/subfinder /usr/bin/
go install github.com/projectdiscovery/dnsx/cmd/dnsx@latest && sudo mv ~/go/bin/dnsx /usr/bin/
go install github.com/tomnomnom/qsreplace@latest && sudo mv ~/go/bin/qsreplace /usr/bin/
go install github.com/lc/gau/v2/cmd/gau@latest && sudo mv ~/go/bin/gau /usr/bin/
go install github.com/cybercdh/assetfinder@cybercdh && sudo mv ~/go/bin/assetfinder /usr/bin/
go install github.com/PentestPad/subzy@latest && sudo mv ~/go/bin/subzy /usr/bin/
# Install nuclei (latest release)
LATEST_VERSION=$(curl -s https://api.github.com/repos/projectdiscovery/nuclei/releases/latest | jq -r '.tag_name')
CLEAN_VERSION=${LATEST_VERSION#v}
wget https://github.com/projectdiscovery/nuclei/releases/download/${LATEST_VERSION}/nuclei_${CLEAN_VERSION}_linux_amd64.zip
unzip -o nuclei_${CLEAN_VERSION}_linux_amd64.zip
sudo mv nuclei /usr/bin/
sudo chmod +x /usr/bin/nuclei
rm -rf nuclei* *.md
- name: Recon
env:
DOMAINS: ${{ secrets.DOMAIN }}
run: |
set -e
TODAY=$(date +%F)
mkdir -p results
echo "$DOMAINS" | while read -r TARGET; do
echo "\nπ Scanning: $TARGET"
mkdir -p results/$TARGET
echo "[*] Subdomain Enumeration..."
assetfinder $TARGET --subs-only | grep "\.${TARGET}$" | sort -u > results/$TARGET/subdomains.txt
echo "[*] Probing live hosts..."
cat results/$TARGET/subdomains.txt | httpx -silent \
-status-code -location -title -web-server -cname -ip \
-tech-detect -cdn -method -probe -follow-redirects -fr \
-random-agent -no-color -timeout 15 -retries 3 -threads 100 \
-o results/$TARGET/httpx.txt
echo "[*] Filtering SUCCESS responses..."
cat results/$TARGET/httpx.txt | grep "SUCCESS" | awk '{print $1}' > results/$TARGET/httpx-success.txt
echo "[*] Resolving DNS (via dnsx)..."
awk '{print $1}' results/$TARGET/httpx.txt | dnsx -nc -cname -resp -silent > results/$TARGET/dnsx.txt
echo "[*] Filtering dangling CNAME (possible takeover)..."
awk '/\[CNAME\]/ {
gsub(/\[|\]/, "", $0); # remove all brackets
print $1, $3;
}' results/$TARGET/dnsx.txt | while read sub cname; do
if ! dig +short "$cname" | grep -q .; then
echo "$sub -> $cname [π₯ Dangling]" >> results/$TARGET/dangling-cname.txt
fi
done
echo "[*] Running Subdomain Takeover Check with Subzy (original list)..."
subzy run --targets results/$TARGET/subdomains.txt \
--concurrency 50 \
--hide_fails \
--timeout 10 \
--vuln \
--output results/$TARGET/subzy-subdomains.json
echo "[*] Extra Subzy (from resolved list)..."
awk '{print $1}' results/$TARGET/dnsx.txt | sort -u > results/$TARGET/filtered.txt
subzy run --targets results/$TARGET/filtered.txt \
--concurrency 50 \
--hide_fails \
--timeout 10 \
--vuln \
--output results/$TARGET/subzy-dnsx.json
echo "[*] Running Nuclei on successful HTTPX targets..."
nuclei -l results/$TARGET/httpx-success.txt \
-severity low, medium, high, critical, unknown \
-c 50 \
-timeout 10 \
-rate-limit 100 \
-silent \
-o results/$TARGET/nuclei-httpx.txt
done
- name: Set Git
run: |
git config --global user.email "${{ secrets.EMAIL_ADDRESS }}"
git config --global user.name "${{ secrets.USER_NAME }}"
- name: Commit & Push
run: |
git add results/
git commit -m "Recon & Takeover $(date -u)" --no-verify || echo "No changes"
git push origin main || true