A JavaScript/TypeScript library for parsing, validating, and generating XARF v4 (eXtended Abuse Reporting Format) reports.
- Parse XARF reports from JSON with validation and typed results
- Generate XARF-compliant reports with auto-generated metadata (UUIDs, timestamps)
- Validate reports against the official JSON schemas with detailed errors and warnings
- Full TypeScript support with discriminated union types for all 7 categories
- v3 backward compatibility with automatic detection and conversion
- Schema-driven — validation rules derived from the official xarf-spec schemas, not hardcoded
npm install @xarf/xarfimport { parse } from '@xarf/xarf';
// Missing first_seen and source_port produce validation errors.
const { report, errors, warnings } = parse({
xarf_version: '4.2.0',
report_id: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
timestamp: '2024-01-15T10:30:00Z',
// first_seen: '2024-01-15T10:00:00Z',
reporter: {
org: 'Security Team',
contact: 'abuse@example.com',
domain: 'example.com',
},
sender: {
org: 'Security Team',
contact: 'abuse@example.com',
domain: 'example.com',
},
source_identifier: '192.0.2.100',
// source_port: 1234,
category: 'connection',
type: 'ddos',
evidence_source: 'honeypot',
destination_ip: '203.0.113.10',
protocol: 'tcp',
});
if (errors.length === 0) {
console.log(report.category); // 'connection'
} else {
console.log('Validation errors:', errors);
}import { createReport, createEvidence } from '@xarf/xarf';
// Returns { content_type, payload (base64), hash, size, description }
const evidence = createEvidence('message/rfc822', rawEmailContent, {
description: 'Original spam email',
hashAlgorithm: 'sha256',
});
// xarf_version, report_id, and timestamp are auto-generated
const { report, errors, warnings } = createReport({
category: 'messaging',
type: 'spam',
source_identifier: '192.0.2.100',
reporter: {
org: 'Example Security',
contact: 'abuse@example.com',
domain: 'example.com',
},
sender: {
org: 'Example Security',
contact: 'abuse@example.com',
domain: 'example.com',
},
evidence_source: 'spamtrap',
description: 'Spam email detected from source',
protocol: 'smtp',
smtp_from: 'spammer@evil.example.com',
evidence: [evidence],
});
console.log(JSON.stringify(report, null, 2));Parse and validate a XARF report from JSON. Supports both v4 and v3 (legacy) formats — v3 reports are automatically converted to v4 with deprecation warnings.
import { parse } from '@xarf/xarf';
const { report, errors, warnings, info } = parse(jsonData, options?);Parameters:
jsonData: string | Record<string, unknown>— JSON string or object containing a XARF reportoptions.strict?: boolean— ThrowXARFValidationErroron validation failures (default:false)options.showMissingOptional?: boolean— Include info about missing optional fields (default:false)
Returns ParseResult:
report: XARFReport— The parsed report, typed by categoryerrors: string[]— Validation errors (empty if valid)warnings: string[]— Validation warningsinfo?: ValidationInfo[]— Missing optional field info (only whenshowMissingOptionalistrue)
Create a validated XARF report with auto-generated metadata. Automatically fills xarf_version, report_id (UUID), and timestamp (ISO 8601) if not provided.
import { createReport } from '@xarf/xarf';
const { report, errors, warnings } = createReport(input, options?);Parameters:
input: ReportInput— Report data. A discriminated union oncategorythat narrows type-safe fields per category (e.g.,MessagingReportInput,ConnectionReportInput, etc.)options.strict?: boolean— Throw on validation failures (default:false)options.showMissingOptional?: boolean— Include info about missing optional fields (default:false)
Returns CreateReportResult:
report: XARFReport— The generated reporterrors: ValidationError[]— Structured validation errors ({ field, message, value? })warnings: ValidationWarning[]— Structured validation warnings ({ field, message, value? })info?: ValidationInfo[]— Missing optional field info (only whenshowMissingOptionalistrue)
Create an evidence object with automatic base64 encoding, hashing, and size calculation.
import { createEvidence } from '@xarf/xarf';
const evidence = createEvidence(contentType, payload, options?);Parameters:
contentType: string— MIME type of the evidence (e.g.,'message/rfc822')payload: string | Buffer— The evidence dataoptions.description?: string— Human-readable descriptionoptions.hashAlgorithm?: 'sha256' | 'sha512' | 'sha1' | 'md5'— Hash algorithm (default:'sha256')
Returns XARFEvidence with computed hash, size, and base64-encoded payload.
Access schema-derived validation rules and metadata programmatically.
import { schemaRegistry } from '@xarf/xarf';
// Get all valid categories
schemaRegistry.getCategories();
// Set { 'messaging', 'connection', 'content', 'infrastructure', 'copyright', 'vulnerability', 'reputation' }
// Get valid types for a category
schemaRegistry.getTypesForCategory('connection');
// Set { 'ddos', 'port_scan', 'login_attack', ... }
// Check if a category/type combination is valid
schemaRegistry.isValidType('connection', 'ddos'); // true
// Get field metadata including descriptions
schemaRegistry.getFieldMetadata('confidence');
// { description: '...', required: false, recommended: true, ... }Both parse() and createReport() run validation internally. Additional behaviors:
- Unknown fields trigger warnings (or errors in strict mode)
- Missing optional fields can be discovered with
showMissingOptional: true:
const { info } = parse(report, { showMissingOptional: true });
if (info) {
info.forEach(({ field, message }) => {
console.log(`${field}: ${message}`);
// e.g., "description: OPTIONAL - Human-readable description of the abuse"
// e.g., "confidence: RECOMMENDED - Confidence score between 0.0 and 1.0"
});
}The library automatically detects XARF v3 reports (by the Version field) and converts them to v4 during parsing. Converted reports include legacy_version: '3' and deprecation warnings.
import { parse } from '@xarf/xarf';
const { report, warnings } = parse(v3Report);
console.log(report.xarf_version); // '4.2.0'
console.log(report.category); // mapped category (e.g., 'messaging')
console.log(report.legacy_version); // '3'
// warnings includes deprecation notice + conversion detailsYou can also use the low-level utilities directly:
import { isXARFv3, convertV3toV4, getV3DeprecationWarning } from '@xarf/xarf';
if (isXARFv3(jsonData)) {
const warnings: string[] = [];
const v4Report = convertV3toV4(v3Report, warnings);
console.log(getV3DeprecationWarning());
}Unknown v3 report types cause a parse error listing the supported types. See MIGRATION_V3_TO_V4.md for the full type mapping and migration strategies.
This library validates against the official xarf-spec JSON schemas. Schemas are fetched automatically on npm install based on the version configured in package.json:
"xarfSpec": {
"version": "v4.2.0"
}# Check if a newer version of xarf-spec is available
npm run check-schema-updates
# Re-fetch schemas (e.g., if missing or to force a refresh)
npm run fetch-schemasTo update to a newer spec version, change the version in package.json and run npm install.
npm test # Run tests
npm run test:coverage # Run tests with coverage
npm run build # Build TypeScript to JavaScript
npm run typecheck # Type-check without emitting
npm run lint # Run ESLint
npm run format:check # Check Prettier formattingSee CONTRIBUTING.md for development guidelines.