fix: restrict payload discovery to resources/ directory (#32)#52
fix: restrict payload discovery to resources/ directory (#32)#52
Conversation
The payload search in _store_required_payloads() uses Path.rglob() which walks the entire adversary-emulation-plans tree and can pick up files from Archive/CALDERA_DIY/evals/payloads instead of the correct Resources/ path. Add _is_resource_path() helper and prioritize Resources/ matches over other locations when copying payloads. Falls back to any match if no Resources/ path is found.
|
There was a problem hiding this comment.
Pull request overview
This PR addresses payload discovery in the emu plugin so that, when duplicate payload names exist across the adversary-emulation-plans repository, payloads under Resources/ are preferred over archived copies (fixing the APT29 mis-selection described in #32) while retaining a fallback to non-Resources/ matches.
Changes:
- Add an
_is_resource_path()helper to identifyResources/-scoped payload paths. - Update
_store_required_payloads()to preferResources/matches when multiple payloads share the same name. - Add unit tests covering preference for
Resources/, fallback behavior, and_is_resource_path().
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| app/emu_svc.py | Adds Resources/-path detection and updates payload discovery ordering to prefer Resources/ matches. |
| tests/test_emu_svc.py | Adds unit tests verifying Resources/ preference, fallback behavior, and _is_resource_path() behavior. |
Comments suppressed due to low confidence (1)
app/emu_svc.py:336
- When one or more Resources/ matches exist, ordered_matches is limited to resource_matches. If copying from all Resources/ locations fails (permissions, transient IO errors), the code will never attempt non-Resources matches even though they may be valid, which reduces the intended backward-compatible fallback behavior. Consider trying resource matches first, and if none copy successfully, then iterating the remaining matches as a fallback.
resource_matches = [p for p in matches if self._is_resource_path(p)]
ordered_matches = resource_matches if resource_matches else matches
for path in ordered_matches:
found = True
target_path = os.path.join(self.payloads_dir, path.name)
try:
shutil.copyfile(path, target_path)
copied = True
break
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| path_str = str(path) | ||
| return 'Resources' + os.sep in path_str or '/Resources/' in path_str |
| matches = list(Path(self.repo_dir).rglob(payload)) | ||
| # Prioritize payloads from Resources/ directories over other locations | ||
| # (e.g. Archive/CALDERA_DIY/evals/payloads) to avoid loading wrong files. | ||
| resource_matches = [p for p in matches if self._is_resource_path(p)] | ||
| ordered_matches = resource_matches if resource_matches else matches | ||
| for path in ordered_matches: |




Summary
_is_resource_path()helper to prioritizeResources/directory matches during payload discoveryResources/path exists, preserving backward compatibilityTest plan
_is_resource_path()helper