Dependency Audit Cron Job — Weekly npm, pip & bundle Check on Monday
Run npm audit, pip-audit, or bundle audit every Monday at midnight and automatically open a GitHub issue when vulnerabilities are found.
What this schedule does
The expression 0 0 * * 1 fires at exactly midnight every Monday. The five fields mean: minute=0, hour=0, any day of month, any month, day 1 (Monday only). It runs once per week at the start of the work week.
This is the standard schedule for automated security hygiene. Running the audit on Monday means your team sees any new vulnerability reports first thing in the week — when the issue is freshly created and engineers are at their desks to triage it. Weekly is the right cadence for most projects: frequent enough to catch newly-disclosed CVEs quickly, infrequent enough that alert fatigue does not set in.
Pair it with a script that exits non-zero on findings and automatically opens a labeled GitHub issue. That way no vulnerability report gets lost in a CI log that nobody reads.
How to run dependency audits automatically
The audit command varies by ecosystem, but the pattern is the same for all of them: run the tool, capture its exit code, and open an issue when it is non-zero.
- Node.js:
npm audit --audit-level=moderate— exits 1 on vulnerabilities at or above the threshold - Python:
pip-audit— checks installed packages against PyPI Advisory Database and OSV - Ruby:
bundle audit check --update— refreshes the advisory database before checking - Go:
govulncheck ./...— scans for known vulnerabilities in Go module dependencies - Rust:
cargo audit— queries the RustSec Advisory Database
For GitHub Actions, the gh CLI is pre-installed and authenticated — use gh issue create in the failure path to file an issue with full audit output attached. Label it security and assign it to your security champion.
Platform snippets
# crontab -e (runs as the app user, UTC on most servers) 0 0 * * 1 /opt/scripts/dependency-audit.sh >> /var/log/dep-audit.log 2>&1 # dependency-audit.sh #!/usr/bin/env bash set -euo pipefail cd /var/www/myapp # npm npm audit --audit-level=moderate # pip # pip-audit # Ruby # bundle audit check --update
name: Weekly Dependency Audit
on:
schedule:
- cron: '0 0 * * 1' # UTC midnight every Monday
workflow_dispatch: # allow manual runs
jobs:
audit:
runs-on: ubuntu-latest
permissions:
issues: write # needed to open issues
contents: read
steps:
- uses: actions/checkout@v4
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run npm audit
id: audit
run: |
npm audit --audit-level=moderate --json > audit-report.json 2>&1 || echo "AUDIT_FAILED=true" >> "$GITHUB_ENV"
- name: Open GitHub issue on failure
if: env.AUDIT_FAILED == 'true'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
VULN_COUNT=$(jq '.metadata.vulnerabilities | to_entries | map(.value) | add' audit-report.json 2>/dev/null || echo "unknown")
gh issue create \
--title "Security: npm audit found vulnerabilities ($(date -u +'%Y-%m-%d'))" \
--label "security,dependencies" \
--body "## Weekly Dependency Audit Failed
**Vulnerability count:** $VULN_COUNT
\`\`\`json
$(cat audit-report.json | head -c 6000)
\`\`\`
Run \`npm audit fix\` locally to apply automatic fixes, or \`npm audit\` for the full report.
_Generated by the [weekly-dependency-audit](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) workflow._"
- name: Fail the workflow if audit failed
if: env.AUDIT_FAILED == 'true'
run: exit 1
# EventBridge cron (6 fields — adds year field, always UTC) cron(0 0 ? * MON *) # Wire it to a Lambda that runs your audit container, # or use an ECS Scheduled Task targeting your app service.
apiVersion: batch/v1
kind: CronJob
metadata:
name: dependency-audit
namespace: security
spec:
schedule: "0 0 * * 1"
jobTemplate:
spec:
template:
spec:
containers:
- name: auditor
image: node:20-slim
workingDir: /app
command:
- /bin/sh
- -c
- |
npm ci --ignore-scripts && \
npm audit --audit-level=moderate || \
curl -s -X POST "$SLACK_WEBHOOK" \
-H 'Content-type: application/json' \
-d '{"text":"Dependency audit failed — check the job logs."}'
env:
- name: SLACK_WEBHOOK
valueFrom:
secretKeyRef:
name: audit-secrets
key: slack-webhook
volumeMounts:
- name: app-source
mountPath: /app
restartPolicy: OnFailure
volumes:
- name: app-source
configMap:
name: package-json
Timezone note
Standard crontab uses the system timezone of the machine it runs on. GitHub Actions and AWS EventBridge always run in UTC. If your team is on US Eastern time (UTC-5), 0 0 * * 1 fires at 7pm Sunday EST — which means the issue is waiting in your inbox Monday morning. If you want it to fire at midnight local time, use 0 5 * * 1 (UTC-5) or 0 8 * * 1 (UTC+8 for Singapore). Kubernetes 1.27+ supports spec.timeZone: "America/New_York" to set the timezone directly.