Skip to content

Commit edf9619

Browse files
fix target bug
1 parent 0aa66e3 commit edf9619

2 files changed

Lines changed: 55 additions & 1 deletion

File tree

bbot_server/modules/targets/targets_api.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ async def refresh_asset_scope(self, host: str, target: BBOTTarget, target_id: UU
113113
scope_result_type = getattr(scope_result, "type", None)
114114
if scope_result_type == "NEW_IN_SCOPE_ASSET":
115115
asset_scope = sorted(set(asset_scope) | set([target_id]))
116-
else:
116+
elif scope_result_type == "ASSET_SCOPE_CHANGED":
117117
asset_scope = sorted(set(asset_scope) - set([target_id]))
118118
asset_results = await self.root.assets.collection.update_many(
119119
{"host": host},

tests/test_applets/test_applet_targets.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -491,6 +491,60 @@ async def after_archive(self):
491491
pass
492492

493493

494+
class TestTargetAddDomainPreservesExistingScope(BaseAppletTest):
495+
"""
496+
Regression test for bug where adding a domain to an existing target
497+
caused all previously-in-scope assets to lose their scope, leaving only
498+
the newly added domain in scope.
499+
500+
Root cause: refresh_asset_scope treated a None return from _check_scope
501+
(meaning "no change") as "out of scope", incorrectly removing the target
502+
from assets that were already in scope.
503+
"""
504+
505+
needs_worker = True
506+
507+
async def setup(self):
508+
assert await self.bbot_server.get_hosts() == []
509+
assert await self.bbot_server.get_targets() == []
510+
511+
# create a target with just evilcorp.com
512+
self.target = await self.bbot_server.create_target(
513+
name="evilcorp",
514+
description="evilcorp target",
515+
target=["evilcorp.com"],
516+
)
517+
518+
async def after_scan_1(self):
519+
# verify evilcorp.com assets are in scope
520+
assets = [a async for a in self.bbot_server.list_assets()]
521+
target_assets = {a.host for a in assets if self.target.id in a.scope}
522+
assert "evilcorp.com" in target_assets
523+
assert len(target_assets) > 1, f"Expected multiple evilcorp.com assets in scope, got: {target_assets}"
524+
self.original_target_assets = target_assets
525+
526+
# BUG REPRODUCTION: add a new domain to the target while keeping the existing one
527+
self.target.target = ["evilcorp.com", "testevilcorp.com"]
528+
await self.bbot_server.update_target(self.target.id, self.target)
529+
await asyncio.sleep(1.0)
530+
531+
# verify that existing evilcorp.com assets are STILL in scope
532+
assets = [a async for a in self.bbot_server.list_assets()]
533+
target_assets_after = {a.host for a in assets if self.target.id in a.scope}
534+
535+
# the new domain should also be in scope
536+
assert "testevilcorp.com" in target_assets_after, (
537+
f"Newly added domain testevilcorp.com should be in scope, got: {target_assets_after}"
538+
)
539+
540+
# all previously in-scope assets should still be in scope
541+
missing = self.original_target_assets - target_assets_after
542+
assert not missing, (
543+
f"BUG: These assets lost their scope after adding a domain to the target: {missing}. "
544+
f"Before: {self.original_target_assets}, After: {target_assets_after}"
545+
)
546+
547+
494548
class TestTargetUpdateRemovesTargetFromAssets(BaseAppletTest):
495549
"""
496550
Regression test for bug where editing or deleting a target to remove a domain

0 commit comments

Comments
 (0)