Agent skill

External Enumeration

by forefy in forefy/.context

Passively map a company's domains, subdomains, DNS ownership, tech stack, and CDNs.

MITAuto-check passedSecurity

Install External Enumeration

skills CLI
$ npx skills add forefy/.context --skill external-enumeration -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install forefy/.context external-enumeration --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/forefy/.context.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills/hunter-utils/external-enumeration .claude/skills/external-enumeration && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
external-enumeration
GitHub stars
152
Token cost
~3.1k tokens
SKILL.md length
863 words
Files
1
Skills in repo
20
Repo updated
First seen
Licence
MIT

At a glance

Passively map a company's domains, subdomains, DNS ownership, tech stack, and CDNs.

  • Works in 12 steps: Scope Clarification → Domain Ownership & Attribution → Multi-Source Subdomain Enumeration → …
  • Recon an external attack surface
  • SKILL.md covers Phase 0 - Scope Clarification, Phase 1 - Domain Ownership &…, Phase 2 - Multi-Source… and Phase 3 - DNS Resolution &…, plus 9 more sections
  • Calls curl, python3 and npm; reaches crt.sh and api.hackertarget.com

What it does

External Enumeration is an agent skill from forefy/.context. Passively map a company's domains, subdomains, DNS ownership, tech stack, and CDNs. Use to recon an external attack surface or enumerate subdomains.

Its SKILL.md is about 3.1k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.

It sits in Security, covering Threat modeling and Cloud networking. It works with Cloudflare and Microsoft Azure. The repository describes itself as: AI Agent Skills, Goals and Dynamic Workflows for Security Auditing, Pentesting and Research. The licence is MIT.

When your agent uses it

  • Recon an external attack surface
  • Enumerate subdomains

Example prompts

  • “/external-enumeration”

Requirements

  • Python 3
  • Node.js

Workflow steps

12 steps, taken from the step headings in SKILL.md.

  1. Scope Clarification
  2. Domain Ownership & Attribution
  3. Multi-Source Subdomain Enumeration
  4. DNS Resolution & Live Check
  5. One-Pass Comprehensive Header Harvest
  6. Technology Identification
  7. Dual CDN Detection
  8. Cloudflare Bypass (Stealth Browser)
  9. Nonintrusive Port Probe (Second Pass)
  10. Subsidiary & Acquisition Research
  11. Notable Findings (Auto-Flag)
  12. Report Structure

What it can do on your machine

Read from SKILL.md and the folder at commit c8ff161. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    Shell commands in SKILL.md call:

    • curl
    • python3
    • npm
    • npx
    • brew

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    Hosts in commands or code, which the agent is likely to contact:

    • crt.sh
    • api.hackertarget.com
    • web.archive.org
    • urlscan.io
    • rapiddns.io
    • otx.alienvault.com

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

External Enumeration loads about 3.1k tokens when it runs. Until then it costs about 42 tokens; SKILL.md has 863 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~42
When it runs · the whole SKILL.md, loaded when a task matches
~3.1k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from forefy/.context at commit c8ff161, republished under its MIT licence (© forefy). 863 words, ~3,076 tokens.

Download SKILL.mdSave it as .claude/skills/external-enumeration/SKILL.md (or your agent's skills folder).
name
external-enumeration
description
Passively map a company's domains, subdomains, DNS ownership, tech stack, and CDNs. Use to recon an external attack surface or enumerate subdomains.

External Enumeration Skill

You are performing passive external reconnaissance on a target company's domain infrastructure. Goal: produce a comprehensive, structured map of all domains, subdomains, technology stack, and notable security observations - using only passive/OSINT techniques (no active exploitation).


Phase 0 - Scope Clarification

Ask the user for:

  1. Primary domain(s) to enumerate (e.g. example.com)
  2. Known subsidiaries or related companies (acquisitions, brand names, sister domains)
  3. Output format - markdown report to a file path?
  4. Depth - quick pass (passive DNS only) or deep pass (stealth browser + port scan)?

Phase 1 - Domain Ownership & Attribution

Before enumerating subdomains, confirm what domains are actually owned by the target.

1.1 WHOIS Check
bash
whois <domain> | grep -iE 'registrar|creation|name server|registrant'

Note: Most domains use privacy protection (e.g. GoDaddy DomainsbyProxy) - registrant names will be hidden. Do NOT rely on registrant names for attribution.

1.2 Nameserver Correlation (Primary Attribution Method)
bash
for d in domain1.com domain2.io domain3.net; do
  echo -n "$d: "; dig NS $d +short | sort | tr '\n' ' '; echo
done

Identical NS pairs = same DNS account = same owner. This is the strongest passive attribution proof even when WHOIS is privacy-protected.

1.3 MX + TXT Record Cross-Reference
bash
dig MX <domain> +short
dig TXT <domain> +short
  • Shared *.mail.protection.outlook.com MX = same Microsoft 365 tenant
  • TXT records reveal: Azure site verifications, Google Workspace, Atlassian, SendGrid
  • Azure TXT format: MS=ms... or azurewebsites.net subdomain references → same Azure tenant
1.4 Similar-Name Domain Trap

Note: Always verify similar-sounding domains (e.g. target.net, target.co) are actually owned by the target - different registrar or NS pair = likely unrelated squatter. Never assume.


Phase 2 - Multi-Source Subdomain Enumeration

Run all sources in parallel on first pass. crt.sh alone is never sufficient.

2.1 Certificate Transparency (crt.sh)
bash
curl -s "https://crt.sh/?q=%.example.com&output=json" \
  | python3 -c "import sys,json; [print(e['name_value']) for e in json.load(sys.stdin)]" \
  | tr ',' '\n' | sort -u | grep -v '^\*'
2.2 HackerTarget
bash
curl -s "https://api.hackertarget.com/hostsearch/?q=example.com" | cut -d',' -f1 | sort -u
2.3 Wayback Machine
bash
curl -s "https://web.archive.org/cdx/search/cdx?url=*.example.com&output=text&fl=original&collapse=urlkey" \
  | grep -oP '[\w.-]+\.example\.com' | sort -u
2.4 urlscan.io
bash
curl -s "https://urlscan.io/api/v1/search/?q=domain:example.com&size=100" \
  | python3 -c "import sys,json; d=json.load(sys.stdin); [print(r['page']['domain']) for r in d.get('results',[])]" \
  | sort -u
2.5 RapidDNS
bash
curl -s "https://rapiddns.io/subdomain/example.com?full=1" \
  | grep -oP '[\w.-]+\.example\.com' | sort -u
2.6 AlienVault OTX

Note: Turn off ssl verification if using Python urllib. Rate limiting is aggressive; skip if blocked.

bash
curl -s "https://otx.alienvault.com/api/v1/indicators/domain/example.com/passive_dns" \
  | python3 -c "import sys,json; [print(r.get('hostname','')) for r in json.load(sys.stdin).get('passive_dns',[])]" \
  | sort -u
2.7 subfinder (if installed)
bash
subfinder -d example.com -silent 2>/dev/null | sort -u

Install: brew install subfinder

2.8 Deduplicate Everything
bash
cat all_sources.txt | sort -u > subdomains_unique.txt
wc -l subdomains_unique.txt

Phase 3 - DNS Resolution & Live Check

bash
# Resolve all subdomains, identify live ones
while read sub; do
  ip=$(dig +short A "$sub" 2>/dev/null | grep -m1 -oP '\d+\.\d+\.\d+\.\d+')
  if [ -n "$ip" ]; then
    echo "$sub -> $ip"
  fi
done < subdomains_unique.txt

Phase 4 - One-Pass Comprehensive Header Harvest

Collect ALL headers in a single pass. Do not come back for a second pass.

bash
collect_headers() {
  local sub=$1
  local result=$(curl -sk -o /dev/null \
    --max-time 10 \
    -D - \
    -A "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36" \
    "https://$sub" 2>/dev/null | head -80)

  local status=$(echo "$result" | head -1 | grep -oP '\d{3}')
  local ip=$(dig +short A "$sub" 2>/dev/null | grep -m1 -oP '\d+\.\d+\.\d+\.\d+')

  python3 -c "
import sys, json
headers_raw = '''$result'''
h = {}
for line in headers_raw.split('\n')[1:]:
    if ': ' in line:
        k, v = line.split(': ', 1)
        h[k.lower().strip()] = v.strip()
print(json.dumps({'subdomain': '$sub', 'status': '$status', 'ip': '$ip', **h}))
"
}

Phase 5 - Technology Identification

5.1 From Server Headers
server valueTechnology
cloudflareCloudflare WAF/proxy
gunicornPython WSGI - direct exposure, no WAF
nginxNginx (may be direct or behind CDN)
UploadServerGoogle Cloud Storage
AmazonS3AWS S3 bucket
5.2 From CNAME Chains
bash
dig CNAME <subdomain> +short
CNAME targetPlatform
*.hubspot.netHubSpot (email/link tracking)
*.lmspowered.comLearnUpon LMS
*.partner-experience.comPartner portal SaaS
*.pendo.ioPendo product analytics
*.salesforce.comSalesforce CRM
*.zendesk.comZendesk support
*.freshdesk.comFreshdesk support
*.atlassian.netAtlassian (Jira/Confluence)
*.cloudfront.netAWS CloudFront (if direct CNAME, not leaked via)
*.vercel.appVercel hosting
*.netlify.appNetlify hosting
*.azurewebsites.netAzure App Service
5.3 From Redirect Targets (location header)
  • launcher.myapps.microsoft.com → Azure AD SSO (check URL for tenant ID)
  • *.okta.com → Okta SSO
  • accounts.google.com → Google Workspace SSO
  • *.auth0.com → Auth0
5.4 Azure AD Tenant ID Extraction

If redirect leads to Microsoft login:

location: https://launcher.myapps.microsoft.com/api/signin/APP_ID?tenantId=TENANT_UUID

Extract tenantId= value - this is the organization's Azure AD tenant ID.


Phase 6 - Dual CDN Detection

This is a high-value finding often missed on first pass.

The pattern: Cloudflare as outer WAF → AWS CloudFront as real CDN → origin

curl -sI https://app.example.com | grep -iE 'via|x-amz|x-cache|server'

Indicators:

  • server: cloudflare AND via: 1.1 xxxxxxxxx.cloudfront.net (CloudFront) → dual CDN confirmed
  • x-amz-cf-pop: TLV55-P1 → CloudFront PoP in Tel Aviv
  • x-cache: Miss from cloudfront → CloudFront active behind CF
  • x-amz-cf-id: → unique CloudFront request ID

Why it matters: Reveals true backend CDN provider, geographic PoP locations, and hints at origin server region.


Show full SKILL.md (347 more words)Show less

Phase 7 - Cloudflare Bypass (Stealth Browser)

When Cloudflare blocks curl, use stealth Playwright.

Note: Critical package name: Use puppeteer-extra-plugin-stealth - NOT playwright-extra-plugin-stealth (that package does NOT exist and will throw an error).

bash
cd /tmp && mkdir cf-stealth && cd cf-stealth
npm init -y
npm install playwright playwright-extra puppeteer-extra-plugin-stealth
npx playwright install chromium
javascript
const { chromium } = require('playwright-extra');
const StealthPlugin = require('puppeteer-extra-plugin-stealth');
chromium.use(StealthPlugin());

const targets = [
  'https://app.example.com',
];

(async () => {
  const browser = await chromium.launch({ headless: true });
  for (const url of targets) {
    const page = await browser.newPage();
    const headers = {};
    page.on('response', async resp => {
      if (resp.url() === url || resp.url().startsWith(url)) {
        Object.assign(headers, resp.headers());
      }
    });
    try {
      await page.goto(url, { waitUntil: 'domcontentloaded', timeout: 15000 });
      console.log(JSON.stringify({ url, headers }));
    } catch(e) {
      console.log(JSON.stringify({ url, error: e.message }));
    }
    await page.close();
  }
  await browser.close();
})();

Phase 8 - Nonintrusive Port Probe (Second Pass)

Don't run on Cloudflare IPs, don't run on WAFs/CDNs protected targets. Only look for applicative ports, don't overdo the web scan to more than a few strategic port decisions (passive-first approach).

bash
for host in direct-ip-1 direct-ip-2; do
  for port in 80 443 8080 8443 3000 4443; do
    result=$(curl -sk --max-time 5 -o /dev/null -w "%{http_code}" \
      "$([ $port = 443 ] || [ $port = 8443 ] && echo https || echo http)://$host:$port/")
    [ "$result" != "000" ] && echo "$host:$port -> HTTP $result"
  done
done

Phase 9 - Subsidiary & Acquisition Research

Stealth startups acquired by the target may have no public domain - this is normal.

Search strategy:

  1. "[company name]" acquisition site:crunchbase.com
  2. "[company name]" acquired site:techcrunch.com OR site:businesswire.com
  3. LinkedIn: search target company name → filter by "acquired by" or check leadership history
  4. Check registrant/NS of likely related domains (founder names, product names)

Note: A stealth startup may have: no domain, no Wayback archive, no CT certificates, no passive DNS entries - this is expected, not a gap in enumeration.


Phase 10 - Notable Findings (Auto-Flag)

Always flag these automatically in the report:

PatternFlag
access-control-allow-origin: *Warning - Open CORS - unauthenticated cross-origin requests allowed
HTTP 525 statusWarning - SSL Handshake Failure - origin SSL misconfiguration behind Cloudflare
server: gunicorn or server: unicorn with no CDNWarning - Direct backend exposure - no WAF, origin IP exposed
HTTP 301 → self (same host)Info - Likely internal-only / auth-required (especially on cslab*, vpn*, admin*)
Azure AD tenantId= in redirect URLInfo - Azure AD Tenant ID leak - extract UUID
x-amz-cf-pop with city codeInfo - CDN geographic PoP - reveals infrastructure region
via: *.cloudfront.net on a CF-served domainInfo - Dual CDN architecture
Subdomain → *.mail.protection.outlook.com CNAMEInfo - Microsoft 365 tenant confirmation

Phase 11 - Report Structure

Always produce the markdown report with this structure:

markdown
# [Company] Recon Report
**Date:** YYYY-MM-DD  
**Scope:** domain1.com · domain2.io · domain3.com

## Table of Contents
1. Confirmed Owned Domains
2. Technology Stack Summary
3. Notable Findings
4. [Primary Domain] - Subdomain Headers
   - Live - Cloudflare + CloudFront (Dual CDN)
   - Live - Cloudflare Only
   - Live - Third-Party / No CDN
   - Cloudflare DNS-Only / No HTTP Response
5. [Other domains]
6. Ownership & Attribution
7. Enumeration Sources

## 1. Confirmed Owned Domains
| Domain | Registrar | Created | Nameservers | Verdict |

## 2. Technology Stack Summary
| Layer | Technology | Evidence |

## 3. Notable Findings
| Finding | Detail |

## 4. Per-Subdomain Tables
### [subdomain]
| Header | Value |
(include: status, ip, server, via, x-amz-cf-pop, x-cache, x-frame-options, CSP, CORS, location, platform)

## 5. Ownership & Attribution
(people, entities, investors, Azure tenant, WHOIS proof)

## 6. Enumeration Sources
| Source | Results | Method |
**Total unique subdomains: N**  
**Vercel detected: yes / no**

Common Pitfalls Reference

PitfallCorrect Approach
Assuming WHOIS registrant names identify ownerUse NS correlation + MX + TXT instead (privacy protection hides names)
Assuming target.net or target.co = same companyVerify NS + MX independently - often different owners
Running crt.sh only for subdomain discoveryAlways run 6+ sources in parallel
Doing header harvest after initial reconCollect ALL headers in the first live check pass
Port scanning CF-fronted IPsPointless - Cloudflare terminates connections. Only port-scan direct/non-CF IPs

© forefy, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in skills/hunter-utils/external-enumeration of forefy/.context.

Open the folder on GitHubat commit c8ff161

Compare with similar skills

External Enumeration next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

External Enumeration compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
External Enumeration this skillforefy/.context152—~3.1kAutomated safety check: PassMIT
Implementing Cloud Waf Rulesmukul975/Anthropic-Cybersecurity-Skills34k—~2.9kAutomated safety check: PassApache-2.0
Managing DNSancoleman/ai-design-components526—~3.6kAutomated safety check: NotesMIT
Security HardenerFerroxLabs/wayland608—~3.3kAutomated safety check: PassApache-2.0
Azure Firewallvinayaklatthe/microsoft-security-skills175—~1.7kAutomated safety check: PassMIT
Origin Ip Discoveryuphiago/recon-skills1.3k—~1.7kAutomated safety check: PassMIT

Similar skills

  • Implementing Cloud Waf Rules

    mukul975/Anthropic-Cybersecurity-Skills

    Deploys and tunes Web Application Firewall rules on AWS WAF, Azure WAF, and Cloudflare, covering managed rule sets, custom business-logic rules, rate limiting, bot management, and false-positive…

    34k GitHub stars~2.9k tokensUpdated 1 mo ago
    SecurityAuto-check passed
  • Managing DNS

    ancoleman/ai-design-components

    Manage DNS records, TTL strategies, and DNS-as-code automation for infrastructure.

    526 GitHub stars~3.6k tokensUpdated 10 mo ago
    DevOps & CloudAuto-check: notes
  • Security Hardener

    FerroxLabs/wayland

    System security hardening expertise covering CIS benchmarks, OS hardening for Linux and Windows, container hardening, network hardening, application hardening, database hardening, cloud hardening…

    608 GitHub stars~3.3k tokensUpdated yesterday
    SecurityAuto-check passed
  • Azure Firewall

    vinayaklatthe/microsoft-security-skills

    Guidance for Azure Firewall — managed cloud-native L3-L7 stateful network firewall for centralised egress, east-west, and ingress control.

    175 GitHub stars~1.7k tokensUpdated 3 mo ago
    SecurityAuto-check passed
  • Origin Ip Discovery

    uphiago/recon-skills

    Discover origin IPs behind CDN/WAF via favicon hash, DNS history, and SSL certs.

    1.3k GitHub stars~1.7k tokensUpdated 1 mo ago
    SecurityAuto-check passed
  • Azure Security Audit

    automateyournetwork/netclaw

    Azure NSG compliance auditing and security posture assessment.

    674 GitHub stars~1.2k tokensUpdated yesterday
    DevOps & CloudAuto-check passed

More from forefy/.context

All 20 skills in this repo
  • Builds and formats security audit reports in Google Docs through the Docs API, with fixes for index drift, code styling and cross-reference links.

    152 GitHub stars~951 tokensUpdated 2 days ago
    Auto-check passed
  • Audits the Safe multisig wallets of DeFi protocols for governance misconfigurations, scoring each against a finding library and producing a severity-ranked report.

    152 GitHub stars~1.4k tokensUpdated 2 days ago
    Auto-check passed
  • Turns a company's domains into likely storage bucket names and checks six cloud providers for publicly readable buckets, for authorized security assessments only.

    152 GitHub stars~1.5k tokensUpdated 2 days ago
    Auto-check passed
  • Audit Scope

    forefy/.context

    Draft a security-audit scope from GitHub repos or API access, with a protocol narrative and a sizing table.

    152 GitHub stars~2.3k tokensUpdated 2 days ago
    Auto-check passed
  • Smart Contract Audit

    forefy/.context

    Comprehensive smart contract security audit framework with multi-expert analysis.

    152 GitHub starsUsed in 1 repo~5.1k tokens
    Auto-check passed
  • Infrastructure Audit

    forefy/.context

    Comprehensive infrastructure security audit framework for IaC, Docker, Kubernetes, and cloud configurations.

    152 GitHub stars~3.7k tokensUpdated 2 days ago
    Auto-check: notes

Questions about External Enumeration

What does External Enumeration do?

Passively map a company's domains, subdomains, DNS ownership, tech stack, and CDNs. context. Passively map a company's domains, subdomains, DNS ownership, tech stack, and CDNs.

When should I use External Enumeration?

External Enumeration fits situations like: recon an external attack surface; enumerate subdomains.

How do I install External Enumeration in Claude Code?

Run `npx skills add forefy/.context --skill external-enumeration -a claude-code`. Or copy the skill folder (skills/hunter-utils/external-enumeration in forefy/.context) into .claude/skills/external-enumeration in your project. Claude Code loads it when a task matches its description.

How do I install External Enumeration in Codex?

Run `npx skills add forefy/.context --skill external-enumeration -a codex`. Or copy the skill folder (skills/hunter-utils/external-enumeration in forefy/.context) into .agents/skills/external-enumeration in your project. Codex loads it when a task matches its description.

Can I use External Enumeration in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add forefy/.context --skill external-enumeration -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/external-enumeration, .gemini/skills/external-enumeration, .github/skills/external-enumeration and .opencode/skills/external-enumeration in your project.

What does External Enumeration need to run?

Going by SKILL.md and its folder, External Enumeration needs the command-line tools its instructions call (curl, python3, npm, npx and brew). Our summary lists: Python 3; Node.js.

Does External Enumeration access the network?

SKILL.md names 6 domains. In commands or code: crt.sh, api.hackertarget.com, web.archive.org, urlscan.io, rapiddns.io and otx.alienvault.com; the agent is likely to contact these when it follows the instructions. This is read from the text; nothing was executed.

Is External Enumeration safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does External Enumeration use?

External Enumeration is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does External Enumeration use?

About 3.1k tokens (SKILL.md is roughly 12k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to External Enumeration?

Skills that share tags, products or a category with External Enumeration: Implementing Cloud Waf Rules (mukul975/Anthropic-Cybersecurity-Skills, 34k stars), Managing DNS (ancoleman/ai-design-components, 526 stars), Security Hardener (FerroxLabs/wayland, 608 stars) and Azure Firewall (vinayaklatthe/microsoft-security-skills, 175 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains External Enumeration?

forefy (a GitHub user) maintains it in forefy/.context, which has 152 GitHub stars. The repository holds 20 skills in this directory. The repository was last updated on October 4, 2026.

Source: forefy/.context on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.