Skip to content

feat(feeds/advanced): add country filter. Closes #525#1028

Open
lvb05 wants to merge 7 commits intointelowlproject:developfrom
lvb05:525-country-filter-feeds-advanced
Open

feat(feeds/advanced): add country filter. Closes #525#1028
lvb05 wants to merge 7 commits intointelowlproject:developfrom
lvb05:525-country-filter-feeds-advanced

Conversation

@lvb05
Copy link

@lvb05 lvb05 commented Mar 11, 2026

Description

Added a country query parameter to the /api/feeds/advanced/ endpoint. When provided, the endpoint filters IOCs by the attacker's country code (case-insensitive, e.g. US, de). The filter is optional and doesn't affect existing behavior when omitted.

Related issues

Fixes #525

Type of change

  • New feature (non-breaking change which adds functionality).

Checklist

Please complete this checklist carefully. It helps guide your contribution and lets maintainers verify that all requirements are met.

Formalities

  • I have read and understood the rules about how to Contribute to this project.
  • I chose an appropriate title for the pull request in the form: <feature name>. Closes #999
  • My branch is based on develop.
  • The pull request is for the branch develop.
  • I have reviewed and verified any LLM-generated code included in this PR.

Docs and tests

  • I documented my code changes with docstrings and/or comments.
  • I have checked if my changes affect user-facing behavior that is described in the docs. If so, I also created a pull request in the docs repository.
  • Linter (Ruff) gave 0 errors. If you have correctly installed pre-commit, it does these checks and adjustments on your behalf.
  • I have added tests for the feature/bug I solved.
  • All the tests gave 0 errors.

Copilot AI review requested due to automatic review settings March 11, 2026 20:10
@lvb05
Copy link
Author

lvb05 commented Mar 11, 2026

@regulartim @mlodic
Screenshot 2026-03-11 234948
Screenshot 2026-03-11 234938

Copy link
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 an optional country query parameter to /api/feeds/advanced/ to filter returned IOCs by attacker country (case-insensitive), with accompanying documentation and tests.

Changes:

  • Adds country to request param parsing/validation and applies it to the IOC queryset filter.
  • Documents the new query parameter on the advanced feeds endpoint.
  • Adds test coverage for the new country filter behavior.

Reviewed changes

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

File Description
api/views/utils.py Parses country and applies attacker_country__iexact filtering in get_queryset().
api/serializers.py Extends FeedsRequestSerializer with a new country query param.
api/views/feeds.py Updates feeds_advanced docstring to mention the new country filter.
tests/api/views/test_feeds_advanced_view.py Adds unit tests for filtering by country (including case-insensitivity and empty result set).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Collaborator

@regulartim regulartim left a comment

Choose a reason for hiding this comment

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

Nice! 👍 Only minor details left.

Copilot AI review requested due to automatic review settings March 12, 2026 13:10
Copy link
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

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (1)

api/views/feeds.py:117

  • The docstring says “attacker country code” but the model field is populated from GeoIP country_name (e.g., “Germany”, “United States”) and the tests also use full names. To avoid misleading API consumers, either update this parameter documentation to describe a country name (or whatever canonical format is actually stored), or switch the stored value/filtering to ISO country codes if that’s the intended contract.
        feed_type (str): Type of feed to retrieve. (supported: `cowrie`, `honeytrap`, etc.; default: `all`)

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copilot AI review requested due to automatic review settings March 12, 2026 14:14
Copy link
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

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


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copilot AI review requested due to automatic review settings March 12, 2026 18:06
Copy link
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

Copilot reviewed 8 out of 8 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copilot AI review requested due to automatic review settings March 12, 2026 19:31
Copy link
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

Copilot reviewed 9 out of 9 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@lvb05 lvb05 requested a review from regulartim March 13, 2026 12:46
@lvb05
Copy link
Author

lvb05 commented Mar 15, 2026

Hi @regulartim @mlodic !
I did the changes, and the tests are passing. I would appreciate a review whenever free. Thanks

Comment on lines 46 to 49
credential = self.cowrie_session.credentials.first()
self.assertEqual(credential.username, "root")
self.assertEqual(credential.password, "root")
self.assertEqual(self.cowrie_session.command_execution, True)
Copy link
Collaborator

Choose a reason for hiding this comment

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

This change seems to be completely unrelated. Please keep your PR focused.

Comment on lines +107 to +110
country = query_params.get("country")
if isinstance(country, str):
country = country.strip()
self.country = country or None
Copy link
Collaborator

Choose a reason for hiding this comment

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

This seems a little overengineered, no? self.country=query_params.get("country") seems sufficient. Empty strings and None get filtered out later, right?

Comment on lines +119 to +139
cls.ioc_4 = IOC.objects.create(
name="200.200.200.200",
type=IocType.IP.value,
first_seen=cls.current_time,
last_seen=cls.current_time,
days_seen=[cls.current_time],
number_of_days_seen=1,
attack_count=1,
interaction_count=1,
scanner=True,
payload_request=False,
related_urls=[],
ip_reputation="",
autonomous_system=cls.as_obj,
destination_ports=[],
login_attempts=0,
recurrence_probability=0.1,
expected_interactions=11.1,
attacker_country="United States",
)

Copy link
Collaborator

Choose a reason for hiding this comment

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

What's the puprose of this 4th IOC? As far I can see it is not needed in your test cases, right?

Copilot AI review requested due to automatic review settings March 23, 2026 17:38
@lvb05 lvb05 force-pushed the 525-country-filter-feeds-advanced branch from 7617efb to c1e06ac Compare March 23, 2026 17:38
Copy link
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

Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copilot AI review requested due to automatic review settings March 24, 2026 11:36
Copy link
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

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


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

recurrence_probability=0.1,
expected_interactions=11.1,
attacker_country="United States",
attacker_country="China",
Copy link

Copilot AI Mar 24, 2026

Choose a reason for hiding this comment

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

This fixture change makes "United States" no longer present in the default dataset (ioc_3 is now "China"), which will cause test_200_countries in tests/api/views/test_statistics_view.py to fail (it asserts United States count == 1). Either restore the original attacker_country values in the shared fixtures or update the downstream statistics test expectations.

Suggested change
attacker_country="China",
attacker_country="United States",

Copilot uses AI. Check for mistakes.
format (str): Response format type. Besides `json`, `txt` and `csv` are supported but the response will only contain IOC values (e.g. IP addresses) without further information. (default: `json`)
tag_key (str, optional): Filter IOCs by tag key, e.g. `malware` or `confidence_of_abuse`. Only IOCs with at least one matching tag are returned.
tag_value (str, optional): Filter IOCs by tag value (case-insensitive substring match), e.g. `mirai`. Can be used alone or combined with `tag_key`.
country (str, optional): Filter IOCs by attacker country code (case-insensitive, e.g. `Germany`, `United States`).
Copy link

Copilot AI Mar 24, 2026

Choose a reason for hiding this comment

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

The new docstring says "country code" but the implementation and examples here use full country names ("Germany", "United States"), and attacker_country is populated from geoip.country_name. Either update the parameter description to say "country name" or implement/describe ISO code support to match the PR description.

Suggested change
country (str, optional): Filter IOCs by attacker country code (case-insensitive, e.g. `Germany`, `United States`).
country (str, optional): Filter IOCs by attacker country name (case-insensitive, e.g. `Germany`, `United States`).

Copilot uses AI. Check for mistakes.
if feed_params.end_date:
query_dict["last_seen__lte"] = feed_params.end_date
if feed_params.country:
query_dict["attacker_country__iexact"] = feed_params.country
Copy link

Copilot AI Mar 24, 2026

Choose a reason for hiding this comment

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

Consider normalizing the incoming country filter the same way as other string params (e.g., trimming whitespace). As-is, values like " Germany " will validate but never match attacker_country__iexact, which is surprising compared to tag_key/tag_value which are stripped in feeds_advanced.

Suggested change
query_dict["attacker_country__iexact"] = feed_params.country
country = feed_params.country.strip()
if country:
query_dict["attacker_country__iexact"] = country

Copilot uses AI. Check for mistakes.
Comment on lines +363 to +364
values = [i["value"] for i in iocs]
self.assertIn(self.ioc.name, values)
Copy link

Copilot AI Mar 24, 2026

Choose a reason for hiding this comment

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

This case-insensitive test only asserts that the expected IOC is included, but it doesn’t assert that non-matching countries are excluded. Strengthen it by asserting the response contains exactly the Germany IOC (e.g., len == 1 and attacker_country == "Germany") so the test would fail if the country filter is accidentally not applied.

Suggested change
values = [i["value"] for i in iocs]
self.assertIn(self.ioc.name, values)
self.assertEqual(len(iocs), 1)
self.assertEqual(iocs[0]["value"], self.ioc.name)
self.assertEqual(iocs[0]["attacker_country"], "Germany")

Copilot uses AI. Check for mistakes.
recurrence_probability=0.1,
expected_interactions=11.1,
attacker_country="China",
attacker_country="Germany",
Copy link

Copilot AI Mar 24, 2026

Choose a reason for hiding this comment

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

Changing the shared CustomTestCase fixture attacker_country from "China" to "Germany" will break existing statistics tests that assert country counts (e.g., tests/api/views/test_statistics_view.py::test_200_countries expects China/United States distribution based on the default fixtures). Prefer keeping the original fixture values and overriding attacker_country within the specific feed tests, or update the dependent statistics assertions accordingly.

Suggested change
attacker_country="Germany",
attacker_country="China",

Copilot uses AI. Check for mistakes.
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.

3 participants