Skip to content

Feature: Add Indicator To AddIOCtoIOCCollectionAction (1315, 1314)#2064

Open
vg-svitla wants to merge 1 commit intodevelopfrom
fix/validation_for_indicators_and_indicator
Open

Feature: Add Indicator To AddIOCtoIOCCollectionAction (1315, 1314)#2064
vg-svitla wants to merge 1 commit intodevelopfrom
fix/validation_for_indicators_and_indicator

Conversation

@vg-svitla
Copy link
Collaborator

@vg-svitla vg-svitla commented Feb 26, 2026

Relates to

Summary by Sourcery

Allow adding a single indicator value to an IOC collection in addition to the existing list-based input and update metadata accordingly.

New Features:

  • Support passing a single indicator field to AddIOCtoIOCCollectionAction alongside the existing indicators list parameter.

Enhancements:

  • Extend AddIOCtoIOCCollectionAction to derive the indicator list from either the indicators array or a single indicator value and validate presence accordingly.

Documentation:

  • Document the new optional indicator field for AddIOCtoIOCCollectionAction in the changelog.

Tests:

  • Add tests covering single IPv4, IPv6, and domain indicators, handling of valid_for, and error behavior when no indicators are provided.

Chores:

  • Bump the Sekoia.io integration manifest version to 2.69.1.

@vg-svitla vg-svitla requested review from a team and squioc February 26, 2026 08:26
@vg-svitla vg-svitla changed the title Feature: Add Indicator To AddIOCtoIOCCollectionAction Feature: Add Indicator To AddIOCtoIOCCollectionAction (1315, 1314) Feb 26, 2026
@sourcery-ai
Copy link
Contributor

sourcery-ai bot commented Feb 26, 2026

Reviewer's Guide

Allow AddIOCtoIOCCollectionAction to accept a single indicator value in addition to a list, and add tests plus metadata updates to cover and document this new behavior.

Sequence diagram for AddIOCtoIOCCollectionAction run logic with list or single indicator

sequenceDiagram
    actor Caller
    participant AddIOCtoIOCCollectionAction as Action

    Caller->>Action: run(arguments)
    activate Action
    Action->>Action: indicators = json_argument("indicators", arguments, required=False)
    Action->>Action: single_indicator = arguments.get("indicator")
    Action->>Action: ioc_collection_id = arguments.get("ioc_collection_id")
    Action->>Action: indicator_type = arguments.get("indicator_type")
    Action->>Action: valid_for = int(arguments.get("valid_for", 0))
    Action->>Action: result_indicators = indicators or [single_indicator]

    alt indicator_type is IP address
        alt indicators is list or single_indicator is set
            Action->>Action: add_IP_action(result_indicators, ioc_collection_id, valid_for)
        else invalid indicators configuration
            Action->>Action: raise ValueError
        end
    else other indicator_type
        alt indicator_type is supported
            Action->>Action: perform_request(result_indicators, ioc_collection_id, mapped_type, valid_for)
        else unsupported indicator_type
            Action->>Action: error(Improper indicator type)
        end
    end
    deactivate Action
Loading

Class diagram for AddIOCtoIOCCollectionAction accepting single indicator

classDiagram
    class InThreatBaseAction {
    }

    class AddIOCtoIOCCollectionAction {
        +perform_request(indicators, ioc_collection_id, indicator_type, valid_for)
        +add_IP_action(indicators, ioc_collection_id, valid_for)
        +run(arguments)
    }

    InThreatBaseAction <|-- AddIOCtoIOCCollectionAction
Loading

File-Level Changes

Change Details Files
Extend AddIOCtoIOCCollectionAction to support a single indicator value alongside the existing list-based input and adjust validation/dispatch accordingly.
  • Make the indicators JSON argument optional when parsing action inputs.
  • Introduce support for an indicator scalar argument and derive the list of indicators from either indicators or indicator.
  • Relax IP address validation to accept either a list of indicators or a single indicator, updating the error message to reflect both options.
  • Ensure both IP and non-IP flows call add_IP_action/perform_request with the resolved indicator list.
Sekoia.io/sekoiaio/intelligence_center/add_ioc_to_ioc_collection.py
Add tests to verify single-indicator behavior, valid_for handling, and error cases when no indicators are supplied.
  • Add fixtures for single IPv4, IPv6, domain indicators, a single indicator with valid_for, and a case with no indicators provided.
  • Add tests checking that single indicators for IPv4, IPv6, and domain types trigger the correct HTTP POST with the expected payload.
  • Add a test verifying that providing valid_for yields a payload containing valid_until.
  • Add a test asserting that omitting both indicators and indicator raises the new validation error message.
Sekoia.io/tests/test_add_ioc_2_ioc_collection.py
Update package metadata to document and version the new indicator field support.
  • Add a changelog entry for version 2.69.1 describing the new optional indicator field for AddIOCtoIOCCollectionAction.
  • Bump the integration manifest version from 2.69.0 to 2.69.1.
Sekoia.io/CHANGELOG.md
Sekoia.io/manifest.json

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey - I've found 2 issues, and left some high level feedback:

  • When neither indicators nor indicator is provided, result_indicators = indicators or [single_indicator] will produce [None] and for non-IP address types this is passed through to perform_request without validation; consider explicitly checking for the absence of both inputs and raising a clear error instead of sending a None indicator.
  • You currently build result_indicators before validating the IP-address-specific constraints; consider moving or duplicating the validation so that you don't construct a [single_indicator] list when single_indicator is falsy, which can help avoid accidental propagation of None values.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- When neither `indicators` nor `indicator` is provided, `result_indicators = indicators or [single_indicator]` will produce `[None]` and for non-`IP address` types this is passed through to `perform_request` without validation; consider explicitly checking for the absence of both inputs and raising a clear error instead of sending a `None` indicator.
- You currently build `result_indicators` before validating the IP-address-specific constraints; consider moving or duplicating the validation so that you don't construct a `[single_indicator]` list when `single_indicator` is falsy, which can help avoid accidental propagation of `None` values.

## Individual Comments

### Comment 1
<location path="Sekoia.io/sekoiaio/intelligence_center/add_ioc_to_ioc_collection.py" line_range="61" />
<code_context>
         indicator_type = arguments.get("indicator_type")
         valid_for = int(arguments.get("valid_for", 0))

+        result_indicators = indicators or [single_indicator]
+
         if str(indicator_type) == "IP address":
</code_context>
<issue_to_address>
**issue:** Guard against both `indicators` and `single_indicator` being missing to avoid passing `[None]` downstream.

When both are absent, `result_indicators` becomes `[None]` and is passed to `add_IP_action`/`perform_request`, likely causing confusing downstream errors. Add an explicit guard, for example:

```python
if not indicators and not single_indicator:
    raise ValueError("You must provide either 'indicators' or 'indicator'")

result_indicators = indicators or [single_indicator]
```
</issue_to_address>

### Comment 2
<location path="Sekoia.io/sekoiaio/intelligence_center/add_ioc_to_ioc_collection.py" line_range="63-67" />
<code_context>
         if str(indicator_type) == "IP address":
-            if not isinstance(indicators, list):
-                raise ValueError("Indicators should be list type")
+            if not isinstance(indicators, list) and not single_indicator:
+                raise ValueError("Indicators should be list type, or you should provide a single indicator value")

-            self.add_IP_action(indicators, ioc_collection_id, valid_for)
</code_context>
<issue_to_address>
**suggestion (bug_risk):** Align validation error message with the actual accepted shapes and ensure list type is also enforced when a single indicator is supplied as a list.

The current condition (`not isinstance(indicators, list) and not single_indicator`) permits non-list `indicators` whenever `single_indicator` is set, which conflicts with the message and weakens type guarantees. If `indicators` should always be a list when present, you could instead enforce:

```python
if indicators is not None and not isinstance(indicators, list):
    raise ValueError("'indicators' must be a list; alternatively, use 'indicator' for a single value")
```

Then rely on the normalization of `result_indicators` to handle cases where both fields are provided.

```suggestion
        if str(indicator_type) == "IP address":
            if indicators is not None and not isinstance(indicators, list):
                raise ValueError("'indicators' must be a list; alternatively, use 'indicator' for a single value")

            self.add_IP_action(result_indicators, ioc_collection_id, valid_for)
```
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

indicator_type = arguments.get("indicator_type")
valid_for = int(arguments.get("valid_for", 0))

result_indicators = indicators or [single_indicator]
Copy link
Contributor

Choose a reason for hiding this comment

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

issue: Guard against both indicators and single_indicator being missing to avoid passing [None] downstream.

When both are absent, result_indicators becomes [None] and is passed to add_IP_action/perform_request, likely causing confusing downstream errors. Add an explicit guard, for example:

if not indicators and not single_indicator:
    raise ValueError("You must provide either 'indicators' or 'indicator'")

result_indicators = indicators or [single_indicator]

Comment on lines 63 to +67
if str(indicator_type) == "IP address":
if not isinstance(indicators, list):
raise ValueError("Indicators should be list type")
if not isinstance(indicators, list) and not single_indicator:
raise ValueError("Indicators should be list type, or you should provide a single indicator value")

self.add_IP_action(indicators, ioc_collection_id, valid_for)
self.add_IP_action(result_indicators, ioc_collection_id, valid_for)
Copy link
Contributor

Choose a reason for hiding this comment

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

suggestion (bug_risk): Align validation error message with the actual accepted shapes and ensure list type is also enforced when a single indicator is supplied as a list.

The current condition (not isinstance(indicators, list) and not single_indicator) permits non-list indicators whenever single_indicator is set, which conflicts with the message and weakens type guarantees. If indicators should always be a list when present, you could instead enforce:

if indicators is not None and not isinstance(indicators, list):
    raise ValueError("'indicators' must be a list; alternatively, use 'indicator' for a single value")

Then rely on the normalization of result_indicators to handle cases where both fields are provided.

Suggested change
if str(indicator_type) == "IP address":
if not isinstance(indicators, list):
raise ValueError("Indicators should be list type")
if not isinstance(indicators, list) and not single_indicator:
raise ValueError("Indicators should be list type, or you should provide a single indicator value")
self.add_IP_action(indicators, ioc_collection_id, valid_for)
self.add_IP_action(result_indicators, ioc_collection_id, valid_for)
if str(indicator_type) == "IP address":
if indicators is not None and not isinstance(indicators, list):
raise ValueError("'indicators' must be a list; alternatively, use 'indicator' for a single value")
self.add_IP_action(result_indicators, ioc_collection_id, valid_for)

Copy link
Contributor

@mchupeau-sk mchupeau-sk left a comment

Choose a reason for hiding this comment

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

Ok for me but need to rebase with develop before

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.

2 participants