Understanding Z-Sans's asset model, breeding process, and topology is the foundation for mastering tool usage and extension.

1. Asset

Everything scanned is an asset. Z-Sans defines a set of asset types:

Type Enum Value Example Meaning
Domain domain example.com Domain seeds and enumerated subdomains
IP ip 93.184.216.34 Resolved IP addresses
URL url https://example.com/ Web page address
Port port example.com:443 IP + port
JS js https://example.com/app.js JavaScript resource

Internal reserved types

The code also defines a cert (certificate) type, but the current breeder factory does not directly produce assets of this type; it is reserved for future use.

Core Asset Fields

Each asset (Asset object) contains:

  • uid: Unique identifier with the format type:value, e.g., domain:example.com
  • type: The asset type
  • value: The normalized asset value
  • source: The source; manually provided seeds are manual
  • depth: Discovery depth (seeds are at 0)
  • state: The state machine state

Asset State Machine

flowchart LR
    new["new (pending)"]
    scanning["scanning (breeding in progress)"]
    scanned["scanned (processing complete)"]
    failed["failed (processing error)"]
    excluded["excluded"]
    eliminated["eliminated (no breeding value)"]

    new --> scanning
    scanning --> scanned
    scanning -->|processing failed| failed
    scanning -->|depth exceeded / type disabled / resource limit / exclusion match| excluded
    scanning -->|breeder judges no value| eliminated
  • new: newly created and pending
  • scanning: currently being processed by a breeder
  • scanned: processing complete
  • excluded: excluded (depth exceeded, type disabled, resource limit reached, or exclusion rule matched)
  • eliminated: eliminated (the breeder judged the asset to have no breeding value)
  • failed: processing error

2. Breeding Engine

The engine (BreedingEngine) is the task controller; its lifecycle is:

flowchart LR
    start["start"]
    loop["concurrent breeding loop"]
    completed["completed"]
    stop["stop"]

    start --> loop --> completed --> stop

Main flow:

  1. add_seed(type, value): Adds a seed asset to the asset graph and the priority queue
  2. run(): start() → start the thread pool → _concurrent_breed()
  3. Each round takes one asset from the queue and runs the _process_asset() processing pipeline
  4. Queue empty → completedstop() (save checkpoint, produce report)

The _process_asset() Processing Pipeline

For each asset, the following steps run in order (order matters):

  1. Depth check: exceeding max_depthexcluded
  2. Type switch: type enabled=falseexcluded
  3. Resource limits: exceeding resource_limits or the type's depth_limitexcluded
  4. Exclusion rules: matching exclusions (domain suffix / exact IP / URL keyword / port / regex) → excluded
  5. Get breeder: BreederFactory.get_breeder(type); no matching breeder → excluded
  6. Execute breeding: breeder.execute(asset, tool_orchestrator) produces a batch of new assets
  7. Add new assets to the graph: add_asset one by one → add_edge(discovered) → enqueue → trigger on_asset_discovered event
  8. Trigger on_asset_scanned; on exception set state=failed and trigger on_asset_failed

3. Breeder

A breeder determines "what related assets a given asset can discover". In core/breeders/breeders.py, the factory BreederFactory dispatches by type.

Breeder Handled Assets Discovery Targets
Domain breeder domain Subdomains, resolved IPs
IP breeder ip Open ports, reverse DNS
URL breeder url Links in the page, JS resources, fingerprints, title
Port breeder port Service identification
JS breeder js Inline referenced URLs

4. Priority Queue

PriorityBreedingQueue determines "who is processed next". The strategy is decided by the config strategy:

Strategy Value Behavior
priority_based Ordered by type priority (see config asset_types.*.priority); among equal priorities, shallower depth comes out first
depth_first Depth-first (deepest comes out first)
breadth_first Breadth-first (shallowest comes out first)
time_based Time order (first in, first out FIFO)

Default priorities

Default type priorities: domain=5, url=4, ip=3, port=2, js=1. Each type can be overridden individually in the config; the higher the value, the earlier it is processed.

The queue supports deduplication: assets already enqueued or in scanned/eliminated/excluded state will not be enqueued again.

5. Asset Graph

AssetGraph is a thread-safe topology store made up of nodes (assets) and edges (relations).

Relation Types (3)

Relation Enum Value Semantics
Discovery discovered Asset A bred asset B
Resolution resolved Domain resolved to IP
Hosting hosted Asset is hosted on an IP

Graph Export

  • JSON: export_json(metadata) → complete nodes and edges with metadata (schema_version, version, stats, seeds, config_hash)
  • GraphML: export_graphml() → directed graph XML; nodes carry attributes such as type/value/depth/state/fingerprints

Statistics

stats() returns: total asset count, total relation count, and asset type distribution. Both the HTML report and the Web console are based on this data.

6. Seed Asset Expansion Logic

add_seed() expands seeds:

Seed Type Additional Registration
domain Records itself (normalized to lowercase); expands to the registrable domain (eTLD+1) per asset_scope.seed_scope — see Configuration Reference
url Extracts hostname as a seed domain; prepends https:// if no scheme
ip Records itself + derives the /16 subnet (x.y.0.0)

Domain relevance uses hostname only

When checking whether a discovered URL/link belongs to the seed scope, Z-Sans compares the hostname (port stripped, lowercased) against seed domains — URLs like http://target.com:8443/ are matched correctly.

7. Concurrency Model

  • The engine uses ThreadPoolExecutor(max_workers=concurrency.max_tasks) (default 20)
  • Each tool also has its own concurrency limit (concurrency.tools.subfinder, etc.)
  • Asset states and graph data are protected by locks and safe to access concurrently
  • Event hooks may be invoked in a concurrent context; handlers must ensure their own thread safety

References

  • Asset model implementation: core/zsans_engine.py
  • Breeder implementation: core/breeders/breeders.py
  • Tool orchestration: core/tools/tools.py
  • Engine controller: the BreedingEngine class in main.py