Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Processes STIX 2.1 threat intelligence bundles delivered via TAXII 2.1 servers, normalizing objects into platform-native schemas and routing them to appropriate consuming systems. Use when onboarding new TAXII collection endpoints, automating bi-directional intelligence sharing with ISACs, or building pipeline validation for malformed STIX bundles. Activates for requests involving OASIS STIX, TAXII server configuration, MISP TAXII, or Cortex XSOAR feed integrations.
.claude/skills/processing-stix-taxii-feeds/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-12 | ✗→✓ | ▲ Improved | — | — |
| case-03 | ✗→✓ | ▲ Improved | — | — |
| case-01 | ✓→✓ | = Same ✓ | — | — |
| case-02 | ✓→✓ | = Same ✓ | — | — |
| case-08 | ✓→✓ | = Same ✓ | — | — |
Use this skill when:
Do not use this skill for proprietary vendor feed formats (Recorded Future JSON, CrowdStrike IOC lists) that require vendor-specific parsers rather than STIX processing.
stix2 library (pip install stix2) and taxii2-client librarypythonfrom taxii2client.v21 import Server, as_pages server = Server("https://cti.example.com/taxii/", user="apiuser", password="apikey") api_root = server.api_roots[0] for collection in api_root.collections: print(collection.id, collection.title, collection.can_read)
Select collections relevant to your threat profile. CISA AIS provides collections segmented by sector (financial, energy, healthcare).
pythonfrom taxii2client.v21 import Collection from datetime import datetime, timedelta, timezone collection = Collection( "https://cti.example.com/taxii/api1/collections/<id>/objects/", user="apiuser", password="apikey") # Fetch only objects added in the last 24 hours added_after = datetime.now(timezone.utc) - timedelta(hours=24) for bundle_page in as_pages(collection.get_objects, added_after=added_after, per_request=100): process_bundle(bundle_page)
pythonimport stix2 def process_bundle(bundle_dict): bundle = stix2.parse(bundle_dict, allow_custom=True) for obj in bundle.objects: if obj.type == "indicator": validate_indicator(obj) elif obj.type == "threat-actor": upsert_threat_actor(obj) elif obj.type == "relationship": link_objects(obj) def validate_indicator(indicator): required = ["id", "type", "spec_version", "created", "modified", "pattern", "pattern_type", "valid_from"] for field in required: if not hasattr(indicator, field): raise ValueError(f"Missing required field: {field}") # Check confidence range if hasattr(indicator, "confidence"): assert 0 <= indicator.confidence <= 100
Map STIX object types to destination systems:
indicator objects → SIEM lookup tables and firewall blocklistsmalware objects → EDR threat intelligence librarythreat-actor / campaign objects → TIP for analyst contextcourse-of-action objects → Security team wiki or SOAR playbook triggersUse TLP marking definitions to enforce sharing restrictions:
pythonfor marking in obj.get("object_marking_refs", []): if "tlp-red" in marking: route_to_restricted_platform_only(obj)
python# Add validated local intelligence back to shared collection new_indicator = stix2.Indicator( name="Malicious C2 Domain", pattern="[domain-name:value = 'evil-c2.example.com']", pattern_type="stix", valid_from="2025-01-15T00:00:00Z", confidence=80, labels=["malicious-activity"], object_marking_refs=["marking-definition--34098fce-860f-479c-ae..."] # TLP:GREEN ) collection.add_objects(stix2.Bundle(new_indicator))
| Term | Definition | |------|-----------| | STIX Bundle | Top-level STIX container object (type: "bundle") holding any number of STIX Domain Objects (SDOs) and STIX Relationship Objects (SROs) | | SDO | STIX Domain Object — core intelligence types: indicator, threat-actor, malware, campaign, attack-pattern, course-of-action | | SRO | STIX Relationship Object — links two SDOs with a labeled relationship (e.g., "uses", "attributed-to", "indicates") | | Pattern Language | STIX pattern syntax for indicator conditions: [network-traffic:dst_port = 443 AND ipv4-addr:value = '10.0.0.1'] | | Marking Definition | STIX object encoding TLP or statement restrictions on intelligence sharing | | added_after | TAXII 2.1 filter parameter (RFC 3339 timestamp) for incremental polling of new objects |
spec_version field: STIX 2.0 and 2.1 have incompatible schemas (2.1 adds confidence, object_marking_refs at bundle level). Always check spec_version before parsing.next link header) causes silent data loss.added_after: Server and client time misalignment causes missed objects at interval boundaries. Use UTC exclusively and add 5-minute overlap windows.| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-10 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-15 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-01 | pass→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-13 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-05 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-16 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-04 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-02 | pass→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-22 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-17 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-20 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-11 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-08 | pass→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-12 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-09 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-03 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-18 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-14 | pass→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-07 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-06 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-19 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-21 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +9 percentage points is the difference between those two pass rates over the 22 comparable cases. 1 case got worse with the skill loaded, and it is included in that figure.
The per-case answers from this run were removed by the retention sweep, so the case table below shows the verdicts without the text either arm produced. The counts above were recorded at the time and are unaffected. Answers are now kept for 180 days.
Other measured skills in the registry, with their headline benchmark lift.