Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions .github/workflows/dependency-vulnerability-scan.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
name: Dependency Vulnerability Scanning

on:
pull_request:
paths:
- "**/package.json"
- "**/package-lock.json"
- "**/Cargo.toml"
- "**/Cargo.lock"
- "scripts/audit-vulnerabilities.sh"
schedule:
- cron: "0 0 * * 1" # Weekly Monday scan
workflow_dispatch:

concurrency:
group: vuln-scan-${{ github.ref }}
cancel-in-progress: true

permissions:
contents: read
security-events: write

jobs:
npm-audit:
name: npm-vulnerability-audit
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: "20"

- name: Audit Listener Dependencies
run: |
cd listener
npm audit --audit-level=high

- name: Audit Dashboard Dependencies
run: |
cd dashboard
npm audit --audit-level=high

cargo-audit:
name: cargo-vulnerability-audit
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Set up Rust & cargo-audit
uses: rustsec/audit-check@v2.0.0
with:
token: ${{ secrets.GITHUB_TOKEN }}
manifest-path: contract/Cargo.toml
35 changes: 35 additions & 0 deletions docs/DEPENDENCY_VULNERABILITY_SCANNING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# 🛡️ Automated Dependency Vulnerability Scanning Policy

This document details NotifyChain's automated vulnerability scanning architecture across JavaScript, TypeScript, and Rust toolchains (Issue #718).

---

## 1. Tooling Architecture

| Ecosystem | Scanner Tool | Target Files | Severity Gate |
|---|---|---|---|
| **Node.js (Listener & Dashboard)** | `npm audit` | `package.json`, `package-lock.json` | High / Critical (Blocking) |
| **Rust (Smart Contracts)** | `cargo-audit` (RustSec) | `Cargo.toml`, `Cargo.lock` | Warnings / Vulnerabilities (Blocking) |

---

## 2. Severity Classification Policy

1. **Informational (Low / Moderate)**: Logged during local and CI audits to provide developers visibility into non-critical advisory notices without failing builds.
2. **Blocking (High / Critical)**: PRs introducing known exploitable vulnerabilities or critical security advisories fail CI automatically.

---

## 3. Local Audit Execution

Run the consolidated vulnerability scanner locally:

```bash
chmod +x scripts/audit-vulnerabilities.sh

# Standard blocking audit
./scripts/audit-vulnerabilities.sh

# Non-blocking advisory mode
./scripts/audit-vulnerabilities.sh --warn-only
```
103 changes: 103 additions & 0 deletions scripts/audit-vulnerabilities.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
#!/usr/bin/env bash
# ==============================================================================
# NotifyChain Automated Dependency Vulnerability Scanner (Issue #718)
# ==============================================================================
# Scans Node.js and Rust dependencies for known security vulnerabilities (CVEs)
# Distinguishes informational (Low/Moderate) from blocking (High/Critical) findings.
# ==============================================================================
set -u

RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ROOT_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)"

WARN_ONLY=false
if [[ "${1:-}" == "--warn-only" ]]; then
WARN_ONLY=true
fi

BLOCKING_FAILURES=0

echo -e "${BLUE}==================================================================${NC}"
echo -e "${BLUE} 🛡️ NotifyChain Automated Dependency Vulnerability Scanner ${NC}"
echo -e "${BLUE}==================================================================${NC}\n"

audit_npm_package() {
local dir_name="$1"
local full_path="${ROOT_DIR}/${dir_name}"

echo -e "${BLUE}--- Scanning Node.js [${dir_name}] ---${NC}"
if [ ! -f "${full_path}/package.json" ]; then
echo -e "${YELLOW}Skipped: No package.json in ${dir_name}/${NC}\n"
return
fi

if ! command -v npm >/dev/null 2>&1; then
echo -e "${YELLOW}npm CLI not found locally; skipping live npm audit.${NC}\n"
return
fi

cd "${full_path}"

# 1. Informational scan (Low/Moderate)
echo -n " • Informational check (Low/Moderate): "
npm audit --audit-level=low >/dev/null 2>&1 && echo -e "${GREEN}Clean${NC}" || echo -e "${YELLOW}Findings present (non-blocking)${NC}"

# 2. Blocking scan (High/Critical)
echo -n " • Blocking check (High/Critical): "
if npm audit --audit-level=high >/dev/null 2>&1; then
echo -e "${GREEN}✓ Passed (No High/Critical CVEs)${NC}\n"
else
echo -e "${RED}✗ HIGH/CRITICAL Vulnerabilities Found!${NC}"
npm audit --audit-level=high || true
BLOCKING_FAILURES=$((BLOCKING_FAILURES + 1))
echo ""
fi
}

audit_cargo_package() {
local dir_name="$1"
local full_path="${ROOT_DIR}/${dir_name}"

echo -e "${BLUE}--- Scanning Rust [${dir_name}] ---${NC}"
if [ ! -f "${full_path}/Cargo.toml" ]; then
echo -e "${YELLOW}Skipped: No Cargo.toml in ${dir_name}/${NC}\n"
return
fi

if ! command -v cargo-audit >/dev/null 2>&1; then
echo -e "${YELLOW}cargo-audit not installed locally; skipping live cargo scan.${NC}\n"
return
fi

cd "${full_path}"
if cargo audit --deny warnings; then
echo -e "${GREEN}✓ Passed (No Rust CVE advisories)${NC}\n"
else
echo -e "${RED}✗ Rust Security Advisories Detected!${NC}\n"
BLOCKING_FAILURES=$((BLOCKING_FAILURES + 1))
fi
}

audit_npm_package "listener"
audit_npm_package "dashboard"
audit_cargo_package "contract"

echo -e "${BLUE}==================================================================${NC}"
if [ $BLOCKING_FAILURES -eq 0 ]; then
echo -e "${GREEN}✅ All components passed high-severity vulnerability checks!${NC}"
exit 0
else
if [ "$WARN_ONLY" = true ]; then
echo -e "${YELLOW}⚠️ Found ${BLOCKING_FAILURES} blocking vulnerability finding(s), but exiting 0 due to --warn-only.${NC}"
exit 0
else
echo -e "${RED}❌ Found ${BLOCKING_FAILURES} blocking vulnerability finding(s). Remediation required.${NC}"
exit 1
fi
fi