Skip to main content

faker-cti

Faker providers for cyber threat intelligence test data: STIX 2.1 objects and identifiers, TLP/PAP markings, MITRE ATT&CK, vulnerabilities, threat names, plus the payloads exchanged by OpenCTI connectors and OpenAEV injectors/collectors.

Everything is built for unit tests with factory_boy: values are reproducible with Faker.seed() / factory.random.reseed_random(), and ids are the ids the real tools compute. Deterministic STIX ids match the stix2 library, and domain-object ids match pycti generate_id, so an id in a fixture is the id OpenCTI would store.

faker-cti does not reimplement anything Faker already has. IP addresses, domains, URLs, emails, host names, MAC addresses and MD5/SHA hashes come from Faker's built-in providers.

>>> from faker import Faker
>>> from faker_cti import CtiProvider
>>> fake = Faker()
>>> fake.add_provider(CtiProvider)

>>> fake.stix_id("ipv4-addr", value="1.2.3.4")        # same as stix2.IPv4Address(value=...).id
'ipv4-addr--0198f97b-e65d-5025-87e5-58bc39d4bdb4'
>>> fake.tlp_marking_id("amber+strict")
'marking-definition--826578e1-40ad-459f-bc73-ede076f81f37'
>>> fake.stix_pattern("domain-name")
"[domain-name:value = 'jones.com']"
>>> fake.mitre_attack_technique()
{'external_id': 'T1059.001', 'name': 'PowerShell', 'phase_name': 'execution',
 'url': 'https://attack.mitre.org/techniques/T1059/001'}
>>> fake.openaev_implant_name()
'oaev-implant-bfe4440e-60fc-47fa-bf8b-1baa47158a7e-agent-309944e2-f5b5-4934-8106-bb058f332483'

Installation

pip install faker-cti        # or: uv add --dev faker-cti

Requires Python 3.10+ and Faker 20+. No other runtime dependency (stix2 and pycti are only used in this project's own tests to check the output).

Providers

You can register CtiProvider to get every formatter, or register only the layer you need. Each provider includes the ones before it:

Provider Adds
ThreatIntelProvider hashes (STIX-keyed dicts, ssdeep, TLSH), ASN, CVE/CWE/CPE, MITRE ATT&CK, threat names
StixProvider STIX ids, timestamps, vocabularies, markings, patterns, SCOs, SDOs, SROs, bundles
OpenCTIProvider enrichment messages, connector config/env, markings, work ids, scores
OpenAEVProvider implant names, expectations and signatures, results, endpoints, injection messages
CtiProvider all of the above

Faker(includes=["faker_cti"]) and the Faker CLI (faker -i faker_cti stix_id) also work.

Threat intelligence

Formatter Example
file_hashes(algorithms=None) {"MD5": "…", "SHA-1": "…", "SHA-256": "…"}; also SHA-512, SSDEEP, TLSH
ssdeep() / tlsh() 384:dC4/DSDC6Lc1mx…:A2h9Uz0+T1… / T1A81AA42B…
asn() / autonomous_system_number() AS64649 / 65094 (private-use range)
defang(value) hxxps://evil[.]example[.]com/payload
cve_id(year=None) / notable_cve_id() CVE-2022-31949 / CVE-2021-44228
cwe_id() / cpe23(vendor, product, version, part="a") CWE-502 / cpe:2.3:a:apache:tomcat:8.4.1:*:*:*:*:*:*:*
mitre_attack_technique() / mitre_attack_technique_id(subtechnique=None) dict / T1059.001
mitre_attack_tactic() / mitre_attack_tactic_id() / kill_chain_phase_name() dict / TA0003 / lateral-movement
malware_family() / threat_tool() AgentTesla / PsExec
intrusion_set() / intrusion_set_profile() / mitre_attack_group_id() APT29 / dict with aliases / G0016
mutex_name() / windows_registry_key() / x509_serial_number() Global\{025B…} / HKEY_…\Run / a5:b6:…

STIX 2.1

Formatter Notes
stix_id(stix_type=None, **properties) random UUIDv4, or the deterministic UUIDv5 when properties are given
stix_type(category=None) "sdo", "sco" or any
stix_timestamp() 2020-11-15T11:52:11.445Z
tlp_level() / tlp_marking_id(level=None) / stix_marking_definition(level=None) well-known TLP ids (clear, green, amber, amber+strict, red)
pap_level() / pap_marking_id(level=None) OpenCTI PAP marking ids
stix_relationship_type(), stix_report_type(), stix_indicator_type(), stix_malware_type(), stix_identity_class(), stix_threat_actor_type(), stix_pattern_type(), industry_sector() STIX open vocabularies
stix_kill_chain_phase() / stix_external_reference(source_name=None)
stix_observable_value(stix_type) / stix_observable(stix_type=None, value=None, **extra) ipv4-addr, ipv6-addr, domain-name, url, email-addr, mac-addr, hostname, file, autonomous-system, mutex
stix_pattern(stix_type=None, value=None) [ipv4-addr:value = '…'], [file:hashes.'SHA-256' = '…']
stix_indicator(...), stix_relationship(source_ref, target_ref, relationship_type, start_time, stop_time) all optional; the id is derived from them (pycti rules)
stix_attack_pattern(technique_id), stix_malware(name), stix_tool(name), stix_intrusion_set(name), stix_threat_actor(name), stix_vulnerability(name), stix_identity(name, identity_class), stix_location(country_code), stix_report(object_refs, name) SDOs with pycti-compatible ids
stix_bundle(objects=None)

Every object formatter accepts **extra keyword arguments, which are merged into the result (confidence=80, created_by_ref=…, x_opencti_score=…).

OpenCTI

Formatter Notes
opencti_enrichment_message(entity_type=None, value=None, marking=None, score=None) what process_message receives; entity_id, stix_entity and enrichment_entity are consistent
opencti_enrichment_entity(...) / opencti_stix_entity(...) the two halves of the message
opencti_connector_config(connector_type=None, name=None) / opencti_connector_env(...) nested settings / OPENCTI_URL, CONNECTOR_ID…
opencti_connector_type(), opencti_connector_scope(), opencti_duration_period(), opencti_work_id()
opencti_marking(level=None), opencti_author(name=None), opencti_label(), opencti_score(), opencti_confidence(), opencti_internal_id(), opencti_observable_type(), opencti_entity_type(), opencti_timestamp()

OpenAEV

Formatter Notes
openaev_implant_name(inject_id=None, agent_id=None, extension=None) oaev-implant-<inject>-agent-<agent>, the format collectors parse
openaev_implant_command_line(inject_id=None, agent_id=None) as seen in EDR process evidence
openaev_expectation(expectation_type=None, signature_types=None, inject_id=None, agent_id=None) implant parent_process_name + start_date < end_date by default
openaev_expectation_signature(signature_type=None, value=None) / openaev_signature_value(signature_type) every pyoaev SignatureTypes value
openaev_expectation_result(expectation_type=None, is_success=None, collector_id=None) Detected / Not Detected / Prevented / Not Prevented
openaev_expectation_trace(...), openaev_execution_callback(...)
openaev_endpoint(platform=None, with_agent=True), openaev_injection_message(...)
openaev_collector_env(slug=None), openaev_injector_env(slug=None), openaev_collector_id(slug=None)
openaev_ai_marker(inject_id=None, agent_id="") same algorithm as pyoaev.signatures.ai_marker
openaev_id(), openaev_signature_type(), openaev_expectation_type(), openaev_execution_status(), openaev_execution_action(), openaev_security_platform_type(), openaev_cloud_provider(), openaev_platform() pyoaev enums

Use with factory_boy

Register the provider once (for example in conftest.py), then use factory.Faker:

import factory
from faker_cti import CtiProvider

factory.Faker.add_provider(CtiProvider)


class StixIpv4EntityFactory(factory.DictFactory):
    value = factory.Faker("ipv4")
    # the id follows the value, even when the test overrides it
    id = factory.Faker("stix_id", stix_type="ipv4-addr", value=factory.SelfAttribute("..value"))
    x_opencti_score = factory.Faker("opencti_score")
    object_marking_refs = factory.List([factory.Faker("tlp_marking_id", level="amber")])


class EnrichmentMessageFactory(factory.DictFactory):
    class Params:
        entity_type = "IPv4-Addr"
        value = None

    message = factory.Faker(
        "opencti_enrichment_message",
        entity_type=factory.SelfAttribute("..entity_type"),
        value=factory.SelfAttribute("..value"),
    )

    @classmethod
    def _create(cls, model_class, *args, **kwargs):
        return kwargs["message"]


StixIpv4EntityFactory(value="1.2.3.4")["id"]  # 'ipv4-addr--0198f97b-…'
EnrichmentMessageFactory(entity_type="Domain-Name")

The examples/ folder has complete, tested examples based on the factories of real connectors and collectors:

  • opencti_enrichment: an internal enrichment connector (replaces the ~500-line Censys / ReversingLabs factory files).
  • openaev_collector: an EDR collector matching alerts against expectations (Cortex XDR / XSOAR style).
  • stix_bundle: an external import connector producing a coherent bundle (author, marking, intrusion set, malware, attack pattern, relationships).

Demo

uv run python examples/demo.py               # one sample of every formatter
uv run python examples/demo.py stix --seed 1 # filter + reproducible
faker -i faker_cti -r 3 stix_pattern         # with Faker's own CLI

Development

uv sync
uv run pytest                     # tests + examples, with stix2 cross-checks
uv run --with pycti pytest -k pycti   # also cross-check ids against pycti
uv run ruff check . && uv run ruff format --check .

License

Apache-2.0

Metadata

Release files for faker-cti 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for faker-cti 0.1.0
File Size Uploaded Provenance Actions
faker_cti-0.1.0.tar.gz 41.3 kB Without provenance Details for faker_cti-0.1.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for faker-cti 0.1.0
File Interpreter ABI Platform Actions
faker_cti-0.1.0-py3-none-any.whl Python 3 none any Details for faker_cti-0.1.0-py3-none-any.whl

Total release size: 74.6 kB

Release files / faker_cti-0.1.0.tar.gz

Download URL faker_cti-0.1.0.tar.gz
Size 41.3 kB
Tags Source
SHA-256 checksum
How to use checksums
fabc2e4f7d1297a478115d9ffcb0b5ab7e67919ef0de9d32461c2ea692508486
BLAKE2b-256 checksum
How to use checksums
60fa8ec6e43053765694f3b47c48f3490053cf4dbd6875ff00cb51094d231bc2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.0 {"installer":{"name":"uv","version":"0.13.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / faker_cti-0.1.0-py3-none-any.whl

Download URL faker_cti-0.1.0-py3-none-any.whl
Size 33.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
2e8cbb2a79595ea7b41ef2f721c83a82c9bd8aad15d9fd3a8073c4e88aae0982
BLAKE2b-256 checksum
How to use checksums
965ffcf0135f5bc49c34b60308743bd2eedc457452d9b8f7f8a27f245f34ae8b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.0 {"installer":{"name":"uv","version":"0.13.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Security for faker-cti 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page