@@ -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+
494548class TestTargetUpdateRemovesTargetFromAssets (BaseAppletTest ):
495549 """
496550 Regression test for bug where editing or deleting a target to remove a domain
0 commit comments