@@ -482,15 +482,68 @@ async def after_scan_2(self):
482482 assets = [a async for a in self .bbot_server .list_assets ()]
483483
484484 # evilcorp.azure.com (127.0.0.3) and evilcorp.amazonaws.com (127.0.0.4) are now part of the target
485- # 127.0.0.1 no longer exists (it is nowhere to be found in scan 2)
486485 # localhost.evilcorp.com (127.0.0.2) is still blacklisted
487486 target_2_assets = {a .host for a in assets if self .target2 .id in a .scope }
488- assert target_2_assets == {"evilcorp.azure.com" , "evilcorp.amazonaws.com" }
487+ assert target_2_assets == {"127.0.0.1" , " evilcorp.azure.com" , "evilcorp.amazonaws.com" }
489488
490489 async def after_archive (self ):
491490 pass
492491
493492
493+ class TestTargetAddDomainPreservesExistingScope (BaseAppletTest ):
494+ """
495+ Regression test for bug where adding a domain to an existing target
496+ caused all previously-in-scope assets to lose their scope, leaving only
497+ the newly added domain in scope.
498+
499+ Root cause: refresh_asset_scope treated a None return from _check_scope
500+ (meaning "no change") as "out of scope", incorrectly removing the target
501+ from assets that were already in scope.
502+ """
503+
504+ needs_worker = True
505+
506+ async def setup (self ):
507+ assert await self .bbot_server .get_hosts () == []
508+ assert await self .bbot_server .get_targets () == []
509+
510+ # create a target with just evilcorp.com
511+ self .target = await self .bbot_server .create_target (
512+ name = "evilcorp" ,
513+ description = "evilcorp target" ,
514+ target = ["evilcorp.com" ],
515+ )
516+
517+ async def after_scan_1 (self ):
518+ # verify evilcorp.com assets are in scope
519+ assets = [a async for a in self .bbot_server .list_assets ()]
520+ target_assets = {a .host for a in assets if self .target .id in a .scope }
521+ assert "evilcorp.com" in target_assets
522+ assert len (target_assets ) > 1 , f"Expected multiple evilcorp.com assets in scope, got: { target_assets } "
523+ self .original_target_assets = target_assets
524+
525+ # BUG REPRODUCTION: add a new domain to the target while keeping the existing one
526+ self .target .target = ["evilcorp.com" , "testevilcorp.com" ]
527+ await self .bbot_server .update_target (self .target .id , self .target )
528+ await asyncio .sleep (1.0 )
529+
530+ # verify that existing evilcorp.com assets are STILL in scope
531+ assets = [a async for a in self .bbot_server .list_assets ()]
532+ target_assets_after = {a .host for a in assets if self .target .id in a .scope }
533+
534+ # the new domain should also be in scope
535+ assert "testevilcorp.com" in target_assets_after , (
536+ f"Newly added domain testevilcorp.com should be in scope, got: { target_assets_after } "
537+ )
538+
539+ # all previously in-scope assets should still be in scope
540+ missing = self .original_target_assets - target_assets_after
541+ assert not missing , (
542+ f"BUG: These assets lost their scope after adding a domain to the target: { missing } . "
543+ f"Before: { self .original_target_assets } , After: { target_assets_after } "
544+ )
545+
546+
494547class TestTargetUpdateRemovesTargetFromAssets (BaseAppletTest ):
495548 """
496549 Regression test for bug where editing or deleting a target to remove a domain
0 commit comments