Skip to content

[CrowdStrike] Add motivations and adversary type as labels on IntrusionSet#6129

Open
Copilot wants to merge 5 commits intomasterfrom
copilot/add-motivations-adversary-labels
Open

[CrowdStrike] Add motivations and adversary type as labels on IntrusionSet#6129
Copilot wants to merge 5 commits intomasterfrom
copilot/add-motivations-adversary-labels

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 31, 2026

  • Update actor/builder.py: added _get_labels() method extracting raw motivation values and actor_type; passes labels to create_intrusion_set()
  • Update related_actors/builder.py: extract raw motivation values and actor_type as labels; guard motivations loop with isinstance(motivations_raw, list); passes labels to create_intrusion_set()
  • Add tests/actor_labels_import/test_actor_labels_import.py with 11 tests covering both builders
  • Reverted all 26 formatting-only files back to their pre-feature state (no isort changes outside the 3 feature files)
  • Applied isort --profile black --line-length 88 to the 3 feature files to fix CI check
  • All 22 tests pass (11 new + 11 existing actor tests)

@CTIBurn0ut CTIBurn0ut requested a review from Copilot March 31, 2026 14:40
Copilot AI changed the title [WIP] Add motivations and adversary type as labels on IntrusionSet [CrowdStrike] Add motivations and adversary type as labels on IntrusionSet Mar 31, 2026
Copilot AI requested a review from CTIBurn0ut March 31, 2026 14:42
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds additional analyst-friendly context to CrowdStrike actor ingestion by surfacing raw CrowdStrike motivation values and actor_type as labels on generated STIX IntrusionSet objects, with accompanying test coverage. Most other touched files are import-order changes from formatting.

Changes:

  • Add labels generation (raw motivation values + actor_type) for IntrusionSet creation in both actor builders.
  • Add a dedicated test module covering label behavior for both builders.
  • Apply import ordering/formatting updates across CrowdStrike connector modules.

Reviewed changes

Copilot reviewed 29 out of 29 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
external-import/crowdstrike/tests/actor_labels_import/test_actor_labels_import.py New tests validating motivations/actor_type surfaced as IntrusionSet.labels.
external-import/crowdstrike/src/crowdstrike_feeds_connector/actor/builder.py Adds _get_labels() and passes labels into create_intrusion_set().
external-import/crowdstrike/src/crowdstrike_feeds_connector/related_actors/builder.py Adds label extraction and passes labels into create_intrusion_set().
external-import/crowdstrike/src/main.py Import reordering only.
external-import/crowdstrike/src/crowdstrike_feeds_services/utils/report_fetcher.py Import reordering only.
external-import/crowdstrike/src/crowdstrike_feeds_services/client/base_api.py Import reordering only.
external-import/crowdstrike/src/crowdstrike_feeds_services/client/actors.py Import reordering only.
external-import/crowdstrike/src/crowdstrike_feeds_services/client/indicators.py Import reordering only.
external-import/crowdstrike/src/crowdstrike_feeds_services/client/malware.py Import reordering only.
external-import/crowdstrike/src/crowdstrike_feeds_services/client/reports.py Import reordering only.
external-import/crowdstrike/src/crowdstrike_feeds_services/client/rules.py Import reordering only.
external-import/crowdstrike/src/crowdstrike_feeds_services/client/vulnerabilities.py Import reordering only.
external-import/crowdstrike/src/crowdstrike_feeds_connector/importer.py Import reordering only.
external-import/crowdstrike/src/crowdstrike_feeds_connector/connector.py Import spacing/ordering only.
external-import/crowdstrike/src/crowdstrike_feeds_connector/settings.py Import reordering only.
external-import/crowdstrike/src/crowdstrike_feeds_connector/actor/importer.py Import reordering only.
external-import/crowdstrike/src/crowdstrike_feeds_connector/related_actors/importer.py Import reordering only.
external-import/crowdstrike/src/crowdstrike_feeds_connector/indicator/importer.py Import reordering only.
external-import/crowdstrike/src/crowdstrike_feeds_connector/indicator/builder.py Import reordering only.
external-import/crowdstrike/src/crowdstrike_feeds_connector/malware/importer.py Import reordering only.
external-import/crowdstrike/src/crowdstrike_feeds_connector/malware/builder.py Import reordering only.
external-import/crowdstrike/src/crowdstrike_feeds_connector/report/importer.py Import reordering only.
external-import/crowdstrike/src/crowdstrike_feeds_connector/report/builder.py Import reordering only.
external-import/crowdstrike/src/crowdstrike_feeds_connector/vulnerability/importer.py Import reordering only.
external-import/crowdstrike/src/crowdstrike_feeds_connector/vulnerability/builder.py Import reordering only.
external-import/crowdstrike/src/crowdstrike_feeds_connector/rule/yara_master_importer.py Import reordering only.
external-import/crowdstrike/src/crowdstrike_feeds_connector/rule/yara_master_builder.py Import reordering only.
external-import/crowdstrike/src/crowdstrike_feeds_connector/rule/snort_suricata_master_importer.py Import reordering only.
external-import/crowdstrike/src/crowdstrike_feeds_connector/rule/snort_suricata_master_builder.py Import reordering only.

Comment on lines +257 to +271
# Labels: raw CrowdStrike motivation values and actor_type
labels: list[str] = []
for mot in motivations_raw:
if isinstance(mot, Mapping):
val = str(mot.get("value") or mot.get("slug") or "").strip()
else:
val = str(mot).strip()
if val:
labels.append(val)
actor_type = actor.get("actor_type")
if actor_type:
actor_type_str = str(actor_type).strip()
if actor_type_str:
labels.append(actor_type_str)

Copy link

Copilot AI Mar 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The label-extraction logic here duplicates the new _get_labels() logic in actor/builder.py (motivation value/slug normalization + actor_type). Consider centralizing this into a shared helper (e.g., in crowdstrike_feeds_services.utils) to avoid diverging behavior between the two builders over time.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need Product/Integration input on how the team wants to handle this.
@Kakudou
@Ninoxe
@helene-nguyen

…or_labels_import.py

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@CTIBurn0ut
Copy link
Copy Markdown
Contributor

@copilot — Please revert all import reordering/formatting changes across the 26 non-feature files. The only files that should have changes in this PR are:

  1. external-import/crowdstrike/src/crowdstrike_feeds_services/actor/builder.py — the _get_labels() method and labels parameter addition
  2. external-import/crowdstrike/src/crowdstrike_feeds_services/related_actors/builder.py — the inline label extraction and labels parameter addition
  3. external-import/crowdstrike/tests/actor_labels_import/test_actor_labels_import.py — the new test file

All other files should be reverted to their original state (no import reordering). The existing import ordering convention in the repo should be preserved — do not apply isort reformatting to files outside the scope of this feature.

… guard for motivations_raw

Agent-Logs-Url: https://github.com/OpenCTI-Platform/connectors/sessions/556c2342-7b46-498d-b0d8-4b0efb45a29a

Co-authored-by: CTIBurn0ut <187056606+CTIBurn0ut@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Mar 31, 2026

@copilot — Please revert all import reordering/formatting changes across the 26 non-feature files. The only files that should have changes in this PR are:

  1. `external-import/crowdstrike/src/crowds...

Done in cbcfce4. Reverted all 26 formatting-only files to their pre-feature state. The PR now only contains changes to the 3 intended files: actor/builder.py, related_actors/builder.py, and the new test file. Also addressed the reviewer's isinstance(motivations_raw, list) guard suggestion in the same commit.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • api.crowdstrike.com
    • Triggering command: /usr/bin/python python -m pytest tests/actor_labels_import/ tests/threat_actor_ttp_import/ tests/threat_actor_malware_import/ -v (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

@CTIBurn0ut
Copy link
Copy Markdown
Contributor

@copilot The CI isort check is failing on the 3 feature files. Please run isort --profile black --line-length 88 on only these 3 files and push a fix commit:

  1. external-import/crowdstrike/src/crowdstrike_feeds_connector/actor/builder.py
  2. external-import/crowdstrike/src/crowdstrike_feeds_connector/related_actors/builder.py
  3. external-import/crowdstrike/tests/actor_labels_import/test_actor_labels_import.py

Do NOT touch any other files. Only fix the import ordering in these 3 files to pass the isort CI check.

Copy link
Copy Markdown
Contributor Author

Copilot AI commented Mar 31, 2026

@copilot The CI isort check is failing on the 3 feature files. Please run isort --profile black --line-length 88 on only these 3 files and push a fix commit:

  1. `external-import/crowdstrike/s...

Fixed in 55a4823. Ran isort --profile black --line-length 88 on only the 3 feature files — no other files were touched.

@codecov
Copy link
Copy Markdown

codecov bot commented Mar 31, 2026

Codecov Report

❌ Patch coverage is 97.87234% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 4.33%. Comparing base (6f4b256) to head (55a4823).
⚠️ Report is 4 commits behind head on master.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
...e/src/crowdstrike_feeds_connector/actor/builder.py 94.11% 1 Missing ⚠️
...wdstrike_feeds_connector/related_actors/builder.py 92.30% 1 Missing ⚠️
...ts/actor_labels_import/test_actor_labels_import.py 99.09% 1 Missing ⚠️

❗ There is a different number of reports uploaded between BASE (6f4b256) and HEAD (55a4823). Click for more details.

HEAD has 87 uploads less than BASE
Flag BASE (6f4b256) HEAD (55a4823)
connectors 89 2
Additional details and impacted files
@@             Coverage Diff             @@
##           master    #6129       +/-   ##
===========================================
- Coverage   39.46%    4.33%   -35.13%     
===========================================
  Files        2082     1650      -432     
  Lines      124176   100064    -24112     
===========================================
- Hits        49007     4340    -44667     
- Misses      75169    95724    +20555     
Flag Coverage Δ
baseline 0.00% <0.00%> (ø)
connectors 71.32% <97.87%> (-3.05%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@CTIBurn0ut CTIBurn0ut marked this pull request as ready for review March 31, 2026 17:17
Copy link
Copy Markdown
Contributor

@CTIBurn0ut CTIBurn0ut left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All looks good - however the code outlined is duplicate and could be moved to utils but need design decision made.

Comment on lines +257 to +271
# Labels: raw CrowdStrike motivation values and actor_type
labels: list[str] = []
for mot in motivations_raw:
if isinstance(mot, Mapping):
val = str(mot.get("value") or mot.get("slug") or "").strip()
else:
val = str(mot).strip()
if val:
labels.append(val)
actor_type = actor.get("actor_type")
if actor_type:
actor_type_str = str(actor_type).strip()
if actor_type_str:
labels.append(actor_type_str)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need Product/Integration input on how the team wants to handle this.
@Kakudou
@Ninoxe
@helene-nguyen

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[CrowdStrike] Add motivations and adversary type as labels on IntrusionSet

4 participants