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 pendingscanning: currently being processed by a breederscanned: processing completeexcluded: 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:
add_seed(type, value): Adds a seed asset to the asset graph and the priority queuerun():start()→ start the thread pool →_concurrent_breed()- Each round takes one asset from the queue and runs the
_process_asset()processing pipeline - Queue empty →
completed→stop()(save checkpoint, produce report)
The _process_asset() Processing Pipeline¶
For each asset, the following steps run in order (order matters):
- Depth check: exceeding
max_depth→excluded - Type switch: type
enabled=false→excluded - Resource limits: exceeding
resource_limitsor the type'sdepth_limit→excluded - Exclusion rules: matching
exclusions(domain suffix / exact IP / URL keyword / port / regex) →excluded - Get breeder:
BreederFactory.get_breeder(type); no matching breeder →excluded - Execute breeding:
breeder.execute(asset, tool_orchestrator)produces a batch of new assets - Add new assets to the graph:
add_assetone by one →add_edge(discovered)→ enqueue → triggeron_asset_discoveredevent - Trigger
on_asset_scanned; on exception setstate=failedand triggeron_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 astype/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
BreedingEngineclass inmain.py