Skip to content

Commit 8e1e10a

Browse files
Merge pull request #146 from blacklanternsecurity/fix-finding-severity-bug
Better risk tests
2 parents bf9575c + 1f068df commit 8e1e10a

5 files changed

Lines changed: 39 additions & 9 deletions

File tree

bbot_server/store.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
1+
import asyncio
2+
import logging
3+
14
from bbot_server.db.base import BaseDB
25

36
from pymongo import AsyncMongoClient
47
from gridfs import AsyncGridFSBucket
58

9+
log = logging.getLogger(__name__)
10+
611

712
class BaseMongoStore(BaseDB):
813
async def setup(self):
@@ -11,6 +16,14 @@ async def setup(self):
1116
self.collection_prefix = getattr(self.db_config, "collection_prefix", "")
1217
bucket_name = f"{self.collection_prefix}fs" if self.collection_prefix else "fs"
1318
self.fs = AsyncGridFSBucket(self.db, bucket_name=bucket_name)
19+
# verify connectivity with retry (MongoDB may still be starting)
20+
while True:
21+
try:
22+
await self.client.admin.command("ping")
23+
break
24+
except Exception as e:
25+
log.error(f"Failed to connect to MongoDB at {self.uri}: {e}, retrying...")
26+
await asyncio.sleep(1)
1427

1528
async def cleanup(self):
1629
await self.client.close()

bbot_server/worker/worker.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,6 @@ async def _event_listener(self, message: dict) -> None:
7373
else:
7474
event_preview = ""
7575
self.log.info(f"Received event: {event.type}{event_preview}")
76-
# get the event's associated asset (this saves on database queries since it will be passed down to each applet)
7776
asset, _activities = await self._get_or_create_asset(event.host, event=event)
7877
activities.extend(_activities)
7978

@@ -139,7 +138,8 @@ async def _get_or_create_asset(self, host: str, event: Event = None, parent_acti
139138
140139
Returns the asset and a list of activities that were generated (NEW_ASSET if the asset was created).
141140
"""
142-
if not host:
141+
# if there's no host, or if the host is a CIDR, we skip.
142+
if not host or "/" in str(host):
143143
return None, []
144144
activities = []
145145
try:

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "bbot-server"
3-
version = "0.1.5"
3+
version = "0.1.6"
44
description = ""
55
authors = [{name = "TheTechromancer"}]
66
license = "AGPL-3.0"

tests/test_applets/test_applet_findings.py

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,11 @@ async def after_scan_1(self):
6464
assert result["risk"] is None
6565
assert result["risk_override"] == False
6666

67+
# override risk on www2 BEFORE scan 2 (which will add CRITICAL findings)
68+
result = await self.bbot_server.set_risk(host="www2.evilcorp.com", risk=2.0)
69+
assert result["risk"] == 2.0
70+
assert result["risk_override"] == True
71+
6772
async def after_scan_2(self):
6873
findings = [f async for f in self.bbot_server.list_findings()]
6974
assert len(findings) == 4
@@ -194,18 +199,28 @@ async def after_scan_2(self):
194199

195200
# --- risk field tests ---
196201

197-
# after scan 2, www2 and api have CRITICAL findings → CVSS 9.0
202+
# www2 had risk overridden to 2.0 before scan 2 (set in after_scan_1)
203+
# scan 2 added CRITICAL findings to www2, but risk should still be 2.0 because of the override
198204
www2_asset = await self.bbot_server.get_asset(host="www2.evilcorp.com")
199-
assert www2_asset.risk == 9.0
200-
assert www2_asset.risk_override == False
205+
assert www2_asset.risk == 2.0, f"risk should still be 2.0 (overridden), got {www2_asset.risk}"
206+
assert www2_asset.risk_override == True
201207
api_asset = await self.bbot_server.get_asset(host="api.evilcorp.com")
202208
assert api_asset.risk == 9.0
203209
assert api_asset.risk_override == False
210+
204211
# www only had HIGH findings from scan 1 → CVSS 7.0
205212
www_asset = await self.bbot_server.get_asset(host="www.evilcorp.com")
206213
assert www_asset.risk == 7.0
207214
assert www_asset.risk_override == False
208215

216+
# clear the override on www2 — risk should revert to CVSS-derived value (CRITICAL → 9.0)
217+
result = await self.bbot_server.set_risk(host="www2.evilcorp.com")
218+
assert result["risk"] == 9.0, f"Expected risk to revert to 9.0, got {result['risk']}"
219+
assert result["risk_override"] == False
220+
www2_asset = await self.bbot_server.get_asset(host="www2.evilcorp.com")
221+
assert www2_asset.risk == 9.0
222+
assert www2_asset.risk_override == False
223+
209224
# manually set risk on www2 (float 0.0-10.0)
210225
result = await self.bbot_server.set_risk(host="www2.evilcorp.com", risk=7.5)
211226
assert result["risk"] == 7.5
@@ -246,8 +261,10 @@ async def after_scan_2(self):
246261
# verify RISK_UPDATED activities were emitted
247262
# expected: 2 from scan 1 auto-sync (www + www2: None->7.0),
248263
# 4 from after_scan_1 manual set_risk (api: set 5.0, clear, set None, clear),
249-
# 2 from scan 2 auto-sync (www2: 7.0->9.0, api: None->9.0),
264+
# 1 from after_scan_1 override on www2 (7.0->2.0),
265+
# 1 from scan 2 auto-sync (api: None->9.0),
266+
# 1 from after_scan_2 clear override on www2 (2.0->9.0),
250267
# 6 from after_scan_2 manual set_risk (7.5, 3.1, 0.0, 10.0, None, clear)
251268
await asyncio.sleep(1.0)
252269
activities = [a async for a in self.bbot_server.list_activities() if a.type == "RISK_UPDATED"]
253-
assert len(activities) == 14
270+
assert len(activities) == 15

uv.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)