GitHub Packages · MIT · Node ≥ 18

hash-sentinel

Check file hashes against your own threat feeds, MISP and optional public lookups, offline-first.

Hash lookup CLI: hash files or take MD5/SHA1/SHA256/SHA512 values and check them offline against self-hosted feeds (hash lists, CSV, MISP events and MISP feed directories, cached URL feeds) and optionally CIRCL hashlookup (no key), MalwareBazaar or VirusTotal. Zero deps.

  1. 1 Point the @mrlouiswright scope at GitHub Packages in .npmrc

    @mrlouiswright:registry=https://npm.pkg.github.com
  2. 2 Install

    npm i -D @mrlouiswright/hash-sentinel
Installing from GitHub Packages needs a token

Published to GitHub Packages, not npmjs.com. GitHub Packages needs a GitHub token with read:packages to install, even for public packages: add //npm.pkg.github.com/:_authToken=${GITHUB_TOKEN} to .npmrc or run npm login --registry=https://npm.pkg.github.com.

~/project — zsh
$ npx hash-sentinel sample.txt --feed feed.txthash-sentinel — 1 target(s) sample.txt  status: malicious  sha256: 8693a2ad77b10798f5a4c4d3574de815797a8d1139df9b56e9a58dcd432ec145  CRITICAL Known malicious: feed.txt: example-malware-family [known-malicious]           ↳ 8693a2ad77b10798f5a4c4d3574de815797a8d1139df9b56e9a58dcd432ec145           ↳ fix: Quarantine the file, block the hash and investigate where it came from. 1 critical✖ Failing (fail-on: high).
Real output from running hash-sentinel locally on a test fixture.

Why it exists

hash-sentinel takes MD5/SHA1/SHA256/SHA512 values, or files and directories that it hashes locally, and checks them against self-hosted feeds you control: plain hash lists, sha256sum output, CSV exports (such as MalwareBazaar's), MISP events, MISP REST search results and MISP feed directories, and URL feeds that are cached locally. Optionally it asks CIRCL hashlookup (no API key; it knows millions of good files from NSRL and flags known-malicious ones), MalwareBazaar (free abuse.ch Auth-Key) and VirusTotal (API key).

CLI, library and GitHub Action. Node.js 18+, zero runtime dependencies. Files are hashed locally and never uploaded. Online lookups are opt-in and send only the hash.

Features

Inputs

hashes, files, directories (recursive), or stdin (-). Files are hashed with MD5, SHA1, SHA256 and SHA512 in one streaming pass, and all four are matched.

Feed formats

(auto-detected):

Known-good lists

(--known-good) for golden images or allow-listed tools. A hash that is both known-good and on a malicious feed raises known-good-conflict (a false positive, or a trojanised copy).

Online sources

(--online circl,malwarebazaar,virustotal): CIRCL hashlookup needs no key and returns NSRL known-good data plus a KnownMalicious flag. MalwareBazaar uses ABUSECH_AUTH_KEY (free at auth.abuse.ch). VirusTotal uses VT_API_KEY and counts 3 or more engines as malicious. Missing keys are reported as skipped, not failures. Lookups run 4 at a time with a 15 s timeout.

Usage

# Example

 npx hash-sentinel 275a021bbfb6489e54d471899f7db9d1663fc695ec2fe2a2c4538aabf651fd0f --feed intel/hashes.txt

# Example

 npx hash-sentinel ./downloads --feed misp-feed/ --feed https://intel.example.net/sha256.txt --online circl

CI / GitHub Action

permissions:
  contents: read
  security-events: write   # only for the SARIF upload
steps:
  - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
    with: { persist-credentials: false }
  - uses: MrLouisWright/hash-sentinel@v1
    with:
      targets: 'downloads/'
      fail-on: high
      sarif: hash-sentinel.sarif
  - uses: github/codeql-action/upload-sarif@v3
    if: always()
    with: { sarif_file: hash-sentinel.sarif }

Options & flags

FlagDescription
--feed <src>Hash list, CSV (e.g. MalwareBazaar export), MISP event JSON, MISP feed
--known-good <src>Known-good hash list(s) (e.g. your golden images)
--ttl <seconds>URL feed cache lifetime (default 21600)
--offlineNever touch the network (cached URL feeds only)
--online <list>circl, malwarebazaar, virustotal
-f tableOne line per input: status, target, label
Policy and output
-c, --config <file>JSON config (default .hash-sentinel.json if present)
-f, --format <fmt>text (default) | json | sarif | markdown
--json/--sarif/--markdown <file>Also write that format to a file
--fail-on <sev>critical | high | medium | low | info | none (default high)
--list-rulesPrint rules and default severities
--no-colorDisable colours

Full reference, config file format and API in the README.

Support this project

Support open-source security tools

I build free, open-source tools that help developers ship safer websites. Every coffee helps keep them maintained, documented and free for everyone.

Buy me a coffee (opens Stripe in a new tab)

Secure checkout by Stripe

Portrait of Louis Wright

About the author

Louis Wright

Cyber security researcher and software engineer based in the UK.

More tools by Louis Wright

58 tools

Sentinels security scanners & CI gates · 19