Skip to main content

oamx

Read the OWASP Amass asset database and pipe it into everything else.

Zero dependencies. Read-only. Works across Amass v4 and v5.


The problem

This is the recon one-liner. Some version of it appears in every Amass tutorial, blog post and cheat sheet written in the last five years:

amass enum -passive -d example.com -o subs.txt
httpx -l subs.txt -silent | nuclei -severity high,critical

Since Amass v5 (August 2025), it writes an empty subs.txt.

v5 moved results into an asset database and stopped populating the text output. The scan works. The data is there. But -o produces nothing, httpx probes nothing, nuclei finds nothing, and the pipeline exits 0. It doesn't fail — it succeeds at doing nothing, quietly, on a schedule, possibly for months.

Amass is a producer with no consumer story. The documented way out is amass subs -names -d example.com, which gives you a flat list of hostnames and nothing else — no IPs, no netblocks, no ports, no provenance, no scoping, no "what changed since yesterday". Everyone else is pasting sqlite3 json_extract incantations out of GitHub issues.

oamx is the consumer.

oamx names -d example.com --resolved-only | httpx -silent | nuclei -severity high,critical

Install

pipx install oamx          # or: pip install oamx

Python 3.10+. No runtime dependencies — deliberately. A recon pipeline that breaks because of a transitive dependency resolution is worse than no tool.

There are two entry points and they are interchangeable:

oamx names -d example.com          # the console script
python -m oamx names -d example.com   # when PATH is not set up for you

The second is the one that keeps working inside a container, a pip install --target layout, or anywhere the scripts directory is not on PATH. Both are checked against the built wheel on every release.


Quickstart

# What is actually in my database?
oamx doctor

# Names, scoped to one target, that actually resolve
oamx names -d example.com --resolved-only

# Everything Amass found listening, ready for httpx or nuclei
oamx targets -d example.com --urls

# What genuinely appeared in the last day
oamx names -d example.com --new --since 24h

# The whole picture, with provenance, for storage or an agent to reason over
oamx json -d example.com > assets.jsonl

oamx doctor is the one to run first when a scan "found nothing":

database        /home/you/.config/amass/amass.sqlite
layout          v5 (entities/edges)
provenance      yes
assets          22

  FQDN                 8
  Service              3
  IPAddress            3
  Identifier           2
  URL                  1
  TLSCertificate       1
  SomeFutureAssetType  1
  Netblock             1
  ContactRecord        1
  AutonomousSystem     1

That is real output from the test fixture rather than an illustration, and everything below the database line is asserted against a live run — see tests/test_readme.py. SomeFutureAssetType is in the fixture deliberately: an asset type this release has never heard of still gets counted, and still comes out of oamx json with a usable value.


Commands

Command Output
names fully qualified domain names
ips IP addresses (--ipv4 / --ipv6)
cidrs netblocks in CIDR notation
asns autonomous system numbers
urls discovered URLs
certs TLS certificates
services responding network services
orgs organisations
emails email addresses
targets host:port pairs, or --urls for scheme://host:port
dns name<TAB>RRTYPE<TAB>target triples
json every matching asset as JSONL, with provenance
graph every matching relation as JSONL
stats counts by asset type
doctor what the database is and what is in it

Filters

Every command takes the same set:

Flag Effect
--db PATH database path (default: auto-discover the usual per-platform locations)
-d, --domain scope to a root domain; repeatable and comma-separated
--scope-depth N graph hops used to scope non-name assets (default 2, 0 disables)
--since DUR last seen within 24h, 7d, 2w …
--new with --since, match first seen — genuinely new, not re-confirmed
--resolved-only only names with a DNS record
--source NAME only assets asserted by this Amass plugin
--exclude-source NAME drop assets whose only sources are these
--min-confidence N drop assets below this source confidence (0–100)
--json JSONL with provenance instead of bare values
--count just the number
--fail-empty exit 1 if nothing matched, for CI

Why it works the way it does

Four decisions worth knowing about, because they change what you get back.

It introspects the schema instead of pinning to a version. Amass has renamed its storage at least three times — v3 graph files, v4 assets/relations, v5 entities/edges, plus column churn inside v5 point releases. oamx reads whatever tables and columns it finds and maps them onto one logical model. Asset types that didn't exist when this was written still come out with a usable value rather than raising. The adapter absorbs the churn so your pipeline doesn't.

Scoping follows the graph, but names are matched by suffix. -d example.com seeds on hostname suffix, then walks out --scope-depth hops to pick up the IPs, netblocks and certificates attached to those names. But a hostname reached by graph proximity is never pulled into scope. Without that rule, one CNAME to a shared CDN drags the CDN's other customers into your target list. Use --scope-depth 1 to stay on directly-resolved addresses, or 0 for names only.

Rows that reduce to the same thing are merged. API.Example.COM. from a certificate SAN and api.example.com from a DNS answer are two database rows and one host. oamx merges them: provenance is unioned, the higher confidence wins, and the sighting window widens to cover every contributing row. Merging happens before time and source filters, so a host is never judged on only one of its sightings.

Rediscovery is not discovery. --new --since 24h reports hosts first seen in that window. A host you've known for a month, which a second data source just re-confirmed, is not new and won't alert. That false-positive class is precisely what trains people to ignore their monitoring.


Output schema

--json emits one object per line, versioned so downstream code can depend on it even as Amass changes underneath:

{
  "schema": "oamx/1",
  "kind": "asset",
  "id": 3,
  "type": "FQDN",
  "value": "api.example.com",
  "first_seen": "2026-06-24 12:00:00.000000000+00:00",
  "last_seen": "2026-07-24 10:00:00.000000000+00:00",
  "sources": [{"name": "crtsh", "confidence": 95}, {"name": "DNS-IP", "confidence": 100}],
  "attrs": {"name": "api.example.com"}
}

graph emits "kind": "edge" records with from, to, label, and decoded DNS record types (rr_type: 1 becomes rr_name: "A", because nobody wants to grep for 5).


As a library

from oamx.integrations import query, values

hosts = values("names", domains=["example.com"], resolved_only=True)
records = query("all", domains=["example.com"], since="7d")

query returns the same records oamx json emits, as dicts. values returns just the values. Both raise OamxError with a message written to be read.

Reading is all it does: the database is opened mode=ro, so nothing here can start a scan or send traffic. That is a useful property if you are handing it to an agent — but oamx ships no agent-framework adapter, deliberately. Build that on your side, where your own conventions for tool schemas and error handling live.

The package ships py.typed, so annotations survive into whatever imports it.


Known limits

Stated plainly, because a recon tool that overstates itself is worse than useless.

  • SQLite only. Amass also supports PostgreSQL and Neo4j. The reader is written behind an interface so those are clean additions, but shipping untested database drivers would defeat the point.
  • Field names are verified for FQDN, IPAddress, Service and Identifier against the Open Asset Model documentation and, for Identifier, the struct in owasp-amass/open-asset-model itself. The remaining ~17 asset types use a best-effort key list with a generic fallback. If one of them extracts the wrong field for you, that's a one-line fix in model.py and a very welcome issue — Identifier was exactly that, reporting the unique_id dedupe key where the value lives in id.
  • The whole graph is loaded into memory to make scoping and merging correct. Fine for target-scoped databases; if yours has millions of entities, this will want a streaming path.
  • Amass v3 graph files are not supported. Only the SQLite asset database.

Compatibility

Amass Layout Status
v5.x entities / edges tested
v4.x assets / relations tested
v3.x graph files not supported

Both layouts are covered by fixtures built from the documented schemas, not from guesses.


Development

python3 -m venv .venv
.venv/bin/pip install -e ".[dev]"
.venv/bin/pytest

122 tests in about a second, gated on branch coverage rather than line coverage — this codebase is mostly branching, and line coverage calls a half-tested if fully covered. ruff, mypy --strict and pylint run from the same dev extra, so what CI runs and what you run cannot drift; see CONTRIBUTING.md for the order.

The dev extra is not part of the zero-dependency promise, which is about what an installed oamx pulls in. CI proves that separately by installing the package alone and asserting nothing third-party came with it.

If you add behaviour, break it on purpose first and check something goes red. A test that has never been seen to fail has not been shown to test anything.

Upstream

The gap this fills is arguably an Amass issue, not a third-party one. If the project wants an amass export that emits structured, scoped, provenance-carrying output, the schema in oamx/model.py is a reasonable starting point and this tool should stop being necessary. That would be the good outcome.

Licensed Apache-2.0, matching the Amass ecosystem.

Metadata

Release files for oamx 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for oamx 0.1.0
File Size Uploaded
oamx-0.1.0.tar.gz 54.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for oamx 0.1.0
File Interpreter ABI Platform
oamx-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 84.2 kB

Release files / oamx-0.1.0.tar.gz

Download URL oamx-0.1.0.tar.gz
Size 54.1 kB
Tags Source
SHA-256 checksum
How to use checksums
3687055ad975495be76043cd73299676301e2211450d8cd8b2f921d574c3eb60
BLAKE2b-256 checksum
How to use checksums
e28303642a203c1bec8557ec89e8e6eb3928e47555d9696bf9c3209d76b23231
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 25, 2026.

Transparency log

Release files / oamx-0.1.0-py3-none-any.whl

Download URL oamx-0.1.0-py3-none-any.whl
Size 30.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
41f629617eb5a549249b67b80e62d8da2ddba38f1d597052c3b633833e85cb23
BLAKE2b-256 checksum
How to use checksums
937abf1f0e3ce68fd43b53700e6b969b9b4a088394a4480a9f4b11e624adb612
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 25, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page