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-v2 / backend / src / sources / index.js 2183 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
62
// Source registry + orchestration. Each module exports { meta, configured, fetchSource }.
import * as urlhaus from './urlhaus.js'
import * as threatfox from './threatfox.js'
import * as feodo from './feodo.js'
import * as phishtank from './phishtank.js'
import * as cisakev from './cisakev.js'
import * as blocklistde from './blocklistde.js'
import * as otx from './otx.js'
import * as rss from './rss.js'
import { demoBatch } from './demo.js'
import { ok } from '../normalize.js'

const MODULES = { urlhaus, threatfox, feodo, phishtank, cisakev, blocklistde, otx, rss }
export const SOURCE_KEYS = Object.keys(MODULES)

const demoEnabled = () => process.env.HORIZON_DEMO === '1' || process.env.HORIZON_DEMO === 'true'

/** Static descriptor of every source and whether it currently has its credentials. */
export function describeSources() {
  return SOURCE_KEYS.map((key) => ({
    key,
    requiresKey: MODULES[key].meta.requiresKey,
    configured: MODULES[key].configured(),
  }))
}

/**
 * Fetch the requested sources concurrently, isolating failures per source.
 * @param {string[]} keys source keys to pull (defaults to all)
 * @returns {Promise<{iocs: object[], status: Record<string, object>}>}
 */
export async function runSources(keys = SOURCE_KEYS) {
  const selected = keys.filter((k) => MODULES[k])
  const demo = demoEnabled()

  const settled = await Promise.allSettled(
    selected.map(async (key) => {
      const mod = MODULES[key]
      // Demo mode substitutes synthetic data for any source lacking credentials.
      if (demo && !mod.configured()) {
        return [key, ok(demoBatch(key), 'demo data (HORIZON_DEMO)')]
      }
      const result = await mod.fetchSource()
      return [key, result]
    })
  )

  const iocs = []
  const status = {}
  settled.forEach((r, i) => {
    const key = selected[i]
    if (r.status === 'fulfilled') {
      const [, result] = r.value
      status[key] = { status: result.status, count: result.count, message: result.message || null }
      iocs.push(...result.iocs)
    } else {
      status[key] = { status: 'error', count: 0, message: String(r.reason?.message || r.reason) }
    }
  })

  return { iocs, status }
}