Catalyst / admin/SAynapse-Horizon 14.8 GB / 57.8 GB 40.0 GB free
Help Sign in

admin / SAynapse-Horizon

public

Self Hosted Cyber Threat Intelligence Hub

Code Issues Pull requests Pipelines Packages Security Insights Wiki Settings
SAynapse-Horizon / Synapse-Horizon / backend / src / sources / otx.js 2173 B · main
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
import { makeIoc, fetchWithTimeout, ok, unconfigured, mapMitre, SEVERITY } from '../normalize.js'

// AlienVault OTX — subscribed threat pulses. Requires an X-OTX-API-KEY.
const URL = 'https://otx.alienvault.com/api/v1/pulses/subscribed?limit=20&page=1'

export const meta = { key: 'otx', requiresKey: true }

export function configured() {
  return Boolean(process.env.OTX_API_KEY)
}

export async function fetchSource() {
  const key = process.env.OTX_API_KEY
  if (!key) return unconfigured('Set OTX_API_KEY (AlienVault OTX account) to enable Threat Pulses.')

  const res = await fetchWithTimeout(URL, { headers: { 'X-OTX-API-KEY': key } })
  const data = await res.json()
  const pulses = Array.isArray(data?.results) ? data.results : []

  const iocs = pulses.map((p) => {
    const indicators = Array.isArray(p.indicators) ? p.indicators : []
    const first = indicators[0]
    const indicator = first?.indicator || p.name
    const isHash = /hash/i.test(first?.type || '')
    const adversary = p.adversary || (p.tags && p.tags[0]) || 'an uncategorized actor'
    const shown = isHash && indicator.length > 18 ? indicator.slice(0, 16) + '…' : indicator
    return makeIoc('otx', {
      detectedAt: p.modified || p.created,
      severity: SEVERITY.HIGH,
      category: 'Threat Pulse',
      indicator,
      indicatorType: first?.type || 'pulse',
      target: adversary,
      confidence: 75,
      mitre: mapMitre(p.attack_ids),
      headline: `Threat Pulse: ${shown} attributed to ${adversary} in an AlienVault OTX pulse (${indicators.length} IOC${
        indicators.length === 1 ? '' : 's'
      })`,
      raw: {
        pulse_id: p.id,
        name: p.name,
        author_name: p.author_name,
        adversary: p.adversary,
        tags: p.tags,
        attack_ids: p.attack_ids,
        indicator_count: indicators.length,
        sample_indicator: indicator,
      },
      stix: {
        type: 'indicator',
        pattern: isHash
          ? `[file:hashes.'SHA-256' = '${indicator}']`
          : `[x-otx:value = '${indicator}']`,
        pattern_type: 'stix',
        labels: ['malicious-activity'],
      },
    })
  })

  return ok(iocs)
}