A CLI-based vulnerability scanning tool that aggregates results from multiple security scanners (SAST, secrets, and dependency scanning) into unified reports.
- SRS Integration: Offload scanning to SRS (Scan Request Service) API for managed scanning infrastructure
- Standalone Mode: Run scans locally without external API dependencies
- Multi-Scanner Support: Semgrep/OpenGrep (SAST), FOSSA/Trivy (dependencies), and Trufflehog (secrets)
- Parallel Execution: Scanners run concurrently for faster results
- Organized Reports: Results saved in
reports/{owner}/{repo}/{branch}/{commit}/structure - Multiple Output Formats: Table, JSON, and YAML output support
git clone https://github.com/splunk/securelens.git
cd securelens
make configThe Makefile target will build the securelens binary and initialize the configuration file.
The recommended approach is to use SRS (Scan Request Service) which handles scanning infrastructure:
# Set your SRS API endpoint
export SRS_ORCHESTRATOR_API_ENDPOINT="https://your-srs-instance.example.com"
# Run scan via SRS
./securelens scan repo https://github.com/org/repo --mode remote --srs-url ${SRS_ORCHESTRATOR_API_ENDPOINT}SRS will:
- Receive the repository zip
- Run Semgrep (SAST), FOSSA (dependencies), and Trufflehog (secrets)
- Return aggregated results
For local scanning without SRS, install scanner binaries:
# Install all scanners to ~/.local/bin
make install_scan_tools_standalone INSTALL_DIR=~/.local/bin
# Ensure ~/.local/bin is in your PATH
export PATH="$HOME/.local/bin:$PATH"
# Verify installation
opengrep --version && trivy --version && trufflehog --version
# Run standalone scan
./securelens scan repo https://github.com/org/repo --mode standalone| Mode | Flag | Description |
|---|---|---|
| Remote | --mode remote |
Send repo to SRS API (Semgrep, FOSSA, Trufflehog) |
| Standalone | --mode standalone |
Run local binaries (OpenGrep, Trivy, Trufflehog) |
| Local | --mode local |
Run configured local scanners (requires config) |
./securelens scan repo https://github.com/org/repo --mode remote --srs-url ${SRS_ORCHESTRATOR_API_ENDPOINT}./securelens scan repo https://github.com/org/repo --mode standaloneSave detailed reports to the reports/ directory:
./securelens scan repo https://github.com/org/repo --mode standalone --debug# Scan a specific branch
./securelens scan repo https://github.com/org/repo --branch develop --mode standalone
# Scan a specific commit
./securelens scan repo https://github.com/org/repo --commit abc123 --mode standalone# Run only OpenGrep (SAST)
./securelens scan repo https://github.com/org/repo --mode standalone --scanners opengrep
# Run OpenGrep and Trivy (skip secrets scanning)
./securelens scan repo https://github.com/org/repo --mode standalone --scanners opengrep,trivy./securelens scan repo https://github.com/org/repo --mode standalone --parallel=falseAfter a scan completes, you'll see a summary table:
=== SecureLens Scan Report ===
Repository: https://github.com/org/repo
Branch: main
Commit: abc123def456...
Timestamp: 2025-12-09T00:58:43Z
Status: completed
┌────────────┬──────────┬───────────────────┬────────────────┐
│ SCANNER │ STATUS │ FINDINGS │ BY SEVERITY │
├────────────┼──────────┼───────────────────┼────────────────┤
│ opengrep │ COMPLETE │ 183 findings │ E:40 W:96 I:47 │
│ trivy │ COMPLETE │ 0 vulnerabilities │ - │
│ trufflehog │ COMPLETE │ 3 findings │ - │
└────────────┴──────────┴───────────────────┴────────────────┘
Column Descriptions:
- SCANNER: The security scanner that ran
- STATUS:
COMPLETE(success),ERROR(failed), orSKIPPED - FINDINGS: Total count of issues found
- BY SEVERITY: Breakdown using abbreviations:
C= CriticalH= HighE= ErrorM= MediumW= WarningL= LowI= Info
| Scanner | Type | Detects |
|---|---|---|
| OpenGrep | SAST | Code vulnerabilities, security anti-patterns, bugs |
| Trivy | SCA | Vulnerable dependencies, CVEs in packages |
| Trufflehog | Secrets | Hardcoded credentials, API keys, tokens |
When using --debug, reports are saved to reports/{owner}/{repo}/{branch}/{commit}/.
./securelens scan results --listOutput:
=== Available Scan Reports ===
Reports directory: reports
Found 4 report(s):
splunk/securelens [main @ 4b18c9f1]
Path: reports/splunk/securelens/main/4b18c9f1/latest.json
splunk/other-repo [develop @ 9725cf87]
Path: reports/splunk/other-repo/develop/9725cf87/latest.json
# Table format (default)
./securelens scan results reports/splunk/repo/main/abc123/latest.json
# JSON format
./securelens scan results reports/splunk/repo/main/abc123/latest.json --format json
# YAML format
./securelens scan results reports/splunk/repo/main/abc123/latest.json --format yaml# Show all findings with details
./securelens scan results reports/splunk/repo/main/abc123/latest.json --details
# Filter by specific scanner
./securelens scan results reports/splunk/repo/main/abc123/latest.json --details --scanner opengrepDetailed output shows individual findings:
=== OPENGREP Findings ===
┌───┬──────────┬──────────────────────┬──────────────────┬──────┬─────────────────────────┐
│ # │ SEVERITY │ RULE │ FILE │ LINE │ MESSAGE │
├───┼──────────┼──────────────────────┼──────────────────┼──────┼─────────────────────────┤
│ 1 │ ERROR │ go.lang.security... │ pkg/auth/jwt.go │ 45 │ JWT token not validated │
│ 2 │ WARNING │ go.lang.best-pra... │ pkg/db/query.go │ 123 │ SQL query concatenation │
└───┴──────────┴──────────────────────┴──────────────────┴──────┴─────────────────────────┘
reports/
└── {owner}/
└── {repo}/
└── {branch}/
└── {commit-short}/
├── latest.json # Most recent combined report
├── report-YYYYMMDD-HHMMSS.json
├── opengrep-latest.json # Raw OpenGrep output
├── trivy-latest.json # Raw Trivy output
└── trufflehog-latest.json # Raw Trufflehog output
SecureLens looks for config.yaml in the current directory or ~/.securelens/config.yaml.
# config.yaml
srs:
base_url: "https://srs.example.com" # Optional SRS API
scanners:
opengrep:
rules_path: "assets/opengrep-rules"
trivy:
severity: "CRITICAL,HIGH,MEDIUM"
trufflehog:
only_verified: falseSecureLens can send scan results to Splunk via HEC (HTTP Event Collector). Each finding/vulnerability/secret is sent as a separate event.
Pull the Splunk image:
docker pull splunk/splunk:latestOn macOS (Apple Silicon), use the Linux AMD64 image:
docker pull --platform linux/amd64 splunk/splunk:latestStart Splunk Enterprise:
docker run -d --name splunk \
-p 8000:8000 -p 8088:8088 \
-e SPLUNK_START_ARGS='--accept-license' \
-e "SPLUNK_GENERAL_TERMS=--accept-sgt-current-at-splunk-com" \
-e SPLUNK_PASSWORD='your_secure_password' \
splunk/splunk:latest startOn macOS (Apple Silicon):
docker run -d --name splunk --platform linux/amd64 \
-p 8000:8000 -p 8088:8088 \
-e SPLUNK_START_ARGS='--accept-license' \
-e "SPLUNK_GENERAL_TERMS=--accept-sgt-current-at-splunk-com" \
-e SPLUNK_PASSWORD='your_secure_password' \
splunk/splunk:latest startWait a couple of minutes, then open the UI at http://localhost:8000 and sign in as admin with the password you set on the command above.
Optional: switch to the free license (after the trial ends, this happens automatically). Go to Settings -> Licensing -> Change License Group -> Free License.
- Settings -> Data Inputs -> HTTP Event Collector -> Global Settings -> Enable -> Save.
- Click New Token, choose a name, then set the sourcetype to
_jsonand select the index you want (for example,main). - Copy the generated token.
Add this to your config file:
splunk:
enabled: true
hec_endpoint: "https://splunk.example.com:8088/services/collector"
hec_token: "your-hec-token"Run a standalone scan to send events:
./securelens scan repo https://github.com/org/repo --mode standaloneUse these searches to build tables for each scanner. Replace index with your value.
OpenGrep (one event per finding):
index=main sourcetype=_json scanner=opengrep
| spath
| spath path=results.findings{} output=finding
| spath input=finding path=check_id output=rule_id
| spath input=finding path=path output=file
| spath input=finding path=start.line output=line
| spath input=finding path=extra.severity output=severity
| spath input=finding path=extra.message output=message
| table _time repository scanner severity rule_id file line message
| appendpipe [
stats count
| where count=0
| eval _time=now(), repository="-", scanner="opengrep", severity="-", rule_id="No findings", file="-", line="-", message="-"
| table _time repository scanner severity rule_id file line message
]
Trivy (one event per vulnerability):
index=main sourcetype=_json scanner=trivy
| spath
| spath path=results.results{} output=entry
| spath input=entry path=Target output=target
| spath input=entry path=Vulnerabilities{} output=vuln
| spath input=vuln path=VulnerabilityID output=cve
| spath input=vuln path=PkgName output=package
| spath input=vuln path=InstalledVersion output=installed
| spath input=vuln path=FixedVersion output=fixed
| spath input=vuln path=Severity output=severity
| spath input=vuln path=Title output=title
| table _time repository scanner severity cve package installed fixed target title
| appendpipe [
stats count
| where count=0
| eval _time=now(), repository="-", scanner="trivy", severity="-", cve="No findings", package="-", installed="-", fixed="-", target="-", title="-"
| table _time repository scanner severity cve package installed fixed target title
]
Trufflehog (one event per secret):
index=main sourcetype=_json scanner=trufflehog
| spath
| spath path=results.findings{} output=finding
| spath input=finding path=DetectorName output=detector
| spath input=finding path=Verified output=verified
| spath input=finding path=Redacted output=redacted
| spath input=finding path=SourceMetadata.Data.Git.file output=file_git
| spath input=finding path=SourceMetadata.Data.Git.line output=line_git
| spath input=finding path=SourceMetadata.Data.Filesystem.file output=file_fs
| spath input=finding path=SourceMetadata.Data.Filesystem.line output=line_fs
| eval file=coalesce(file_git, file_fs), line=coalesce(line_git, line_fs)
| where detector!=""
| table _time repository scanner verified detector file line redacted
| appendpipe [
stats count
| where count=0
| eval _time=now(), repository="-", scanner="trufflehog", verified="-", detector="No findings", file="-", line="-", redacted="-"
| table _time repository scanner verified detector file line redacted
]
# Scan commands
securelens scan repo <url> [flags] # Scan a repository
securelens scan results [path] [flags] # View saved reports
# Scan flags
--mode standalone # Use local scanner binaries
--branch <name> # Target branch
--commit <sha> # Target commit
--scanners <list> # Comma-separated scanner list
--parallel # Run scanners in parallel (default: true)
--debug # Save detailed reports to reports/
--format <type> # Output format: table, json, yaml
# Results flags
--list # List all saved reports
--details # Show detailed findings
--scanner <name> # Filter by scanner name
--format <type> # Output format: table, json, yamlApache 2.0 (ASL2)
Contributions are welcome! Please open an issue or submit a pull request.