bbot 2.4.2.6611rc0__py3-none-any.whl → 2.4.2.6621rc0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of bbot might be problematic. Click here for more details.

bbot/__init__.py CHANGED
@@ -1,5 +1,5 @@
1
1
  # version placeholder (replaced by poetry-dynamic-versioning)
2
- __version__ = "v2.4.2.6611rc"
2
+ __version__ = "v2.4.2.6621rc"
3
3
 
4
4
  from .scanner import Scanner, Preset
5
5
 
bbot/modules/dehashed.py CHANGED
@@ -13,23 +13,23 @@ class dehashed(subdomain_enum):
13
13
  "author": "@SpamFaux",
14
14
  "auth_required": True,
15
15
  }
16
- options = {"username": "", "api_key": ""}
17
- options_desc = {"username": "Email Address associated with your API key", "api_key": "DeHashed API Key"}
16
+ options = {"api_key": ""}
17
+ options_desc = {"api_key": "DeHashed API Key"}
18
18
  target_only = True
19
19
 
20
- base_url = "https://api.dehashed.com/search"
20
+ base_url = "https://api.dehashed.com/v2/search"
21
21
 
22
22
  async def setup(self):
23
- self.username = self.config.get("username", "")
24
23
  self.api_key = self.config.get("api_key", "")
25
- self.auth = (self.username, self.api_key)
26
24
  self.headers = {
27
25
  "Accept": "application/json",
26
+ "Content-Type": "application/json",
27
+ "Dehashed-Api-Key": self.api_key,
28
28
  }
29
29
 
30
30
  # soft-fail if we don't have the necessary information to make queries
31
- if not (self.username and self.api_key):
32
- return None, "No username / API key set"
31
+ if not self.api_key:
32
+ return None, "No API key set"
33
33
 
34
34
  return await super().setup()
35
35
 
@@ -38,29 +38,31 @@ class dehashed(subdomain_enum):
38
38
  async for entries in self.query(query):
39
39
  for entry in entries:
40
40
  # we have to clean up the email field because dehashed does a poor job of it
41
- email_str = entry.get("email", "").replace("\\", "")
42
- found_emails = list(await self.helpers.re.extract_emails(email_str))
43
- if not found_emails:
44
- self.debug(f"Invalid email from dehashed.com: {email_str}")
45
- continue
46
- email = found_emails[0]
41
+ emails = []
42
+ for email in entry.get("email", []):
43
+ email_str = email.replace("\\", "")
44
+ found_emails = list(await self.helpers.re.extract_emails(email_str))
45
+ if not found_emails:
46
+ self.debug(f"Invalid email from dehashed.com: {email_str}")
47
+ continue
48
+ emails += found_emails
47
49
 
48
- user = entry.get("username", "")
49
- pw = entry.get("password", "")
50
- h_pw = entry.get("hashed_password", "")
50
+ users = entry.get("username", [])
51
+ pws = entry.get("password", [])
52
+ h_pws = entry.get("hashed_password", [])
51
53
  db_name = entry.get("database_name", "")
52
54
 
53
55
  tags = []
54
56
  if db_name:
55
57
  tags = [f"db-{db_name}"]
56
- if email:
58
+ for email in emails:
57
59
  email_event = self.make_event(email, "EMAIL_ADDRESS", parent=event, tags=tags)
58
60
  if email_event is not None:
59
61
  await self.emit_event(
60
62
  email_event,
61
63
  context=f'{{module}} searched API for "{query}" and found {{event.type}}: {{event.data}}',
62
64
  )
63
- if user:
65
+ for user in users:
64
66
  await self.emit_event(
65
67
  f"{email}:{user}",
66
68
  "USERNAME",
@@ -68,7 +70,7 @@ class dehashed(subdomain_enum):
68
70
  tags=tags,
69
71
  context=f"{{module}} found {email} with {{event.type}}: {{event.data}}",
70
72
  )
71
- if pw:
73
+ for pw in pws:
72
74
  await self.emit_event(
73
75
  f"{email}:{pw}",
74
76
  "PASSWORD",
@@ -76,7 +78,7 @@ class dehashed(subdomain_enum):
76
78
  tags=tags,
77
79
  context=f"{{module}} found {email} with {{event.type}}: {{event.data}}",
78
80
  )
79
- if h_pw:
81
+ for h_pw in h_pws:
80
82
  await self.emit_event(
81
83
  f"{email}:{h_pw}",
82
84
  "HASHED_PASSWORD",
@@ -86,30 +88,33 @@ class dehashed(subdomain_enum):
86
88
  )
87
89
 
88
90
  async def query(self, domain):
89
- query = f"domain:{domain}"
90
- url = f"{self.base_url}?query={query}&size=10000&page=" + "{page}"
91
- page = 0
92
- num_entries = 0
93
- agen = self.api_page_iter(url=url, auth=self.auth, headers=self.headers, _json=False)
91
+ url = self.base_url
92
+ json = {
93
+ "query": "",
94
+ "page": 1,
95
+ "size": 10000, # The maximum permitted size and pagination.
96
+ }
97
+ json["query"] = f"domain:{domain}"
98
+ json["page"] = 1
99
+ max_pages = 1
100
+ agen = self.api_page_iter(url=url, headers=self.headers, _json=False, method="POST", json=json)
94
101
  async for result in agen:
95
102
  result_json = {}
96
103
  with suppress(Exception):
97
104
  result_json = result.json()
98
105
  total = result_json.get("total", 0)
99
106
  entries = result_json.get("entries", [])
100
- if entries is None:
101
- entries = []
102
- num_entries += len(entries)
103
- page += 1
104
- if (page >= 3) or (not entries):
105
- if result is not None and result.status_code != 200:
106
- self.warning(
107
- f"Error retrieving results from dehashed.com (status code {result.status_code}): {result.text}"
108
- )
109
- elif (page >= 3) and (total > num_entries):
110
- self.info(
111
- f"{domain} has {total:,} results in Dehashed. The API can only process the first 30,000 results. Please check dehashed.com to get the remaining results."
112
- )
107
+ json["page"] += 1
108
+ if result is not None and result.status_code != 200:
109
+ self.warning(
110
+ f"Error retrieving results from dehashed.com (status code {result.status_code}): {result.text}"
111
+ )
112
+ elif (json["page"] > max_pages) and (total > (json["size"] * max_pages)):
113
+ self.info(
114
+ f"{domain} has {total:,} results in Dehashed. The API can only process the first 10,000 results. Please check dehashed.com to get the remaining results."
115
+ )
116
+ if entries:
117
+ yield entries
118
+ if not entries or json["page"] > max_pages:
113
119
  await agen.aclose()
114
120
  break
115
- yield entries
@@ -0,0 +1,75 @@
1
+ from bbot.modules.templates.github import github
2
+ from bbot.modules.templates.subdomain_enum import subdomain_enum
3
+
4
+
5
+ class github_usersearch(github, subdomain_enum):
6
+ watched_events = ["DNS_NAME"]
7
+ produced_events = ["SOCIAL", "EMAIL_ADDRESS"]
8
+ flags = ["passive", "safe", "code-enum"]
9
+ meta = {
10
+ "description": "Query Github's API for users with emails matching in scope domains that may not be discoverable by listing members of the organization.",
11
+ "created_date": "2025-05-10",
12
+ "author": "@domwhewell-sage",
13
+ "auth_required": True,
14
+ }
15
+ options = {"api_key": ""}
16
+ options_desc = {"api_key": "Github token"}
17
+
18
+ async def handle_event(self, event):
19
+ self.verbose("Searching for users with emails matching in scope domains")
20
+ query = self.make_query(event)
21
+ users = await self.query_users(query)
22
+ for user, email in users:
23
+ user_url = f"https://github.com/{user}"
24
+ event_data = {"platform": "github", "profile_name": user, "url": user_url}
25
+ user_event = self.make_event(event_data, "SOCIAL", tags="github-org-member", parent=event)
26
+ if user_event:
27
+ await self.emit_event(
28
+ user_event,
29
+ context=f"{{module}} searched for users with {{DNS_NAME}} in the profile and discovered {{event.type}}: {user_url}",
30
+ )
31
+ if email:
32
+ await self.emit_event(
33
+ email,
34
+ "EMAIL_ADDRESS",
35
+ parent=event,
36
+ context=f"{{module}} found an {{event.type}} on the github profile {user_url}: {{event.data}}",
37
+ )
38
+
39
+ async def query_users(self, query):
40
+ users = []
41
+ graphql_query = f"""query search_users {{
42
+ search(query: "{query}", type: USER, first: 100, after: "{{NEXT_KEY}}") {{
43
+ userCount
44
+ pageInfo {{
45
+ hasNextPage
46
+ endCursor
47
+ }}
48
+ edges {{
49
+ node {{
50
+ ... on User {{
51
+ login
52
+ # bio Commented out as user can add arbritrary domains to their bio
53
+ email # Email is verified by github
54
+ websiteUrl # Website is not verified by github
55
+ }}
56
+ }}
57
+ }}
58
+ }}
59
+ }}"""
60
+ async for data in self.github_graphql_request(graphql_query, "search"):
61
+ if data:
62
+ user_count = data.get("userCount", 0)
63
+ self.verbose(f"Found {user_count} users with the query {query}, verifying if they are in-scope...")
64
+ edges = data.get("edges", [])
65
+ for node in edges:
66
+ user = node.get("node", {})
67
+ in_scope_hosts = await self.scan.extract_in_scope_hostnames(str(user))
68
+ if in_scope_hosts:
69
+ login = user.get("login", "")
70
+ email = user.get("email", None)
71
+ self.verbose(
72
+ f'Found in-scope hostname(s): "{in_scope_hosts}" in the profile https://github.com/{login}, the profile appears to be in-scope'
73
+ )
74
+ users.append((login, email))
75
+ return users
@@ -44,3 +44,31 @@ class github(BaseModule):
44
44
  self.trace(traceback.format_exc())
45
45
  return None, f"Error with API ({str(e).strip()})"
46
46
  return True
47
+
48
+ async def github_graphql_request(self, graphql_query, resp_key):
49
+ url = f"{self.base_url}/graphql"
50
+ next_key = ""
51
+ has_next_page = True
52
+
53
+ while has_next_page:
54
+ query = graphql_query.replace("{NEXT_KEY}", next_key)
55
+ r = await self.api_request(url, method="POST", json={"query": query})
56
+ if r is None:
57
+ break
58
+ status_code = getattr(r, "status_code", 0)
59
+ if status_code == 403:
60
+ self.warning("Github is rate-limiting us (HTTP status: 403)")
61
+ break
62
+ try:
63
+ json = r.json()
64
+ except Exception as e:
65
+ self.warning(f"Failed to decode JSON for {r.url} (HTTP status: {status_code}): {e}")
66
+ break
67
+
68
+ data = json.get("data", {}).get(resp_key, {})
69
+ yield data
70
+
71
+ # Update pagination variables
72
+ page_info = data.get("pageInfo", {})
73
+ has_next_page = page_info.get("hasNextPage", False)
74
+ next_key = page_info.get("endCursor", "")
@@ -1,52 +1,44 @@
1
1
  from .base import ModuleTestBase
2
2
 
3
- dehashed_domain_response = {
4
- "balance": 10000,
5
- "entries": [
6
- {
7
- "id": "4363462346",
8
- "email": "bob@blacklanternsecurity.com",
9
- "ip_address": "",
10
- "username": "bob@bob.com",
11
- "password": "",
12
- "hashed_password": "$2a$12$pVmwJ7pXEr3mE.DmCCE4fOUDdeadbeefd2KuCy/tq1ZUFyEOH2bve",
13
- "name": "Bob Smith",
14
- "vin": "",
15
- "address": "",
16
- "phone": "+91283423839",
17
- "database_name": "eatstreet",
18
- },
19
- {
20
- "id": "234623453454",
21
- "email": "tim@blacklanternsecurity.com",
22
- "ip_address": "",
23
- "username": "timmy",
24
- "password": "TimTamSlam69",
25
- "hashed_password": "",
26
- "name": "Tim Tam",
27
- "vin": "",
28
- "address": "",
29
- "phone": "+123455667",
30
- "database_name": "eatstreet",
31
- },
32
- ],
33
- "success": True,
34
- "took": "61µs",
35
- "total": 2,
36
- }
37
-
38
3
 
39
4
  class TestDehashed(ModuleTestBase):
40
5
  modules_overrides = ["dehashed", "speculate"]
41
6
  config_overrides = {
42
7
  "scope": {"report_distance": 2},
43
- "modules": {"dehashed": {"username": "admin", "api_key": "deadbeef"}},
8
+ "modules": {"dehashed": {"api_key": "deadbeef"}},
44
9
  }
45
10
 
46
11
  async def setup_before_prep(self, module_test):
47
12
  module_test.httpx_mock.add_response(
48
- url="https://api.dehashed.com/search?query=domain:blacklanternsecurity.com&size=10000&page=1",
49
- json=dehashed_domain_response,
13
+ url="https://api.dehashed.com/v2/search",
14
+ method="POST",
15
+ json={
16
+ "balance": 10000,
17
+ "entries": [
18
+ {
19
+ "id": "4363462346",
20
+ "email": ["bob@blacklanternsecurity.com"],
21
+ "ip_address": ["127.0.0.9"],
22
+ "username": ["bob@bob.com"],
23
+ "hashed_password": ["$2a$12$pVmwJ7pXEr3mE.DmCCE4fOUDdeadbeefd2KuCy/tq1ZUFyEOH2bve"],
24
+ "name": ["Bob Smith"],
25
+ "phone": ["+91283423839"],
26
+ "database_name": "eatstreet",
27
+ "raw_record": {"le_only": True, "unstructured": True},
28
+ },
29
+ {
30
+ "id": "234623453454",
31
+ "email": ["tim@blacklanternsecurity.com"],
32
+ "username": ["timmy"],
33
+ "password": ["TimTamSlam69"],
34
+ "name": "Tim Tam",
35
+ "phone": ["+123455667"],
36
+ "database_name": "eatstreet",
37
+ },
38
+ ],
39
+ "took": "61ms",
40
+ "total": 2,
41
+ },
50
42
  )
51
43
  await module_test.mock_dns(
52
44
  {
@@ -100,3 +92,68 @@ class TestDehashed(ModuleTestBase):
100
92
  [e for e in events if e.type == "PASSWORD" and e.data == "tim@blacklanternsecurity.com:TimTamSlam69"]
101
93
  )
102
94
  assert 1 == len([e for e in events if e.type == "USERNAME" and e.data == "tim@blacklanternsecurity.com:timmy"])
95
+
96
+
97
+ class TestDehashedBadEmail(TestDehashed):
98
+ async def setup_before_prep(self, module_test):
99
+ module_test.httpx_mock.add_response(
100
+ url="https://api.dehashed.com/v2/search",
101
+ method="POST",
102
+ json={
103
+ "balance": 10000,
104
+ "entries": [
105
+ {
106
+ "id": "EZxg4Lz-INLUt6uRXZaV",
107
+ "email": ["foo.example.com"],
108
+ "database_name": "Collections",
109
+ },
110
+ ],
111
+ "took": "41ms",
112
+ "total": 1,
113
+ },
114
+ )
115
+
116
+ def check(self, module_test, events):
117
+ debug_log_content = open(module_test.scan.home / "debug.log").read()
118
+ assert "Invalid email from dehashed.com: foo.example.com" in debug_log_content
119
+
120
+
121
+ class TestDehashedHTTPError(TestDehashed):
122
+ async def setup_before_prep(self, module_test):
123
+ module_test.httpx_mock.add_response(
124
+ url="https://api.dehashed.com/v2/search",
125
+ method="POST",
126
+ json={"error": "issue with request body"},
127
+ status_code=400,
128
+ )
129
+
130
+ def check(self, module_test, events):
131
+ scan_log_content = open(module_test.scan.home / "scan.log").read()
132
+ assert (
133
+ 'Error retrieving results from dehashed.com (status code 400): {"error":"issue with request body"}'
134
+ in scan_log_content
135
+ )
136
+
137
+
138
+ class TestDehashedTooManyResults(TestDehashed):
139
+ async def setup_before_prep(self, module_test):
140
+ module_test.httpx_mock.add_response(
141
+ url="https://api.dehashed.com/v2/search",
142
+ method="POST",
143
+ json={
144
+ "balance": 10000,
145
+ "entries": [
146
+ {
147
+ "id": "VXhNxj46SGsW4Lworh-G",
148
+ "email": ["bob@bob.com"],
149
+ "database_name": "Collections",
150
+ },
151
+ ],
152
+ "took": "40ms",
153
+ "total": 10001,
154
+ },
155
+ )
156
+
157
+ def check(self, module_test, events):
158
+ scan_log_content = open(module_test.scan.home / "scan.log").read()
159
+ assert "has 10,001 results in Dehashed. The API can only process the first 10,000 results." in scan_log_content
@@ -0,0 +1,138 @@
1
+ from .base import ModuleTestBase
2
+
3
+
4
+ class TestGithub_Usersearch(ModuleTestBase):
5
+ config_overrides = {"modules": {"github_usersearch": {"api_key": "asdf"}}}
6
+ query_1 = """query search_users {
7
+ search(query: "blacklanternsecurity.com", type: USER, first: 100, after: "") {
8
+ userCount
9
+ pageInfo {
10
+ hasNextPage
11
+ endCursor
12
+ }
13
+ edges {
14
+ node {
15
+ ... on User {
16
+ login
17
+ # bio Commented out as user can add arbritrary domains to their bio
18
+ email # Email is verified by github
19
+ websiteUrl # Website is not verified by github
20
+ }
21
+ }
22
+ }
23
+ }
24
+ }"""
25
+ query_2 = """query search_users {
26
+ search(query: "blacklanternsecurity.com", type: USER, first: 100, after: "Y3Vyc29yOjUz") {
27
+ userCount
28
+ pageInfo {
29
+ hasNextPage
30
+ endCursor
31
+ }
32
+ edges {
33
+ node {
34
+ ... on User {
35
+ login
36
+ # bio Commented out as user can add arbritrary domains to their bio
37
+ email # Email is verified by github
38
+ websiteUrl # Website is not verified by github
39
+ }
40
+ }
41
+ }
42
+ }
43
+ }"""
44
+
45
+ async def setup_before_prep(self, module_test):
46
+ module_test.httpx_mock.add_response(url="https://api.github.com/zen")
47
+ module_test.httpx_mock.add_response(
48
+ url="https://api.github.com/graphql",
49
+ match_headers={"Authorization": "token asdf"},
50
+ match_json={"query": self.query_1},
51
+ json={
52
+ "data": {
53
+ "search": {
54
+ "userCount": 2,
55
+ "pageInfo": {"hasNextPage": True, "endCursor": "Y3Vyc29yOjUz"},
56
+ "edges": [
57
+ {
58
+ "node": {
59
+ "login": "user_one",
60
+ "email": "test@blacklanternsecurity.com",
61
+ "websiteUrl": None,
62
+ }
63
+ },
64
+ {"node": {"login": "user_two", "email": None, "websiteUrl": None}},
65
+ ],
66
+ }
67
+ }
68
+ },
69
+ )
70
+ module_test.httpx_mock.add_response(
71
+ url="https://api.github.com/graphql",
72
+ match_headers={"Authorization": "token asdf"},
73
+ match_json={"query": self.query_2},
74
+ json={
75
+ "data": {
76
+ "search": {
77
+ "userCount": 1,
78
+ "pageInfo": {"hasNextPage": False, "endCursor": "Y3Vyc29yOjU"},
79
+ "edges": [
80
+ {
81
+ "node": {
82
+ "login": "user_three",
83
+ "email": None,
84
+ "websiteUrl": "https://blog.blacklanternsecurity.com",
85
+ }
86
+ }
87
+ ],
88
+ }
89
+ }
90
+ },
91
+ )
92
+
93
+ def check(self, module_test, events):
94
+ assert 1 == len(
95
+ [
96
+ e
97
+ for e in events
98
+ if e.type == "SOCIAL"
99
+ and e.data["platform"] == "github"
100
+ and e.data["profile_name"] == "user_one"
101
+ and str(e.module) == "github_usersearch"
102
+ and "github-org-member" in e.tags
103
+ and e.scope_distance == 1
104
+ ]
105
+ ), "Failed to find user_one github"
106
+ assert 1 == len(
107
+ [
108
+ e
109
+ for e in events
110
+ if e.type == "EMAIL_ADDRESS"
111
+ and e.data == "test@blacklanternsecurity.com"
112
+ and str(e.module) == "github_usersearch"
113
+ ]
114
+ ), "Failed to find email address for user_one"
115
+ assert 0 == len(
116
+ [
117
+ e
118
+ for e in events
119
+ if e.type == "SOCIAL"
120
+ and e.data["platform"] == "github"
121
+ and e.data["profile_name"] == "user_two"
122
+ and str(e.module) == "github_usersearch"
123
+ and "github-org-member" in e.tags
124
+ and e.scope_distance == 1
125
+ ]
126
+ ), "user_two should not be in scope due to no email or website"
127
+ assert 1 == len(
128
+ [
129
+ e
130
+ for e in events
131
+ if e.type == "SOCIAL"
132
+ and e.data["platform"] == "github"
133
+ and e.data["profile_name"] == "user_three"
134
+ and str(e.module) == "github_usersearch"
135
+ and "github-org-member" in e.tags
136
+ and e.scope_distance == 1
137
+ ]
138
+ ), "Failed to find user_three github"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: bbot
3
- Version: 2.4.2.6611rc0
3
+ Version: 2.4.2.6621rc0
4
4
  Summary: OSINT automation for hackers.
5
5
  License: GPL-3.0
6
6
  Keywords: python,cli,automation,osint,threat-intel,intelligence,neo4j,scanner,python-library,hacking,recursion,pentesting,recon,command-line-tool,bugbounty,subdomains,security-tools,subdomain-scanner,osint-framework,attack-surface,subdomain-enumeration,osint-tool
@@ -1,4 +1,4 @@
1
- bbot/__init__.py,sha256=Sj6Ww0s5mr9AjzAEu-u6gU8g5aBo7xw-OHJg-aVo95Q,163
1
+ bbot/__init__.py,sha256=DK7EeAVAAynkbWC2Q4Rv1ao4pXjaeTKcViVbLcWeK0Q,163
2
2
  bbot/cli.py,sha256=1QJbANVw9Q3GFM92H2QRV2ds5756ulm08CDZwzwPpeI,11888
3
3
  bbot/core/__init__.py,sha256=l255GJE_DvUnWvrRb0J5lG-iMztJ8zVvoweDOfegGtI,46
4
4
  bbot/core/config/__init__.py,sha256=zYNw2Me6tsEr8hOOkLb4BQ97GB7Kis2k--G81S8vofU,342
@@ -83,7 +83,7 @@ bbot/modules/code_repository.py,sha256=x70Z45VnNNMF8BPkHfGWZXsZXw_fStGB3y0-8jbP1
83
83
  bbot/modules/credshed.py,sha256=HAF5wgRGKIIpdMAe4mIAtkZRLmFYjMFyXtjjst6RJ20,4203
84
84
  bbot/modules/crt.py,sha256=6Zm90VKXwYYN6Sab0gwwhTARrtnQIqALJTVtFWMMTGk,1369
85
85
  bbot/modules/crt_db.py,sha256=xaIm2457_xGJjnKss73l1HpPn7pLPHksVzejsimTfZA,2198
86
- bbot/modules/dehashed.py,sha256=iyzWHmJs6zC7FsRhw9_AdkckQKCf_0oNnL9RwG409r0,5071
86
+ bbot/modules/dehashed.py,sha256=0lzcqMEgwRmprwurZ2-8Y8aOO4KTueJgpY_vh0DWQwA,5155
87
87
  bbot/modules/digitorus.py,sha256=XQY0eAQrA7yo8S57tGncP1ARud-yG4LiWxx5VBYID34,1027
88
88
  bbot/modules/dnsbimi.py,sha256=A4cqhvhytmEEd-tY4CgFwMLbsVtMjkRY9238Aj8aVtU,6921
89
89
  bbot/modules/dnsbrute.py,sha256=Y2bSbG2IcwIJID1FSQ6Qe9fdpWwG7GIO-wVQw7MdQFM,2439
@@ -108,6 +108,7 @@ bbot/modules/git_clone.py,sha256=XFZXx0k97EMY3E5PZzdNvqQzZddOfRMaVp5ol2gk11s,246
108
108
  bbot/modules/gitdumper.py,sha256=XBYt6oSXm09FJVdH37zrn9T1Nhqc0zK4KLugMevedOw,11531
109
109
  bbot/modules/github_codesearch.py,sha256=a-r2vE9N9WyBpFUiKCsg0TK4Qn7DaEGyVRTUKzkDLWA,3641
110
110
  bbot/modules/github_org.py,sha256=WM18vJCHuOHJJ5rPzQzQ3Pmp7XPPuaMeVgNfW-FlO0k,8938
111
+ bbot/modules/github_usersearch.py,sha256=G8knkQBJsn7EKcMhcEaFPiB_Y5S96e2VaseBubsqOyk,3407
111
112
  bbot/modules/github_workflows.py,sha256=RDtzR0DC2sqiWzMtiqlrCSwtZHWL2MoIJBKd6LVTAdI,9720
112
113
  bbot/modules/gitlab.py,sha256=9oWWpBijeHCjuFBfWW4HvNqt7bvJvrBgBjaaz_UPPnE,5964
113
114
  bbot/modules/google_playstore.py,sha256=N4QjzQag_bgDXfX17rytBiiWA-SQtYI2N0J_ZNEOdv0,3701
@@ -199,7 +200,7 @@ bbot/modules/subdomaincenter.py,sha256=aWjcIqGGWnAj2ePwcS4sgUJDUsq0trY3Klhr_lcc4
199
200
  bbot/modules/subdomainradar.py,sha256=YlRNMtNGLpa13KZ7aksAMVZdSjxe1tkywU5RXlwXpPc,6784
200
201
  bbot/modules/telerik.py,sha256=i9Zy2JZXLrmwSslFzVFVWApQNwTwNcrGsb_UxBuCtkI,18905
201
202
  bbot/modules/templates/bucket.py,sha256=muLPpfAGtcNhL0tLU-qHTlTNIz4yncRcVjdZMqVRtUI,7153
202
- bbot/modules/templates/github.py,sha256=n6cVjf62ezkztCRAcXNnlxfCkB0VRWqn138mOOt6T08,1454
203
+ bbot/modules/templates/github.py,sha256=lrV1EYPqjtPkJsS0fQfqmLvGchNo_fO3A75W9-03gxY,2531
203
204
  bbot/modules/templates/postman.py,sha256=MIpz2q_r6LP0kIEgByo7oX5qHhMZLOhr7oKzJI9Beec,6959
204
205
  bbot/modules/templates/shodan.py,sha256=MXBvlmfw3jZFqT47v10UkqMSyQR-zBIxMJmK7PWw6uw,1174
205
206
  bbot/modules/templates/sql.py,sha256=o-CdyyoJvHJdJBKkj3CIGXYxUta4w2AB_2Vr-k7cDDU,3553
@@ -329,7 +330,7 @@ bbot/test/test_step_2/module_tests/test_module_credshed.py,sha256=ipkCFL7YmZBLWW
329
330
  bbot/test/test_step_2/module_tests/test_module_crt.py,sha256=V15tE1jcXdXJEzEEdAJvSMRWhKBFtxBBUJ_eewvV3U4,717
330
331
  bbot/test/test_step_2/module_tests/test_module_crt_db.py,sha256=R0CvLnzhN5T7XNPVSDRYD9vSwYMTNED6w-EPGoWPVII,849
331
332
  bbot/test/test_step_2/module_tests/test_module_csv.py,sha256=UJqMqdiPjx-UjJw10OoVMAj378wu5mWIq0v04TCljTM,579
332
- bbot/test/test_step_2/module_tests/test_module_dehashed.py,sha256=BZ0LFO4xBwDsXzsqjZCYRMTbXdwwUEma2OeJh8YQIEs,3625
333
+ bbot/test/test_step_2/module_tests/test_module_dehashed.py,sha256=Oi2McmPf873xWWUahYNh-CquDfLFamATyODjAZL33vU,6009
333
334
  bbot/test/test_step_2/module_tests/test_module_digitorus.py,sha256=1GwxQGny6TxHsV8Fx7cR-aaLU8ZZkcF065VM_XoG1Hs,1612
334
335
  bbot/test/test_step_2/module_tests/test_module_discord.py,sha256=Z66fGb-kkdZTQfUh6WZiM35Ad-gDyvwxlA7mUUB2vnQ,1838
335
336
  bbot/test/test_step_2/module_tests/test_module_dnsbimi.py,sha256=nAhNAuH2hS7r4KYzhuPMocae1ifoIRMESYio8L577lg,4393
@@ -358,6 +359,7 @@ bbot/test/test_step_2/module_tests/test_module_git_clone.py,sha256=Mo0Q7bCXcrkGW
358
359
  bbot/test/test_step_2/module_tests/test_module_gitdumper.py,sha256=ya_eQUQk0344G7iqBYMls2z5H-bYM87rydbz-ACR2Ng,17461
359
360
  bbot/test/test_step_2/module_tests/test_module_github_codesearch.py,sha256=M50xBiGG2EuPGXDJU6uFsSUE-fhqZl3CzYtNdszW7LM,4735
360
361
  bbot/test/test_step_2/module_tests/test_module_github_org.py,sha256=5tKO6NH4TPBeIdeTf7Bz9PUZ1pcvKsjrG0nFhc3YgT0,25458
362
+ bbot/test/test_step_2/module_tests/test_module_github_usersearch.py,sha256=IIQ0tYZjQN8_L8u_N4m8Nz3kbB4IyBp95tYCPcQeScg,5264
361
363
  bbot/test/test_step_2/module_tests/test_module_github_workflows.py,sha256=o_teEaskm3H22QEKod5KJayFvvcgOQoG4eItGWv8C8E,38006
362
364
  bbot/test/test_step_2/module_tests/test_module_gitlab.py,sha256=fnwE7BWTU6EQquKdGLCiaX_LwVwvzOLev3Y9GheTLSY,11859
363
365
  bbot/test/test_step_2/module_tests/test_module_google_playstore.py,sha256=uTRqpAGI9HI-rOk_6jdV44OoSqi0QQQ3aTVzvuV0dtc,3034
@@ -448,8 +450,8 @@ bbot/wordlists/raft-small-extensions-lowercase_CLEANED.txt,sha256=ZSIVebs7ptMvHx
448
450
  bbot/wordlists/top_open_ports_nmap.txt,sha256=LmdFYkfapSxn1pVuQC2LkOIY2hMLgG-Xts7DVtYzweM,42727
449
451
  bbot/wordlists/valid_url_schemes.txt,sha256=0B_VAr9Dv7aYhwi6JSBDU-3M76vNtzN0qEC_RNLo7HE,3310
450
452
  bbot/wordlists/wordninja_dns.txt.gz,sha256=DYHvvfW0TvzrVwyprqODAk4tGOxv5ezNmCPSdPuDUnQ,570241
451
- bbot-2.4.2.6611rc0.dist-info/LICENSE,sha256=GzeCzK17hhQQDNow0_r0L8OfLpeTKQjFQwBQU7ZUymg,32473
452
- bbot-2.4.2.6611rc0.dist-info/METADATA,sha256=LDoYczD9e_LGiKrrwmi9WHdJDFoT_v57p5oNaJAFfIc,18308
453
- bbot-2.4.2.6611rc0.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
454
- bbot-2.4.2.6611rc0.dist-info/entry_points.txt,sha256=cWjvcU_lLrzzJgjcjF7yeGuRA_eDS8pQ-kmPUAyOBfo,38
455
- bbot-2.4.2.6611rc0.dist-info/RECORD,,
453
+ bbot-2.4.2.6621rc0.dist-info/LICENSE,sha256=GzeCzK17hhQQDNow0_r0L8OfLpeTKQjFQwBQU7ZUymg,32473
454
+ bbot-2.4.2.6621rc0.dist-info/METADATA,sha256=XpdUo5_30J3J3EJUgjM3a3VpninDPABYKWDJRVqxvqk,18308
455
+ bbot-2.4.2.6621rc0.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
456
+ bbot-2.4.2.6621rc0.dist-info/entry_points.txt,sha256=cWjvcU_lLrzzJgjcjF7yeGuRA_eDS8pQ-kmPUAyOBfo,38
457
+ bbot-2.4.2.6621rc0.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 2.1.2
2
+ Generator: poetry-core 2.1.3
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any