Skip to main content

org-attack-surface

Org-grade attack-surface mapping: given a company's legal identity, discover its ENTIRE owned internet footprint — corporate family -> owned domains -> owned netblocks/ASN -> live assets — with attribution discipline, not just DNS breadth. The org-first attribution pyramid (legal entity -> LEI/registration -> corporate family -> owned domains -> owned netblocks/ASN -> live assets). Corporate-identity resolution via the GLEIF LEI API (legal name -> LEI, exact-LEI direct-children expansion, downward-only depth-capped BFS, NEVER a name re-resolution), SEC-EDGAR full-text search + Exhibit-21 subsidiary entity names, OpenCorporates entity corroboration, Wikidata SPARQL corporate graph (P856/P355/P749/P1830). Domain attribution via reverse-WHOIS (WhoisXML preview-then-purchase quota guard, SecurityTrails associated-domains — both paid), crt.sh O= certificate-transparency organization pivot (keyless), infrastructure correlation (shared NS/MX/SaaS-TXT, netblock membership, reverse-DNS PTR), and the independent-eviden

Source facts

Repository
elementalsouls/Claude-OSINT
Last source activity
August 24, 2026 at 16:21
Detected SKILL.md language
English
Stars
2,881
Forks
526

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

File Explorer
2 files

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
org-attack-surface
description
Org-grade attack-surface mapping: given a company's legal identity, discover its ENTIRE owned internet footprint — corporate family -> owned domains -> owned netblocks/ASN -> live assets — with attribution discipline, not just DNS breadth. The org-first attribution pyramid (legal entity -> LEI/registration -> corporate family -> owned domains -> owned netblocks/ASN -> live assets). Corporate-identity resolution via the GLEIF LEI API (legal name -> LEI, exact-LEI direct-children expansion, downward-only depth-capped BFS, NEVER a name re-resolution), SEC-EDGAR full-text search + Exhibit-21 subsidiary entity names, OpenCorporates entity corroboration, Wikidata SPARQL corporate graph (P856/P355/P749/P1830). Domain attribution via reverse-WHOIS (WhoisXML preview-then-purchase quota guard, SecurityTrails associated-domains — both paid), crt.sh O= certificate-transparency organization pivot (keyless), infrastructure correlation (shared NS/MX/SaaS-TXT, netblock membership, reverse-DNS PTR), and the independent-evidence combiner (1-prod(1-w_i), rule of three, OwnerTier NONE/WEAK/MODERATE/STRONG/CONFIRMED) — discover-only `related:` candidates are NEVER auto-scanned. Netblock/ASN attribution via org-first RIR queries (ARIN Whois-RWS org-handle search, RIPE DB organisation + inverse-org search) that recover 'dark netblocks' with no DNS link to the seed, ASN discovery (RIPEstat + BGPView union), the HYPERSCALER-SCOPE GUARD (never attribute a whole AWS/GCP/Azure/Cloudflare announced range to a tenant — keep only the seed-containing block, tag shared_hosting_cdn), and org-identity-seeded internet-scan-index queries (Shodan/Censys/ZoomEye/FOFA/BinaryEdge org: filters + an always-on keyless crt.sh fallback). Promote-to-scan triage ranks forgotten discover-only netblocks by remote-access exposure (gateway-vendor/KEV/control-plane/datastore port scoring) into an operator queue. Attribution confidence rubric + anti-patterns (namesake grafting via GLEIF name re-resolution, single-signal ownership, hyperscaler over-attribution, privacy-WHOIS pivot poisoning, RIR org-name collisions). Passive/keyless-first OSINT only — every paid-key dependency is enrichment on top of a keyless core, never a hard requirement. Use when mapping an organization's full corporate-family internet footprint, resolving a legal entity to its LEI/subsidiaries, discovering domains/netblocks/ASNs an org owns beyond its one seed domain, auditing M&A/shadow-IT sprawl, or scoping an engagement that starts from a company NAME rather than a domain.
version
1
sources
asm_reference_impl, gleif, public_research
triggers
["org attack surface","organization attack surface","org footprint","corporate footprint","corporate family","corporate family mapping","corporate family tree","subsidiary discovery","subsidiary attack surface","subsidiary mapping","GLEIF","LEI lookup","legal entity identifier","legal name to LEI","EDGAR subsidiary","SEC EDGAR","Exhibit 21","10-K subsidiaries","OpenCorporates","Wikidata corporate graph","reverse WHOIS","reverse whois pivot","crt.sh organization search","crt.sh O=","certificate transparency org pivot","CT org pivot","dark netblock","org-first RIR search","ARIN Whois-RWS","ARIN org search","RIPE DB search","RIPE organisation search","[Truncated]"]
# Org Attack Surface — Corporate-Family Footprint Mapping > Companion skills: [`osint-methodology`](../osint-methodology/) (the "how to think" 5-stage recon > pipeline this plugs into) and [`offensive-osint`](../offensive-osint/) (the per-host arsenal you run > once this skill hands you owned domains/netblocks — see its §14 Public Records and §28 Infrastructure > OSINT for the tool directory this skill deepens rather than duplicates). This skill answers a > different, upstream question: **not** "what does `acme.com` expose", but "what does **Acme > Corporation, the legal entity**, own across every domain, netblock, and subsidiary it has — including > the parts with no DNS trail back to the seed at all." ## 0. When to Use / When NOT **Use this skill when:** - The engagement starts from a **company name or legal entity**, not a domain — you need to derive the domain(s) first, not just enumerate one. - You need to find an org's **subsidiaries, sister brands, or M&A-acquired footprint** that a DNS/CT-only sweep of one seed domain would never surface. - You suspect **"dark" IP space** — netblocks or ASNs registered to the org's legal entity with no DNS record pointing at them (forgotten datacenter allocations, un-linked M&A infrastructure, IPs that only ever ran raw services). - You need **attribution discipline**: every candidate domain/netblock/ASN this skill surfaces carries an explicit, auditable ownership score — never a bare "looks related." - You are scoping a large or conglomerate engagement and need to prune scope by real corporate ownership before spending recon budget on strangers. **Do NOT use this skill when:** - You already have a confirmed, bounded target list and just need per-host recon — go straight to `offensive-osint`. - The target's authorization isn't established — see §1. - You need active exploitation or post-exploitation — out of scope here and everywhere in this skill family. --- ## 1. Authorization & Legal Posture Same posture as the companion skills: intended for assets the operator owns or has **written authorization** to assess. This skill is unusually likely to surface entities the operator did NOT ask about (subsidiaries, sister brands, M&A targets) — that is the point, but it sharpens the scope question rather than loosening it. **Soft scope check** — ask once when unclear: > *"This will surface the target's subsidiaries and related infrastructure, some of which may be > outside your engagement scope. Should I include the full corporate family, or stay bounded to the > named entity and its direct domains?"* **Always-on guardrail specific to this skill:** every asset this skill discovers beyond the seed domain — related domains, dark netblocks, discover-only ASNs, index-search IPs — is a **lead**, not a target. See §6.6 and every "discover-only" callout below. Nothing this skill produces is automatically in scope for active testing; a human confirms ownership first. --- ## 2. Confidence Levels & Ownership Tiers (two axes — do not conflate them) This skill runs **two separate scoring axes**, and mixing them up is the single most common way to misreport a finding. **Axis 1 — Finding confidence** (same as the companion skills): TENTATIVE / FIRM / CONFIRMED. Answers *"how sure am I this asset/record exists and I read it correctly."* **Axis 2 — Ownership tier**: answers *"how sure am I this asset belongs to the target organization."* Computed by combining every `OwnerSignal` that fired for a candidate via an independent-evidence formula (full mechanics in §8.4): | Score band | Tier | Meaning | |---|---|---| | 0 | `NONE` | No signal fired. | | 0–39 | `WEAK` | One low-weight signal (e.g. shared nameserver) — a lead, not attribution. | | 40–69 | `MODERATE` | Multiple weak signals, or one medium signal — worth an operator's eyeball. | | 70–89 | `STRONG` | Multiple independent signals, or one high-confidence signal — an active-scan-eligible score in a typical ASM promotion gate. | | 90–100 | `CONFIRMED` | Independent corroboration close to certainty, or a **confirming** signal (e.g. the seed domain itself) that forces 100 directly. | **A `NOT_OWNED` (stranger-lock) signal caps the score at 20 regardless of how many weak positives also fired** — so a foreign asset that happens to share a generic nameserver with the seed can never climb into an owned tier. **Critical nuance:** ownership tier is advisory, not a gate. Every domain/netblock/ASN/IP this skill mints beyond the seed carries an explicit **`discover_only=True`** structural flag that keeps it out of active scanning **independent of its score** — a `related:` domain that happens to score `STRONG` (85) still does not get auto-scanned. The score tells the operator *which* discover-only lead to promote first; only an explicit operator action (§10, promote-to-scan) moves an asset into the active pipeline. **Rule of three still applies** on top of the numeric score: a single signal type, however individually weighted, is a lead. Treat anything below `STRONG` as requiring a second, independent signal class before you say it out loud to a client as "this belongs to them." --- ## 3. Output Format Every candidate carries the standard finding schema (see companion skill §3) **plus** the org-attribution evidence block: ``` Finding: id: <stable hash> module: org-attack-surface asset_key: <typed key — e.g. org:acme-corp, related:acmesub.com, net:203.0.113.0/24, asn:64500> category: ORG_FOOTPRINT | RELATED_DOMAIN | DARK_NETBLOCK | PROMOTE_QUEUE severity: info # attribution work is discovery, not a vuln — see §6.6 confidence: <tentative|firm|confirmed> # Axis 1 — did I read the record right title: <one-line summary> description: <what was found + why it's plausibly the org's> attribution: owner_score: <0-100> # Axis 2 — combine() output owner_tier: <none|weak|moderate|strong|confirmed> discover_only: true # structural gate; independent of owner_score signals: - name: <signal name, e.g. cert_org_match> weight: <0.0-1.0> confirming: <bool> detail: <human-readable evidence, e.g. "crt.sh O= match: Acme Corp"> source: <module/connector> evidence: url: <where found> timestamp: <UTC ISO8601> raw: <truncated to 2 KiB> references: [<registry URL, RFC, etc.>] remediation: <"confirm ownership before promoting to active scan" — always the remediation here> ``` UTC timestamps everywhere. Never collapse `attribution.signals` to a bare count — the reviewing operator (or an auditor asking "why did you attribute this to them") needs to see exactly which evidence fired, not just how much. --- ## 4. Source Hygiene & Citations Same discipline as the companion skills: URL + UTC timestamp + tool/API version + run_id on every artifact. For registry lookups specifically: - Record the **exact query string** sent to GLEIF/EDGAR/ARIN/RIPE — registry search results are not reproducible from a vague "I searched for the company" note months later. - Cache raw registry JSON responses (GLEIF, ARIN, RIPE, EDGAR) — these APIs change/deprecate fields and a re-run six months later may not reproduce the same shape. - GLEIF LEI records and EDGAR filings are durable references (an LEI or CIK doesn't expire); prefer citing those over an ephemeral index-search hit. --- ## 5. Do NOT - Do NOT auto-scan a `related:` domain, a `discover_only` netblock/ASN, or a `discover_only` IP. Ever. That is the entire structural contract of this skill (§2, §6.6). - Do NOT re-resolve a subsidiary's name against GLEIF/EDGAR/OpenCorporates once you already hold its exact LEI or CIK — name search is not unique across jurisdictions and will graft a namesake's subtree onto the wrong parent (§7.1, §11.1). - Do NOT treat a shared nameserver, shared MX, or a brand string in an ASN org field as ownership. Each is `WEAK`-tier at best and needs corroboration (§11.1). - Do NOT attribute an entire hyperscaler-announced ASN range (AWS/GCP/Azure/Cloudflare/Akamai) to a tenant because one of the tenant's IPs lives in it (§9.5 — the hyperscaler-scope guard). - Do NOT pivot on a privacy-masked WHOIS registrant org or a registrar's own name/email — the pivotability guards in §8.1/§8.3 exist because these produce thousands of unrelated false positives. - Do NOT treat a fuzzy label match (Wikidata `rdfs:label`, an ASN holder substring match) as equivalent evidence to a filed registry record (a GLEIF LEI relationship, an EDGAR Exhibit-21 entry, an exact RIR org-handle match). Weight them accordingly (§8.4's signal table). - Do NOT paste real registrant PII, private beneficial-ownership data, or engagement-client identity details into cloud LLMs beyond what's needed for the recon task itself. --- ## 6. The Org-First Attribution Pyramid The mental model for everything in this skill. Most recon starts **bottom-up** from a seed domain and walks outward (subdomains, then IPs, then maybe an ASN). That misses everything that has no DNS trail back to the seed. This skill also walks **top-down**, starting from the legal entity itself: ``` ┌─────────────────────────┐ │ LEGAL ENTITY (name) │ §7 — the anchor: WHOIS registrant_org, │ → LEI / registration │ the seed's own TLS cert O=, or a └────────────┬─────────────┘ seed-owned ASN holder string │ ┌────────────▼─────────────┐ │ CORPORATE FAMILY │ §7.1-7.4 — GLEIF direct-child tree, │ (subsidiaries, M&A) │ EDGAR Exhibit-21, OpenCorporates, └────────────┬─────────────┘ Wikidata P355/P749/P1830 │ ┌──────────────────┴──────────────────┐ ▼ ▼ ┌───────────────────────┐ ┌───────────────────────────┐ │ OWNED DOMAINS │ │ OWNED NETBLOCKS / ASN │ │ (seed + related:) │ │ (seed-owned + dark) │ └───────────┬─────────────┘ └─────────────┬───────────────┘ │ §8 — reverse-WHOIS, crt.sh O=, │ §9 — org-first RIR (ARIN/RIPE), │ infra correlation, independent- bottom-up ASN (RIPEstat/BGPView), │ evidence combiner hyperscaler-scope guard └──────────────────┬──────────────────────┘ ▼ ┌─────────────────────────┐ │ LIVE ASSETS │ hand off to `offensive-osint` once │ (hosts, services, apps) │ ownership is operator-confirmed └─────────────────────────┘ ``` ### 6.1 Why top-down closes gaps bottom-up misses A DNS/CT-only sweep of `acme.com` will find `mail.acme.com`, `api.acme.com`, subsidiaries that happen to share the parent's nameservers — and nothing else. It will **never** find: - A subsidiary acquired in an M&A deal that still runs on its own pre-acquisition domain, nameservers, and netblocks, with zero DNS/cert linkage to `acme.com`. - A netblock registered directly to "Acme Corporation" at ARIN or RIPE that has never had a single A record point into it — a forgotten datacenter allocation, or IP space used only for raw non-DNS-fronted services. - A brand's cloud footprint that shows up in Shodan/Censys under `org:"Acme Corp"` with no DNS name at all — a bare IP serving a banner with the org string baked into a TLS cert or ASN registration. Each of these requires **starting from the org identity itself** and querying registries/indexes by *who owns it*, not *what resolves from the seed*. That is what §7–§9 do. ### 6.2 Discovery direction cheat sheet | Direction | Seeded from | Finds | Section | |---|---|---|---| | Top-down: entity → subsidiaries | Legal name / LEI | Corporate family tree | §7 | | Top-down: entity → domains | Registrant org / cert O= string | Related root domains | §8 | | Top-down: entity → netblocks/ASN | Org identity string | Dark netblocks, registered ASNs | §9.1–§9.4 | | Top-down: entity → live IPs | Org identity string | No-DNS live hosts (index search) | §9.6 | | Bottom-up: seed IP → ASN | Resolved seed IPs | Announced prefixes, adjacent infra | §9.3 | Both directions run in the same pipeline and reconcile through the same ownership-scoring axis (§2, §8.4) — a bottom-up-discovered netblock and a top-down-discovered netblock get scored the same way and land in the same graph. --- ## 7. Corporate Identity Resolution ### 7.1 GLEIF LEI API — the corporate-family tree The Global Legal Entity Identifier Foundation publishes, **keyless**, the filed parent/child relationships between legal entities under ISO 17442 LEIs. This is the highest-precision source in this entire skill because relationships are *filed*, not inferred. **Two-hop query pattern:** 1. Resolve a legal name → LEI (only ever done for the **seed** — see why below): ```bash LEI=$(curl -sk "https://api.gleif.org/api/v1/lei-records?filter[entity.legalName]=Acme%20Corporation&page[size]=1" \ -H "Accept: application/vnd.api+json" | jq -r '.data[0].attributes.lei') echo "$LEI" # capture it — the next step reuses $LEI ``` ```powershell $r = Invoke-RestMethod -Uri "https://api.gleif.org/api/v1/lei-records?filter[entity.legalName]=Acme%20Corporation&page[size]=1" ` -Headers @{ Accept = "application/vnd.api+json" } $lei = $r.data[0].attributes.lei ``` 2. Fetch that LEI's **direct children** (one level down, filed relationships only): ```bash curl -sk "https://api.gleif.org/api/v1/lei-records/$LEI/direct-children?page[size]=100" \ -H "Accept: application/vnd.api+json" | \ jq -r '.data[].attributes | .lei + " " + .entity.legalName.name' ``` ```powershell $children = Invoke-RestMethod -Uri "https://api.gleif.org/api/v1/lei-records/$lei/direct-children?page[size]=100" ` -Headers @{ Accept = "application/vnd.api+json" } $children.data | ForEach-Object { "$($_.attributes.lei) $($_.attributes.entity.legalName.name)" } ``` **Recurse for a multi-level tree — but with two non-negotiable rules:** 1. **Downward-only.** Only ever ask for a LEI's direct children — never ascend to the ultimate parent and fan into its siblings. Ascending turns "map Acme's subsidiaries" into "map every company under Acme's ultimate holding conglomerate," which is a different (much larger, mostly irrelevant) question the operator did not ask. 2. **Exact-LEI expansion for every descendant, name resolution ONLY for the seed.** Once you have a child's own filed LEI from step 2's response, expand *that entity's* children via `/lei-records/<child-LEI>/direct-children` directly — never by searching its **name** again. **Why this matters:** `filter[entity.legalName]=` is a name search, and legal names are **not unique across jurisdictions**. If entity B (a direct child of your seed) shares a name with an unrelated entity B' in another country, re-resolving "B" by name can silently return B' — and you then graft B''s entire subsidiary subtree onto your target's corporate family, under an authoritative-looking GLEIF badge. Carrying the exact LEI through the recursion makes this collision structurally impossible. **Depth and fan-out caps (recommended, mirrors the production implementation):** | Cap | Suggested value | Why | |---|---|---| | Max recursion depth | operator-set; default OFF, 1 level for a "deep" pass | Depth grows the tree exponentially with fan-out; an unbounded walk on a conglomerate never terminates in a useful time. | | Max nodes minted total | ~200 | Global budget; a capped tree must be flagged as truncated, never silently rendered as complete. | | Max direct children expanded per parent | ~50 | A parent with hundreds of filed subsidiaries (a large holding company) would otherwise dominate the whole budget. | **When either cap is hit, flag the affected parent node (`children_truncated`) rather than silently dropping the rest of its children** — an operator reading a "complete-looking" corporate tree that was actually cut off is worse than one that visibly says "and N more, not expanded." **Cycle safety:** track visited LEIs; a diamond ownership structure (A owns B and C, both B and C own D) should mint D once, under whichever parent reaches it first — not twice, and not infinitely. ### 7.2 SEC-EDGAR — Exhibit-21 subsidiary lists US-listed companies' 10-K filings include Exhibit 21, a list of subsidiary entity names. EDGAR's full-text search surfaces filings; you extract entity names, not domains — EDGAR asserts *"this subsidiary exists,"* not *"this subsidiary owns this URL."* ```bash curl -sk 'https://efts.sec.gov/LATEST/search-index?q=%22Acme%20Corporation%22&forms=10-K' \ -H "User-Agent: YourOrg-Recon research@yourdomain.example" | \ jq -r '.hits.hits[]._source.display_names[]' ``` ```powershell $headers = @{ "User-Agent" = "YourOrg-Recon research@yourdomain.example" } $r = Invoke-RestMethod -Uri 'https://efts.sec.gov/LATEST/search-index?q=%22Acme%20Corporation%22&forms=10-K' -Headers $headers $r.hits.hits | ForEach-Object { $_._source.display_names } ``` **Caveats:** - **Response shape is documented, not guaranteed** — EFTS full-text search returns *filing-level* metadata under `_source` (`display_names`, `ciks`, `form`, …), so `display_names` are the filer / co-filer entity names on matching 10-K filings — **corroboration that the entity files with the SEC**, not a ready-made subsidiary roster. True subsidiary lists live inside the filing's **Exhibit 21** document, which you fetch separately from the filing (not from the search index). Verify the field against a live response before trusting a parse. - SEC requires a **descriptive User-Agent identifying you** (name + contact) on every request — a bare `curl` UA gets throttled/blocked. This is SEC's own fair-access policy, not a tooling quirk. - **US-SEC-filer-only.** Empty for any org that doesn't file 10-Ks (non-US, private, or a subsidiary itself rather than the filer). Treat a null result as "not applicable," not "no subsidiaries." - Entity names from EDGAR feed the **depth-1 entity→domain pivot** (§8.5) — you take each returned name and pivot it through crt.sh O=, capped, to find candidate domains for that specific subsidiary. ### 7.3 OpenCorporates — entity corroboration (not domain discovery) OpenCorporates confirms *"is this a real registered company, and in what jurisdiction"* — it does not supply domains at all. Use it to corroborate a candidate subsidiary name found elsewhere (GLEIF, EDGAR, a press release) before spending a crt.sh pivot on it. ```bash
View on GitHub
This SKILL.md is very large, so SkillsMP previews the first section here. View on GitHub