Skip to content

[ BUG ] query_malware_entities ignores last_updated FQL filter #1422

@Kakudou

Description

@Kakudou

Describe the bug
Intel.query_malware_entities appears to ignore the provided FQL filter on last_updated (last_updated:>=<timestamp>).
The endpoint returns malware entities with last_updated older than the specified timestamp, while meta.pagination.total suggests the filter was not applied (or not applied correctly).

To Reproduce

  1. Run the script below (set BASE_URL, CLIENT_ID, CLIENT_SECRET).
  2. It builds an FQL filter for "last 24h" using last_updated:>=<utc_timestamp>.
  3. Call query_malware_entities twice with the same filter but different sorts (desc then asc).
  4. Observe that the ascending query returns an entity with last_updated older than the filter threshold, and the total count looks unfiltered.
import json
from datetime import datetime, timezone

from falconpy import Intel

BASE_URL = ""
CLIENT_ID = ""
CLIENT_SECRET = ""

cs_intel = Intel(
    client_id=CLIENT_ID,
    client_secret=CLIENT_SECRET,
    base_url=BASE_URL,
)

now = datetime.now(timezone.utc)
now_timestamp = int(now.timestamp() - 86400)
print(f"Now: {now}, Timestamp: {now_timestamp}")
print("sort desc:")

fql_filter = f"last_updated:>={now_timestamp}"

response = cs_intel.query_malware_entities(
    limit=1,
    offset=0,
    sort="last_updated|desc",
    filter=fql_filter,
)
print(f"""-----------------------------------
Meta:
{json.dumps(response["body"]["meta"], indent=2)}
Threat:
  id: {response["body"]["resources"][0]["id"]}
  name: {response["body"]["resources"][0]["name"]}
  slug: {response["body"]["resources"][0]["slug"]}
  description: {response["body"]["resources"][0]["description"]}
  created_timestamp: {response["body"]["resources"][0]["created_timestamp"]}
  last_updated: {response["body"]["resources"][0]["last_updated"]}
-----------------------------------
""")

print("sort asc:")
response = cs_intel.query_malware_entities(
    limit=1,
    offset=0,
    sort="last_updated|asc",
    filter=fql_filter,
)
print(f"""-----------------------------------
Meta:
{json.dumps(response["body"]["meta"], indent=2)}
Threat:
  id: {response["body"]["resources"][0]["id"]}
  name: {response["body"]["resources"][0]["name"]}
  slug: {response["body"]["resources"][0]["slug"]}
  description: {response["body"]["resources"][0]["description"]}
  created_timestamp: {response["body"]["resources"][0]["created_timestamp"]}
  last_updated: {response["body"]["resources"][0]["last_updated"]}
-----------------------------------
""")

Observed output:

Now: 2026-01-28 10:22:34.374846+00:00, Timestamp: 1769595754
sort desc:
-----------------------------------
Meta:
{
  "query_time": 2.137844837,
  "pagination": {
    "offset": 0,
    "limit": 1,
    "total": 3927
  },
  "powered_by": "msa-api",
  "trace_id": "563b4b2c-dda5-4a10-bbf1-e5995df19bd0"
}
Threat:
  id: Threat:9716244ca0bc92f2dff5d99c7c2004cc3b9bfb30bbcaa8b85b428409d5c1e1f9
  name: GandCrab
  slug: gandcrab
  description: GandCrab first emerged on 26 January 2018. Distributed using the RIG and GrandSoft exploit kits, it is one of the first known ransomware families to accept the DASH cryptocurrency and utilize the cryptocurrency Namecoin TLD .bit, which acts as an alternative, decentralized domain name system. Aside from the aforementioned features, there is nothing remarkable about the way that GandCrab performs file encryption or network communications. GandCrab uses 256-bit AES and 2,048-bit RSA to encrypt files. The network communications are all carried out over HTTP requests and are Base64-encoded after being RC4-encrypted with a hard-coded key.
  created_timestamp: 2020-04-08T10:46:51Z
  last_updated: 2026-01-28T10:22:32Z
-----------------------------------

sort asc:
-----------------------------------
Meta:
{
  "query_time": 2.096554089,
  "pagination": {
    "offset": 0,
    "limit": 1,
    "total": 3927
  },
  "powered_by": "msa-api",
  "trace_id": "6dec567c-6bd4-45e5-8ab9-e964b122e5e2"
}
Threat:
  id: Threat:657b34146d8953cd513901fefcf40edb2be7de9515d82cbbdc4a789448190ee6
  name: CryptBot
  slug: cryptbot
  description: CryptBot Information Stealer
  created_timestamp: 2021-01-20T10:50:31Z
  last_updated: 2025-03-21T12:40:10Z
-----------------------------------
  • With sort="last_updated|desc" the returned entity has last_updated: 2026-01-28T10:22:32Z (looks correct).
  • With sort="last_updated|asc" the returned entity has last_updated: 2025-03-21T12:40:10Z (violates last_updated:>={timestamp}), while meta.pagination.total remains 3927.
Now: 2026-01-28 10:22:34.374846+00:00, Timestamp: 1769595754
fql_filter = last_updated:>=1769595754

sort desc -> last_updated: 2026-01-28T10:22:32Z, total: 3927
sort asc  -> last_updated: 2025-03-21T12:40:10Z, total: 3927

Expected behavior
When using filter="last_updated:>=<timestamp>", results should only include malware entities whose last_updated is greater than or equal to the provided timestamp.
In this example (last 24 hours), the sort asc query should still return an entity updated within that window, and meta.pagination.total should reflect only those filtered results (not the full dataset).

Environment (please complete the following information):

  • OS: Linux 6.14.0-37-generic (Ubuntu 24.04.1, x86_64)
  • Python: 3.12.3
  • FalconPy: 1.6.0

Additional context

Metadata

Metadata

Assignees

Labels

bug 🐛Something isn't working

Type

No fields configured for Bug.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions