stix-rs 0.1.0

STIX 2.1 types and helpers for Rust
Documentation

stix-rs

Rust License

A complete, production-ready Rust implementation of STIX 2.1 (Structured Threat Information Expression)

stix-rs provides full support for creating, parsing, and manipulating STIX 2.1 cyber threat intelligence data. Built for performance and type safety, it's ready for use in threat intelligence platforms, TAXII servers, and security tools.


Features

100% STIX 2.1 Compliant

  • All 18 STIX Domain Objects (SDOs) - Malware, Indicator, ThreatActor, Campaign, etc.
  • All 17 Cyber Observable Objects (SCOs) - File, Network Traffic, Process, etc.
  • All Relationship Objects (SROs) - Relationship, Sighting
  • All Meta Objects - Bundle, Marking Definition, Language Content, etc.
  • 17 Vocabulary Enums - Complete type-safe enumerations

Production-Ready Features

  • 🔍 Bundle Query Helpers - Powerful search and filter APIs
  • ID Validation - Prevent invalid STIX references
  • 📡 MIME Type Constants - Standard HTTP/TAXII content types
  • 🔄 Object Versioning - Proper STIX object update handling
  • 🎨 Pattern Validation - STIX pattern language syntax checking
  • 📦 Builder Pattern - Ergonomic object construction

🛡️ Type-Safe & Fast

  • Full Rust type safety with no runtime overhead
  • Comprehensive error handling with thiserror
  • Efficient serialization/deserialization with serde
  • Zero-copy parsing where possible

Installation

Add to your Cargo.toml:

[dependencies]
stix-rs = "0.1.0"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
chrono = "0.4"

Quick Start

Creating STIX Objects

use stix_rs::*;
use chrono::Utc;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Create a Malware object
    let malware = Malware::builder()
        .name("Poison Ivy")
        .description("Advanced persistent threat RAT")
        .malware_types(vec!["remote-access-trojan".into()])
        .is_family(true)
        .aliases(vec!["PIVY".into()])
        .first_seen(Utc::now())
        .build()?;

    // Create an Indicator
    let indicator = Indicator::builder()
        .name("Malicious domain")
        .pattern("[domain-name:value = 'evil.com']")
        .pattern_type(IndicatorPatternType::Stix)
        .valid_from(Utc::now())
        .validate_pattern(true)  // Enable pattern validation
        .build()?;

    // Create a Bundle
    let bundle = Bundle::new(vec![
        malware.into(),
        indicator.into(),
    ]);

    // Serialize to JSON
    let json = serde_json::to_string_pretty(&bundle)?;
    println!("{}", json);

    Ok(())
}

Working with Bundles

use stix_rs::*;

// Load a bundle from JSON
let bundle: Bundle = serde_json::from_str(&json_data)?;

// Query by type
let all_malware = bundle.malware();
let all_indicators = bundle.indicators();
let all_threats = bundle.threat_actors();

// Find by ID
if let Some(obj) = bundle.get("malware--abc-123") {
    println!("Found: {}", obj.type_());
}

// Filter generically
let identities = bundle.filter_by_type("identity");

// Count objects
println!("Total malware: {}", bundle.count_by_type("malware"));
println!("Object types: {:?}", bundle.object_types());

// Find references
let refs = bundle.find_references_to("malware--abc-123");

// Iterate
for obj in bundle.iter() {
    println!("{}: {}", obj.type_(), obj.id());
}

Common Properties & Marking

use stix_rs::*;

let mut malware = Malware::builder()
    .name("BadWare")
    .malware_types(vec!["trojan".into()])
    .build()?;

// Add common properties
malware.common.labels = Some(vec!["apt".into(), "targeted".into()]);
malware.common.confidence = Some(95);
malware.common.lang = Some("en".into());

// Add external references (CVE, ATT&CK)
malware.common.external_references = Some(vec![
    ExternalReference::builder()
        .source_name("mitre-attack")
        .external_id("S0020")
        .url("https://attack.mitre.org/software/S0020/")
        .build()?,
]);

// Add TLP marking
let tlp_red = MarkingDefinition::tlp("red");
malware.common.object_marking_refs = Some(vec![tlp_red.id().to_string()]);

Pattern Validation

use stix_rs::pattern::{validate_pattern, PatternBuilder};

// Validate patterns
validate_pattern("[file:hashes.MD5 = 'abc123']")?;
validate_pattern("[ipv4-addr:value = '192.168.1.1']")?;

// Build patterns programmatically
let pattern = PatternBuilder::new()
    .compare("file", "name", "=", "'malware.exe'")
    .and()
    .compare("file", "size", ">", "1000")
    .build();

println!("{}", pattern);
// Output: [file:name = 'malware.exe' AND file:size > 1000]

ID Validation

use stix_rs::*;

// Validate STIX IDs
assert!(is_valid_stix_id("malware--550e8400-e29b-41d4-a716-446655440000"));
assert!(!is_valid_stix_id("invalid-id"));

// Extract type from ID
let obj_type = extract_type_from_id("malware--abc-123");
assert_eq!(obj_type, Some("malware"));

// Validate reference types
assert!(is_valid_ref_for_type(
    "malware--abc-123",
    "malware"
));

Object Versioning

use stix_rs::*;

let mut threat_actor = ThreatActor::builder()
    .name("APT28")
    .threat_actor_types(vec!["nation-state".into()])
    .build()?;

// Make updates
threat_actor.description = Some("Also known as Fancy Bear".into());

// Create new version (updates modified timestamp, preserves ID)
threat_actor.common.new_version();

🌐 HTTP/TAXII Integration

MIME Type Constants

use stix_rs::*;

// Use standard STIX/TAXII MIME types
println!("{}", MEDIA_TYPE_STIX);   // application/stix+json;version=2.1
println!("{}", MEDIA_TYPE_TAXII);  // application/taxii+json;version=2.1

Example TAXII Server (Axum)

use axum::{Router, routing::get, Json, http::StatusCode};
use stix_rs::*;

async fn get_objects() -> (StatusCode, [(String, String); 1], Json<Bundle>) {
    let bundle = load_threat_intel();

    (
        StatusCode::OK,
        [("Content-Type".to_string(), MEDIA_TYPE_STIX.to_string())],
        Json(bundle)
    )
}

#[tokio::main]
async fn main() {
    let app = Router::new()
        .route("/collections/1/objects/", get(get_objects));

    // ... serve
}

Complete Object Support

Domain Objects (SDOs)

Object Builder Tests Fields
Attack Pattern Complete
Campaign Complete
Course of Action Complete
Grouping Complete
Identity Complete
Incident Complete
Indicator Complete + Validation
Infrastructure Complete
Intrusion Set Complete
Location Complete
Malware Complete + Extended
Malware Analysis Complete
Note Complete
Observed Data Complete
Opinion Complete
Report Complete
Threat Actor Complete
Tool Complete
Vulnerability Complete

Cyber Observables (SCOs)

Object Support
Artifact
Autonomous System
Directory
Domain Name
Email Address
Email Message
File
IPv4 Address
IPv6 Address
MAC Address
Mutex
Network Traffic
Process
Software
URL
User Account
Windows Registry Key
X.509 Certificate

Relationship Objects (SROs)

Object Support
Relationship
Sighting

Meta Objects

Object Support
Bundle ✅ + Query Helpers
Marking Definition ✅ + TLP Support
Language Content
Extension Definition
External Reference ✅ + Builder
Granular Marking

Vocabulary Enums

All STIX 2.1 open vocabularies are implemented as type-safe enums:

  • MalwareType - ransomware, trojan, backdoor, etc. (20 types)
  • ThreatActorType - nation-state, criminal, hacktivist, etc. (12 types)
  • ThreatActorRole - director, agent, sponsor, etc. (5 roles)
  • ThreatActorSophistication - minimal, intermediate, advanced, etc. (7 levels)
  • AttackMotivation - ideology, dominance, personal-gain, etc. (10 types)
  • AttackResourceLevel - individual, club, organization, government (6 levels)
  • ToolType - exploitation, remote-access, etc. (8 types)
  • InfrastructureType - command-and-control, botnet, etc. (11 types)
  • ReportType - threat-report, attack-pattern, etc. (11 types)
  • IndustrySector - financial, healthcare, government, etc. (40+ sectors)
  • IndicatorType - malicious-activity, anomalous-activity, etc.
  • ImplementationLanguage - Python, C++, JavaScript, etc. (20+ languages)
  • IndicatorPatternType - stix, pcre, snort, yara, suricata
  • IdentityClass - individual, group, organization, system
  • HashAlgorithm - MD5, SHA-1, SHA-256, SHA-512
  • RelationshipType - targets, uses, indicates, etc.
  • EncryptionAlgorithm - AES-256-GCM, ChaCha20-Poly1305

🧪 Testing

# Run all tests
cargo test

# Run with output
cargo test -- --nocapture

# Run specific test
cargo test bundle_query

# Check for compilation issues
cargo check

# Build release
cargo build --release

Test Coverage: 78 tests passing (57 unit + 21 integration/doc tests)


Documentation

Generate API Docs

cargo doc --open

Use Cases

Threat Intelligence Platforms

Query and analyze threat data with type-safe APIs:

let apt_malware: Vec<_> = bundle.malware()
    .iter()
    .filter(|m| m.name.contains("APT"))
    .collect();

TAXII 2.1 Servers

Serve STIX bundles with proper MIME types:

response.header("Content-Type", MEDIA_TYPE_STIX);

Security Orchestration (SOAR)

Parse and create STIX indicators programmatically:

let indicator = Indicator::builder()
    .pattern(pattern)
    .valid_from(Utc::now())
    .build()?;

Threat Feed Aggregators

Merge multiple STIX feeds efficiently:

let mut combined = Bundle::new(vec![]);
combined.objects.extend(feed1.objects);
combined.objects.extend(feed2.objects);

Intelligence Sharing

Exchange standardized threat intelligence:

let bundle = Bundle::new(vec![
    malware.into(),
    threat_actor.into(),
    relationship.into(),
]);

Advanced Features

Custom Properties

let identity = Identity::builder()
    .name("ACME Corp")
    .class(IdentityClass::Organization)
    .property("x_industry", "financial")
    .property("x_priority", 5)
    .build()?;

Extensions

let extension = ExtensionDefinition::builder()
    .name("my-extension")
    .version("1.0.0")
    .schema("https://example.com/schema.json")
    .extension_types(vec!["property-extension".into()])
    .build()?;

Granular Markings

malware.common.granular_markings = Some(vec![
    GranularMarking {
        marking_ref: Some("marking-definition--tlp-red".into()),
        selectors: vec!["name".into(), "description".into()],
        lang: None,
    }
]);

Development

# Clone the repository
git clone https://github.com/yourusername/stix-rs
cd stix-rs

# Run tests
cargo test

# Check formatting
cargo fmt --check

# Run clippy
cargo clippy

# Build docs
cargo doc --open

📝 License

This project is licensed under the MIT License - see the LICENSE file for details.


Acknowledgments