7 min read Updated May 9, 2026

On-Chain Attestations

Attestations are the core Web3 primitive in Tamandua Sentinel. They create cryptographic, tamper-evident records of security events on the Solana blockchain without exposing sensitive telemetry.

What is an Attestation?

An attestation is a signed statement that a security event occurred. It contains:

  • Cryptographic hashes proving the event's existence
  • Metadata describing severity, technique, and timing
  • Pseudonyms linking to organization/agent without identification
  • Verification state tracking review status
  • Bounty information for rule author rewards

Attestations are stored as Solana accounts (PDAs) or embedded in Memo Program transactions, depending on configuration.

Attestation Schema (v2)

The current attestation format includes:

{
  "t": "tamandua_attestation",
  "v": 2,
  "ih": "incident_hash_hex",
  "mh": "manifest_hash_hex",
  "s": 4,
  "m": "T1555.003",
  "rh": "rule_hash_hex",
  "op": "org_pseudonym_hex",
  "ap": "agent_pseudonym_hex",
  "ts": 1715180400,
  "ic": 3,
  "it": ["hash_sha256", "domain", "ip"],
  "cf": 0.95,
  "tlp": "amber",
  "tc": "infostealer",
  "mf": "redline_stealer"
}

Field Reference

FieldNameTypeDescription
tTypestringAttestation type identifier
vVersionintegerSchema version
ihIncident HashhexSHA256 of redacted alert payload
mhManifest HashhexSHA256 of public IOC manifest
sSeverity1-51=Info, 2=Low, 3=Medium, 4=High, 5=Critical
mMITRE TechniquestringATT&CK technique ID
rhRule HashhexSHA256 of detection rule ID
opOrg PseudonymhexSHA256 of organization ID
apAgent PseudonymhexSHA256 of agent ID
tsTimestampunixWhen incident occurred
icIOC CountintegerNumber of public IOCs
itIOC TypesarrayTypes of IOCs included
cfConfidencefloatDetection confidence 0.0-1.0
tlpTLPstringTraffic Light Protocol (clear/amber)
tcThreat Classstringinfostealer/ransomware/c2/endpoint_threat
mfMalware FamilystringOptional family name

Attestation Types

Incident Attestation

Created when a high-severity alert is generated:

# Automatically when alert is created (if enabled)
{:ok, alert} = Alerts.create_alert(params)
# Triggers: Attestation.attest_alert(alert)

# Or manually
{:ok, tx_signature} = TamanduaServer.Solana.Attestation.attest_alert(alert)

The attestation includes a full public manifest stored locally:

manifest = %{
  schema: "tamandua.attestation_manifest",
  version: 2,
  tlp: "amber",
  incident_hash: "abc123...",
  severity: "high",
  mitre_technique: "T1555.003",
  rule_hash: "def456...",
  ioc_count: 3,
  ioc_types: ["hash_sha256", "domain"],
  redacted_ioc_count: 4,
  confidence: 0.95,
  threat_class: "infostealer",
  malware_family: "redline_stealer",
  iocs: [
    %{type: "hash_sha256", value: "abc...", source: "tamandua"},
    %{type: "domain", value: "evil.com", source: "tamandua"}
  ]
}

Health Attestation

Created to prove endpoint monitoring posture:

posture = %{
  window_started_at: ~U[2025-05-07 00:00:00Z],
  window_ended_at: ~U[2025-05-08 00:00:00Z],
  critical_alerts: 0,
  high_alerts: 0,
  active_alerts: 0
}

{:ok, tx_signature} = TamanduaServer.Solana.Attestation.attest_agent_health(agent, posture)

Health manifest format:

{
  "t": "tamandua_health",
  "v": 1,
  "ph": "posture_hash_hex",
  "op": "org_pseudonym_hex",
  "ap": "agent_pseudonym_hex",
  "st": "monitored",
  "ca": 0,
  "ha": 0,
  "aa": 0,
  "wh": 24,
  "pp": "default",
  "ts": 1715180400
}

Status values:

  • monitored - Endpoint healthy, no critical issues
  • at_risk - High-severity alerts present
  • critical - Critical alerts present
  • not_reporting - Endpoint offline during window

Fleet Health Attestation

Aggregates health across all endpoints for an organization:

{
  "t": "tamandua_fleet",
  "v": 1,
  "fh": "fleet_hash_hex",
  "op": "org_pseudonym_hex",
  "st": "monitored",
  "ta": 50,
  "ca": 0,
  "wa": 2,
  "pp": "balanced",
  "ts": 1715180400
}

Remediation Attestation

Created when a response action completes:

{
  "t": "tamandua_remediation",
  "v": 1,
  "rh": "remediation_hash_hex",
  "at": "quarantine",
  "op": "org_pseudonym_hex",
  "ap": "agent_pseudonym_hex",
  "st": "success",
  "ih": "incident_reference_hex",
  "ts": 1715180400
}

Action types:

  • kill - Process terminated
  • quarantine - File quarantined
  • isolate - Host isolated from network
  • rollback - System restored
  • playbook - Playbook completed

Creating Attestations

Automatic (Recommended)

Enable automatic attestation in your configuration:

# config/runtime.exs
config :tamandua_server, TamanduaServer.Alerts,
  auto_attest: true,
  attest_severity_threshold: "high"  # Only high/critical alerts

Manual via API

# Create attestation for an alert
curl -X POST https://your-server/api/v1/alerts/{alert_id}/attest \
  -H "Authorization: Bearer $TOKEN"

# Response
{
  "data": {
    "tx_signature": "5Uy3...",
    "solscan_url": "https://solscan.io/tx/5Uy3...?cluster=devnet",
    "attestation_hash": "abc123..."
  }
}

Via Elixir

alias TamanduaServer.Solana.Attestation

# Attest an alert
{:ok, tx_signature} = Attestation.attest_alert(alert)

# Get Solscan URL
url = Attestation.solscan_url(alert)
# => "https://solscan.io/tx/5Uy3...?cluster=devnet"

# Check if already attested
Attestation.attested?(alert)
# => true

Batch Attestations

For high-volume deployments, attestations are batched:

alias TamanduaServer.Solana.RelayBatch

# Queue attestation for batch publication
{:ok, batch_info} = RelayBatch.queue_attestation(%{
  ih: incident_hash,
  s: 4,
  m: "T1555.003",
  rh: rule_hash,
  op: org_pseudonym,
  ap: agent_pseudonym,
  ts: timestamp
})

# batch_info
%{
  batch_id: "batch_57185",
  position: 12,
  queue_size: 12
}

# Check batch status
RelayBatch.status()
%{
  enabled: true,
  queue_size: 12,
  batch_size: 50,
  batch_interval_ms: 30000,
  stats: %{
    total_queued: 1234,
    total_published: 1200,
    total_batches: 24,
    last_batch_at: ~U[2025-05-08 12:00:00Z]
  }
}

Batch transactions combine up to 50 attestation hashes in a single Solana transaction, reducing costs to ~$0.00002 per attestation.

Privacy Guarantees

IOC Sanitization

Only these IOC types can appear in attestations:

TypeExampleAllowed
hash_sha256abc123...Yes
hash_sha1def456...Yes
hash_md5789abc...Yes
domainevil.comYes (public only)
ip1.2.3.4Yes (public only)
urlhttps://evil.com/payloadYes (public only)
hostnamevictim-pc.localNo - Redacted
usernamejohn.doeNo - Redacted
pathC:\Users\...No - Redacted
command_linepowershell -encNo - Redacted

Private IP/Domain Detection

# These are automatically filtered:

# Private IPs (RFC1918, localhost, link-local)
10.x.x.x        # => Redacted
192.168.x.x     # => Redacted
172.16-31.x.x   # => Redacted
127.x.x.x       # => Redacted

# Private domains
*.local         # => Redacted
*.lan           # => Redacted
*.internal      # => Redacted
*.corp          # => Redacted

Traffic Light Protocol

Attestations are classified by TLP:

  • TLP:CLEAR - No IOCs redacted, all data is public
  • TLP:AMBER - Some IOCs redacted, contains privacy-sensitive indicators

The TLP is determined automatically based on redaction count:

tlp = if redacted_ioc_count > 0, do: "amber", else: "clear"

Pseudonymization

Organization and agent IDs are never stored directly. Instead, SHA256 hashes are used:

def pseudonymize(id) when is_binary(id) do
  :crypto.hash(:sha256, id)
end

# Example:
org_id = "org_abc123"
pseudonym = pseudonymize(org_id)
# => <<0x1a, 0x2b, ...>>  # 32 bytes
# Displayed as: "1a2b3c4d..."

This ensures:

  • Same org/agent always produces same pseudonym (for correlation)
  • Pseudonym cannot be reversed to real ID
  • Privacy preserved while allowing pattern analysis

Incident Hash Computation

The incident hash uniquely identifies an alert without exposing sensitive data:

def compute_incident_hash(alert) do
  payload = [
    to_string(alert.id),
    to_string(alert.severity),
    extract_mitre_technique(alert),
    to_string(rule_id),
    DateTime.to_iso8601(alert_timestamp),
    pseudonymize(alert.organization_id) |> Base.encode16(case: :lower),
    pseudonymize(alert.agent_id) |> Base.encode16(case: :lower)
  ]
  |> Enum.join("|")

  :crypto.hash(:sha256, payload)
end

This hash:

  • Is deterministic (same alert = same hash)
  • Contains no sensitive data
  • Can be used to verify attestation authenticity

Viewing Attestations

Solscan Explorer

Every attestation includes a Solscan link for public verification:

https://solscan.io/tx/5Uy3...?cluster=devnet

The transaction memo contains the JSON attestation data.

Dashboard

Attested alerts show blockchain verification status:

  • Transaction signature
  • Solscan link
  • Attestation timestamp
  • Verification status

API

# Get attestation details for an alert
curl https://your-server/api/v1/alerts/{alert_id}/attestation \
  -H "Authorization: Bearer $TOKEN"

{
  "data": {
    "tx_signature": "5Uy3...",
    "solscan_url": "https://solscan.io/tx/5Uy3...?cluster=devnet",
    "incident_hash": "abc123...",
    "manifest_hash": "def456...",
    "attestation_timestamp": "2025-05-08T12:00:00Z",
    "verified": false
  }
}

Best Practices

  1. Enable automatic attestation for high/critical alerts
  2. Use batch mode for high-volume deployments
  3. Monitor attestation success via /api/v1/solana/status
  4. Archive manifests locally for verification
  5. Review TLP classification before enabling public sharing

Next Steps