A CLI tool that syncs security vulnerabilities from GitHub Dependabot and Snyk to Jira, automating your security ticket workflow.
- Multi-provider support: Fetch vulnerabilities from GitHub Dependabot and Snyk
- Local cache with semantic search: Persistent Stoolap-backed cache with natural-language search via built-in embeddings
- Targeted lookups: Search by keyword, CVE, Snyk ID, severity, package, or repository
- Jira integration: Automatically create and update Jira tickets
- Cross-provider deduplication: Merge vulnerabilities by CVE across providers into unified tickets
- Duplicate detection: Finds existing open tickets and adds informative comments instead of creating duplicates
- Comment throttling: Only adds comments once per 24 hours to avoid noise
- Sprint management: Automatically add high-severity issues to the active sprint
- Flexible filtering: Filter by severity, CVSS score, age, packages, and repositories
- Pattern matching: Include/exclude repos and projects using glob patterns
- Priority mapping: Map vulnerability severity to Jira priority levels
- Severity normalization: Normalize provider-specific severity values (e.g., GitHub's "moderate" → "medium")
- Namespaced labels: Auto-generate structured Jira labels (
argus:dependabot,argus:snyk,argus:critical)
curl -fsSL https://raw.githubusercontent.com/sentiolabs/argus/main/scripts/install.sh | bashInstall a specific version:
curl -fsSL https://raw.githubusercontent.com/sentiolabs/argus/main/scripts/install.sh | bash -s -- --tag=v0.4.0go install github.com/sentiolabs/argus@latestgit clone https://github.com/sentiolabs/argus.git
cd argus
make build# Build the image
docker build -t argus .
# Run with environment variables
docker run --rm \
-e ARGUS_GITHUB_TOKEN \
-e ARGUS_SNYK_TOKEN \
-e ARGUS_JIRA_URL \
-e ARGUS_JIRA_USERNAME \
-e ARGUS_JIRA_TOKEN \
-v $(pwd)/.argus.yaml:/app/.argus.yaml:ro \
argus syncArgus includes a Helm chart for running as a scheduled CronJob in Kubernetes.
# Install with inline values
helm install argus ./charts/argus \
--namespace argus --create-namespace \
--set credentials.githubToken="ghp_xxx" \
--set credentials.snykToken="xxx-xxx" \
--set credentials.jiraUrl="https://your-domain.atlassian.net" \
--set credentials.jiraUsername="your-email@example.com" \
--set credentials.jiraToken="xxx" \
--set config.providers.github.orgs[0]="your-org"Or create a values.yaml file:
schedule: "0 */6 * * *" # Every 6 hours
credentials:
githubToken: "ghp_xxx"
snykToken: "xxx-xxx"
jiraUrl: "https://your-domain.atlassian.net"
jiraUsername: "your-email@example.com"
jiraToken: "xxx"
config:
defaults:
jira:
project: "SEC"
board_name: "Security Board"
providers:
github:
enabled: true
orgs:
- your-org
snyk:
enabled: true
org_id: "your-snyk-org-id"helm install argus ./charts/argus -f values.yaml -n argus --create-namespaceUse an existing secret instead of storing credentials in values:
# Create secret manually
kubectl create secret generic argus-credentials -n argus \
--from-literal=ARGUS_GITHUB_TOKEN="ghp_xxx" \
--from-literal=ARGUS_SNYK_TOKEN="xxx" \
--from-literal=ARGUS_JIRA_URL="https://your-domain.atlassian.net" \
--from-literal=ARGUS_JIRA_USERNAME="email@example.com" \
--from-literal=ARGUS_JIRA_TOKEN="xxx"
# Install with existing secret
helm install argus ./charts/argus -n argus \
--set existingSecret=argus-credentialsSet the following environment variables (or use a .env file):
# GitHub
ARGUS_GITHUB_TOKEN=ghp_xxxxxxxxxxxx
# Snyk
ARGUS_SNYK_TOKEN=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
# Jira
ARGUS_JIRA_URL=https://your-domain.atlassian.net
ARGUS_JIRA_USERNAME=your-email@example.com
ARGUS_JIRA_TOKEN=xxxxxxxxxxxxxxxxCreate a .argus.yaml file in your working directory:
defaults:
jira:
project: "SEC"
board_name: "Security Team Board"
labels:
- security
- vulnerability
thresholds:
priority:
critical: "Highest"
high: "High"
medium: "Medium"
low: "Low"
sprint_min_severity: "high"
filters:
min_severity: "medium"
max_age_days: 90
# Severity mappings (optional - defaults shown)
# severity_mappings:
# moderate: medium # GitHub's "moderate" → Argus's "medium"
providers:
github:
enabled: true
orgs:
- your-org
exclude_repos:
- archived-repo
snyk:
enabled: true
org_id: "your-snyk-org-id"
project_patterns:
- "your-org/*"See config.example.yaml for a complete example.
# Fetch from all providers, dedupe, and sync to Jira
argus sync
# Preview what would be synced (no Jira changes)
argus sync --dry-run
# Verbose output
argus sync -v
# JSON output
argus sync --output jsonUse verify to preview vulnerabilities from a specific provider without syncing to Jira:
# Preview GitHub Dependabot alerts
argus verify --provider github
# Preview Snyk issues
argus verify --provider snykThis is useful for:
- Testing provider configuration
- Debugging API connectivity
- Previewing what will be synced
Argus includes a persistent cache backed by Stoolap with built-in semantic search, enabling fast lookups without re-fetching from APIs.
# Fetch and cache vulnerabilities
argus cache refresh # all providers
argus cache refresh --provider snyk # snyk only
# Check cache status
argus cache status
# Search by keyword (semantic search)
argus search "session handling auth bypass"
# Search by field filters
argus search "severity:critical"
argus search "package:rack* provider:snyk"
# Combine semantic search with field filters
argus search "rails" --provider snyk --repo bactrack/view-api
# Look up a specific vulnerability by ID or CVE
argus show SNYK-RUBY-RACKSESSION-15928857
argus show CVE-2025-27610
# Search across all cached projects
argus search "severity:high" --all-projects
# JSON output
argus search "rails" --output json
argus show CVE-2025-27610 --output jsonSupported search field prefixes: severity:, package:, repo:, provider:, cve:, id:
The cache is stored at ~/.cache/argus/vulns.db with a 24-hour TTL. Search and show commands auto-fetch if the cache is expired.
- Fetch: Argus queries all configured providers for open security vulnerabilities
- Filter: Vulnerabilities are filtered by severity, age, CVSS score, and package patterns
- Merge: Vulnerabilities are deduplicated by CVE across providers (e.g., same CVE from GitHub and Snyk becomes one entry)
- Check Jira: For each merged vulnerability, Argus searches Jira for existing open tickets
- Create or Update:
- If no ticket exists: Create a new Jira ticket with severity-based priority
- If ticket exists and >24h since last comment: Add an informative comment
- If ticket exists and <24h since last comment: Skip (throttled)
- Sprint Assignment: High-severity issues are automatically added to the active sprint
Different vulnerability providers use different severity terminology. Argus normalizes these to a consistent set of canonical levels:
| Argus Level | Provider Values |
|---|---|
critical |
critical |
high |
high |
medium |
medium, moderate (GitHub) |
low |
low |
By default, GitHub's "moderate" is automatically mapped to "medium". You can customize these mappings in your config:
defaults:
severity_mappings:
moderate: medium # Default: GitHub's "moderate" → "medium"
informational: low # Custom: map "informational" → "low"Argus automatically adds structured labels to Jira tickets for easy filtering:
| Label | Description |
|---|---|
argus |
Base label for all Argus-created tickets |
argus:dependabot |
Detected by GitHub Dependabot |
argus:snyk |
Detected by Snyk |
argus:critical |
Critical severity |
argus:high |
High severity |
argus:medium |
Medium severity |
argus:low |
Low severity |
These are in addition to any custom labels configured in defaults.jira.labels.
Required scopes:
repo(for private repos) orpublic_repo(for public repos only)security_events- Read Dependabot alerts
- API token from Snyk account settings
- Requires access to the organization specified in config
- API token from Atlassian account settings
- User must have permission to create issues in the target project
MIT License - see LICENSE for details.