Note: This article was authored by me and originally published on Moonfare’s Official Blog as part of my work at Moonfare. It is republished here on my personal blog with permission.

This blog post will guide you through setting up and running Witcher via CLI, along with automating routines using GitHub Actions.

How to install Witcher

$ git clone git@github.com:mf-labs/witcher.git
$ cd witcher
$ npm i

Setting Up Environment Variables

Set the following environment variables for running Witcher without SIEM, Slack and Jira support

 export GITHUB_TOKEN=YOUR_GITHUB_TOKEN
 export GITHUB_USER=YOUR_GITHUB_USERNAME
 export ORG=YOUR_GITHUB_ORGANIZATION
 export SLACK_BOT_TOKEN=ABC
 export SLACK_SIGNING_SECRET=ABC
 export SLACK_CHANNEL=ABC
 export SERVERLESS_APP_URL=ABC
 export JIRA_API_TOKEN=ABC
 export JIRA_EMAIL=ABC
 export JIRA_URL=ABC
 export JIRA_PROJECT=ABC
 export JIRA_ISSUE_TYPE=ABC

Configuring Exclusions in Witcher

To refine security monitoring and focus on core repositories, update the exclusion list in github/data/exclusion.json. This file allows you to exclude specific repositories from GitHub Advanced Security (GHAS) and other security modules.

Example Exclusion File:

{
    "Dependabot": [],
    "IaC": [],
    "GHAS": [],
    "SecretScanning": [],
    "Workflows": [],
    "CodeQL": []
}

How It Works:

Witcher operates on a blacklisting approach, meaning it automatically monitors all repositories unless explicitly excluded. By adding a repository to this list, you can prevent it from being scanned ensuring that only critical, core repositories remain under active security enforcement.

Creating SIEM Logic App (Optional)

Create a webhook or serverless application to capture and parse object and store data in tables. The schema(s) can be found in the ./utils/siem.js class. By default SIEM integration is disabled

Enable logging to SIEM / Serverless Application

If you want to enable logging for SIEM, just set the logOnSIEM = true in ./utils/siem.js or provide --siem flag via CLI.

$ node witcher.js -m ghas -a disable -r <repo-name> --siem

Creating Slack App / Webhook (Optional)

Slack App - quickstart

Disable slack post and alert

If you want to disable the slack post and alerts, do no provide --slack flag.

Witcher in action

GHAS

  1. List repositories where GHAS is disabled
$ node witcher.js -m ghas -a status -r all
[-] List repositories where GHAS is disabled
[+] Total: 0
[]
  1. Enabling / Disabling GHAS on a repository
# Disable GHAS on <repo-name>
$ node witcher.js -m ghas -a disable -r <repo-name>
[-] Disabling GHAS for '<repo-name>' repository
[+] GHAS is disabled for '<repo-name>'

# Get GHAS status for <repo-name>
$ node witcher.js -m ghas -a status -r <repo-name>
[-] Checking GHAS status for '<repo-name>' repository
[+] GHAS disabled for <repo-name>

# Enable GHAS on <repo-name>
$ node witcher.js -m ghas -a enable -r <repo-name>
[-] Enabling GHAS for '<repo-name>' repository
[+] GHAS is enabled for '<repo-name>'

GHAS Demo

Secret Scanning

# List repositories where Secret Scanning is disabled
$ node witcher.js -m secret-scanning -a status -r all

# Checking Secret Scanning status for '<repo-name>' repository
$ node witcher.js -m secret-scanning -a status -r <repo-name>

# Enable Secret Scanning for '<repo-name>' repository
$ node witcher.js -m secret-scanning -a enable -r <repo-name>

# Disable Secret Scanning for '<repo-name>' repository
$ node witcher.js -m secret-scanning -a disable -r <repo-name>

CodeQL

# List repositories where CodeQL is disabled
$ node witcher.js -m codeql -a status -r all

# Get status of CodeQL on `offsec-sast-testing`
node witcher.js -m codeql -a status -r offsec-sast-testing

# Enable Codeql for `offsec-sast-testing`
node witcher.js -m codeql -a enable -r offsec-sast-testing

# Disable CodeQL for `offsec-sast-testing`
node witcher.js -m codeql -a disable -r offsec-sast-testing

# Deploy custom codeql.yml file to `offsec-sast-testing`
node witcher.js -m codeql -a deploy -r offsec-sast-testing --jira-ticket PROJECT-123

# Removing existing codeql.yml file from `offsec-sast-testing`
node witcher.js -m codeql -a delete -r offsec-sast-testing --jira-ticket PROJECT-123

CodeQL Demo

More Commands

Witcher Cheatsheet

Daily routine with GitHub Action

Create a daily routine workflow by adding the following configuration to .github/workflows/witcher-daily-routine.yml:

name: "witcher - Daily Routine"

on:
  schedule:
    - cron: '30 7 * * 1,2,3,4,5' # Runs every 9:30 CET expect for Sunday / Saturday
    
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }}

jobs:
  daily-routine:
    name: "App Sec Daily Routine"
    if: ${{ github.event.schedule == '30 7 * * 1,2,3,4,5' }}
    runs-on: ubuntu-latest

    steps:
      - name: "Checkout witcher"
        uses: actions/checkout@v4
        with:
          repository: mf-labs/witcher
          token: ${{ secrets.SAST_TOKEN }}
          path: './witcher'
      
      - name: "Setup NodeJS"
        uses: actions/setup-node@v3
        with:
          node-version: lts/Hydrogen

      - name: "Installing NPM packages"
        run: cd witcher && npm i

      - name: "witcher daily routine"
        run: cd witcher && node witcher.js --daily-summary -m ALL -a status --slack --jira
        env:
          GITHUB_TOKEN: ${{ secrets.SAST_TOKEN }}
          GITHUB_USER: ${{ github.actor }}
          ORG: ${{ secrets.ORG }}
          SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
          SLACK_SIGNING_SECRET: ${{ secrets.SLACK_SIGNING_SECRET }}
          SLACK_CHANNEL: ${{ secrets.SLACK_CHANNEL }}
          SERVERLESS_APP_URL: ${{ secrets.SERVERLESS_APP_URL }}
          JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }}
          JIRA_EMAIL: ${{ secrets.JIRA_EMAIL }}
          JIRA_URL: ${{ secrets.JIRA_URL }}
          JIRA_PROJECT: ${{ secrets.JIRA_PROJECT }}
          JIRA_ISSUE_TYPE: ${{ secrets.JIRA_ISSUE_TYPE }}

References