From a89e5a880c4f27c816134a8a898eb90e19917873 Mon Sep 17 00:00:00 2001 From: mr-pmillz <58376398+mr-pmillz@users.noreply.github.com> Date: Sun, 27 Sep 2026 17:50:01 -0400 Subject: [PATCH 1/2] Fix default wordlist path under uv run and package fuzz.txt The default -m/-b wordlist path was derived from sys.argv[0], which under `uv run cloud_enum` is the console-script shim in .venv/bin. The default became .venv/bin/enum_tools/fuzz.txt, so the tool exited with "Cannot access brute-force file" even when -m was passed. Resolve it from the module's own __file__ instead. fuzz.txt was also never declared as package data, so clean wheel builds (uv tool install, pip install .) shipped without it. Declare it under [tool.setuptools.package-data]. Add a regression test that runs parse_arguments with argv[0] pointing at a venv shim. Co-Authored-By: Claude Opus 5.5 --- cloud_enum.py | 5 +++-- pyproject.toml | 3 +++ tests/test_cloud_enum.py | 18 ++++++++++++++++++ 3 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 tests/test_cloud_enum.py diff --git a/cloud_enum.py b/cloud_enum.py index 8746d42..e4340a5 100755 --- a/cloud_enum.py +++ b/cloud_enum.py @@ -34,8 +34,9 @@ def parse_arguments(): desc = "Multi-cloud enumeration utility. All hail OSINT!" parser = argparse.ArgumentParser(description=desc) - # Grab the current dir of the script, for setting some defaults below - script_path = os.path.split(os.path.abspath(sys.argv[0]))[0] + # Grab the install dir of this module, for setting some defaults below. + # Not sys.argv[0]: console-script entry points live in the venv's bin dir. + script_path = os.path.dirname(os.path.abspath(__file__)) kw_group = parser.add_mutually_exclusive_group(required=True) diff --git a/pyproject.toml b/pyproject.toml index 34cd28a..a068023 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,6 +21,9 @@ dev = [ py-modules = ["cloud_enum"] packages = ["enum_tools"] +[tool.setuptools.package-data] +enum_tools = ["fuzz.txt"] + [build-system] requires = ["setuptools>=61"] build-backend = "setuptools.build_meta" diff --git a/tests/test_cloud_enum.py b/tests/test_cloud_enum.py new file mode 100644 index 0000000..9ec190c --- /dev/null +++ b/tests/test_cloud_enum.py @@ -0,0 +1,18 @@ +import os +import sys + +import cloud_enum + + +def test_default_wordlists_resolve_when_run_as_console_script(monkeypatch): + """ + `uv run cloud_enum` launches the console-script shim in .venv/bin, so the + default wordlists must not be located relative to sys.argv[0]. + """ + shim = os.path.join(os.sep, 'nonexistent', '.venv', 'bin', 'cloud_enum') + monkeypatch.setattr(sys, 'argv', [shim, '-k', 'test']) + + args = cloud_enum.parse_arguments() + + assert os.access(args.mutations, os.R_OK) + assert os.access(args.brute, os.R_OK) From 229fd0b7368702add647fcd4895c5ad7c3cf5e47 Mon Sep 17 00:00:00 2001 From: initstring <26131150+initstring@users.noreply.github.com> Date: Sun, 4 Oct 2026 19:27:09 +1100 Subject: [PATCH 2/2] Update stale docs to match the uv migration - utils.py pointed at a requirements.txt that no longer exists; the missing-dependency message now says to run 'uv sync' - -ns help text omitted its 1.1.1.1 default - README: regenerate the usage block from the real --help output, correct the cloudenum/ -> enum_tools/ regions paths, document uv tool install Co-Authored-By: Claude Opus 5 --- README.md | 38 +++++++++++++++++++++++--------------- cloud_enum.py | 3 ++- enum_tools/utils.py | 2 +- 3 files changed, 26 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index f548862..e8cb6c1 100644 --- a/README.md +++ b/README.md @@ -52,6 +52,12 @@ This project uses [uv](https://github.com/astral-sh/uv) for dependency managemen uv sync ``` +Or install it as a standalone tool: + +```sh +uv tool install git+https://github.com/initstring/cloud_enum +``` + ### Running The only required argument is at least one keyword. You can use the built-in fuzzing strings, but you will get better results if you supply your own with `-m` and/or `-b`. @@ -71,32 +77,34 @@ HTTP scraping and DNS lookups use 5 threads each by default. You can try increas uv run cloud_enum -k keyword -t 10 ``` -**IMPORTANT**: Some resources (Azure Containers, GCP Functions) are discovered per-region. To save time scanning, there is a "REGIONS" variable defined in `cloudenum/azure_regions.py and cloudenum/gcp_regions.py` that is set by default to use only 1 region. You may want to look at these files and edit them to be relevant to your own work. +**IMPORTANT**: Some resources (Azure Containers, GCP Functions) are discovered per-region. To save time scanning, there is a "REGIONS" variable defined in `enum_tools/azure_regions.py` and `enum_tools/gcp_regions.py` that is set by default to use only 1 region. You may want to look at these files and edit them to be relevant to your own work. **Complete Usage Details** ``` -usage: cloud_enum.py [-h] -k KEYWORD [-m MUTATIONS] [-b BRUTE] +usage: cloud_enum [-h] (-k KEYWORD | -kf KEYFILE) [-m MUTATIONS] [-b BRUTE] [-t THREADS] + [-ns NAMESERVER] [-nsf NAMESERVERFILE] [-l LOGFILE] [-f FORMAT] [--disable-aws] + [--disable-azure] [--disable-gcp] [-qs] Multi-cloud enumeration utility. All hail OSINT! -optional arguments: +options: -h, --help show this help message and exit - -k KEYWORD, --keyword KEYWORD + -k, --keyword KEYWORD Keyword. Can use argument multiple times. - -kf KEYFILE, --keyfile KEYFILE + -kf, --keyfile KEYFILE Input file with a single keyword per line. - -m MUTATIONS, --mutations MUTATIONS + -m, --mutations MUTATIONS Mutations. Default: enum_tools/fuzz.txt - -b BRUTE, --brute BRUTE - List to brute-force Azure container names. Default: enum_tools/fuzz.txt - -t THREADS, --threads THREADS + -b, --brute BRUTE List to brute-force Azure container names. Default: enum_tools/fuzz.txt + -t, --threads THREADS Threads for HTTP brute-force. Default = 5 - -ns NAMESERVER, --nameserver NAMESERVER - DNS server to use in brute-force. - -l LOGFILE, --logfile LOGFILE - Will APPEND found items to specified file. - -f FORMAT, --format FORMAT - Format for log file (text,json,csv - defaults to text) + -ns, --nameserver NAMESERVER + DNS server to use in brute-force. Default: 1.1.1.1 + -nsf, --nameserverfile NAMESERVERFILE + Path to the file containing nameserver IPs + -l, --logfile LOGFILE + Appends found items to specified file. + -f, --format FORMAT Format for log file (text,json,csv) - default: text --disable-aws Disable Amazon checks. --disable-azure Disable Azure checks. --disable-gcp Disable Google checks. diff --git a/cloud_enum.py b/cloud_enum.py index e4340a5..a9130a5 100755 --- a/cloud_enum.py +++ b/cloud_enum.py @@ -65,7 +65,8 @@ def parse_arguments(): parser.add_argument('-ns', '--nameserver', type=str, action='store', default='1.1.1.1', - help='DNS server to use in brute-force.') + help='DNS server to use in brute-force.' + ' Default: 1.1.1.1') parser.add_argument('-nsf', '--nameserverfile', type=str, help='Path to the file containing nameserver IPs') parser.add_argument('-l', '--logfile', type=str, action='store', diff --git a/enum_tools/utils.py b/enum_tools/utils.py index b9f84b8..1a8faab 100644 --- a/enum_tools/utils.py +++ b/enum_tools/utils.py @@ -20,7 +20,7 @@ from requests_futures.sessions import FuturesSession from concurrent.futures._base import TimeoutError except ImportError: - print("[!] Please pip install requirements.txt.") + print("[!] Missing dependencies, please run 'uv sync'.") sys.exit() LOGFILE = False