Overview
Meerkat is a dependency-tracking platform for your Git repositories. It scans repositories across configured repository groups, extracts all project dependencies, and presents them through a web interface — enabling rapid identification of which projects are affected when a package has a known security threat.
Key capabilities:
- Projects Dashboard — view all scanned projects with their dependencies, versions, and ecosystems
- Hunt — search for packages across all repos to identify exposure instantly
- Allow List & Policy Enforcement — curate approved dependencies and enforce them via CI
- Vulnerability Threat Feed — auto-subscribe to malware reports from a vulnerability intelligence feed
- CI Agent — gate CI pipelines on policy compliance
- Notifications — email and chat alerts for violations and new malware
Prerequisites
Before deploying Meerkat, ensure you have:
- Docker and Docker Compose installed
- A Git hosting platform Personal Access Token (PAT) with
read_apiscope - A PostgreSQL database (provided automatically by the devcontainer)
- OIDC client credentials from your identity provider
For local development, VS Code with the Dev Containers extension is recommended — no local tool installation required.
Quick Start
The fastest way to run Meerkat locally is via the VS Code devcontainer:
1. Clone the repository
git clone https://git.internal/your-group/meerkat.git
cd meerkat
2. Create your .env file
cp .env.example .env
# Edit .env and fill in real values
3. Open in devcontainer
Open the project folder in VS Code. When prompted, click "Reopen in Container". The devcontainer will build the Go backend and PostgreSQL services, run DB migrations, and install all required tooling automatically.
4. Start the server
cd backend && go run main.go
The server will be available at http://localhost:8080.
frontend/index.html directly in a browser. The contact form requires the Go backend.
Environment Variables
All secrets must be provided via a .env file (gitignored). Copy .env.example to get started. Non-secret configuration lives in config.yaml.
| Variable | Required | Description |
|---|---|---|
| GIT_HOST_URL | Yes | Git hosting platform instance base URL |
| GIT_HOST_TOKEN | Yes | Personal Access Token with read_api scope |
| WEBHOOK_SECRET | Yes | Shared secret for CI webhook authentication |
| DATABASE_URL | Yes | PostgreSQL connection string: postgresql://user:pass@host:port/db |
| ADMIN_USERS | No | Comma-separated OIDC preferred_username values for admin role |
| THREAT_FEED_ENABLED | No | Enable vulnerability threat feed (true/false, default: true) |
| THREAT_FEED_POLL_INTERVAL | No | How often to poll the threat feed (Go duration, default: 1h) |
| EMAIL_TENANT_ID | Notifications | Email API tenant ID |
| EMAIL_CLIENT_ID | Notifications | App registration client ID with mail-send permission |
| EMAIL_CLIENT_SECRET | Notifications | App registration client secret |
| EMAIL_SENDER | Notifications | Mailbox UPN/object ID the app sends as |
| CHAT_WEBHOOK_URL | Chat | Base URL of the team chat server |
| CHAT_USERNAME | Chat | Bot account username |
| CHAT_PASSWORD | Chat | Bot account password |
| MEERKAT_BASE_URL | No | Public base URL embedded in notification emails |
| NOTIFICATIONS_DEV_OVERRIDE | No | Redirect all email notifications to this address in dev |
| TENANT_SCAN_ENABLED | No | Master switch for tenant-wide scanning (default: true) |
| INCREMENTAL_SCAN_ENABLED | No | Skip unchanged projects in scans (default: true) |
Authentication & Roles
Meerkat uses OpenID Connect (OIDC) for authentication. All routes require authentication except /docs, /openapi.yaml, and /metrics.
Roles
| Role | Description |
|---|---|
admin |
Full access — can trigger scans, manage deny/allow list entries and enforcements, and access all pages. |
reader |
Read-only access — can view all pages but cannot trigger scans or modify list entries. |
The ADMIN_USERS variable accepts a comma-separated list of OIDC preferred_username values (case-insensitive). Users whose username matches an entry are assigned the admin role; all others get reader. If ADMIN_USERS is unset, all authenticated users are treated as admins.
ADMIN_USERS=jalexander,jdoe
CI Agent — Setup
The Meerkat CI agent is a single static Go binary distributed as a container image (meerkat-ci-agent:latest). Add the following stage to any project's .ci-pipeline.yml:
meerkat-scan:
stage: test
image: registry.internal/internal/meerkat-ci-agent:latest
variables:
MEERKAT_URL: "https://meerkat.internal"
MEERKAT_SECRET: $MEERKAT_WEBHOOK_SECRET
script:
- meerkat-ci-agent --output meerkat-report.json
artifacts:
paths:
- meerkat-report.json
when: always
expire_in: 30 days
allow_failure: false
CI_PROJECT_ID is provided automatically by your CI platform — no extra configuration needed.
CI Agent Environment Variables
| Variable | Source | Description |
|---|---|---|
| MEERKAT_URL | Pipeline config | Base URL of the Meerkat instance |
| MEERKAT_SECRET | CI/CD variable | Webhook shared secret (must match WEBHOOK_SECRET) |
| CI_PROJECT_ID | CI platform (auto) | Numeric project ID |
| CI_PIPELINE_ID | CI platform (auto) | Included in artifact for traceability |
| CI_JOB_ID | CI platform (auto) | Included in artifact for traceability |
CI Agent — Flags & Exit Codes
Flags
| Flag | Default | Description |
|---|---|---|
--allow-failure | false | Exit 0 even when denied dependencies are found (warn-only rollout mode) |
--output <path> | none | Write the full JSON response as a CI artifact |
--timeout <secs> | 300 | HTTP request timeout in seconds |
Exit Codes
| Code | Meaning |
|---|---|
| 0 | Pass — scan succeeded, no deny-list or allow-list violations |
| 1 | Fail — denied or unapproved dependencies found, or unexpected error |
| 2 | Timeout — scan did not complete within the allowed time |
CI Agent — Artifact Output
When --output is specified, the agent writes a JSON file wrapping the scan response with CI metadata:
{
"http_status": 200,
"timestamp": "2026-04-09T11:00:00Z",
"ci_project_id": "42",
"ci_pipeline_id": "12345",
"ci_job_id": "67890",
"result": {
"status": "pass",
"project_id": 1,
"project_name": "my-app",
"violations": [],
"violation_count": 0,
"allow_list_violations": [],
"allow_list_violation_count": 0,
"allow_list_enforced": false,
"scan_status": "success",
"dependency_count": 87,
"message": "Scan completed. No policy violations found."
}
}
Supported Package Ecosystems
Meerkat extracts dependencies from the following manifest file types:
yarn.lock
package-lock.json
pyproject.toml
Pipfile / Pipfile.lock
go.sum
Gemfile.lock
build.gradle
composer.lock
Cargo.lock
packages.config
API Reference
All endpoints are under /api/v1/. Full interactive documentation is available at /docs (Swagger UI) and the raw schema at /openapi.yaml.
| Method | Path | Description | Auth |
|---|---|---|---|
| GET | /api/v1/projects | List all scanned projects | Required |
| GET | /api/v1/projects/:id/dependencies | List dependencies for a project | Required |
| POST | /api/v1/hunt | Search packages across all projects | Required |
| POST | /api/v1/webhooks/scan | CI webhook to trigger rescan | Secret |
| GET | /api/v1/allow-list | List approved packages | Required |
| POST | /api/v1/allow-list | Create allow list entry | Admin |
| PUT | /api/v1/allow-list/:id | Update allow list entry | Admin |
| DELETE | /api/v1/allow-list/:id | Delete allow list entry | Admin |
| GET | /api/v1/reports/:type | Policy report (allow or deny) | Required |
| GET | /api/v1/threat-feed/status | Threat feed poller status | Required |
| POST | /api/v1/threat-feed/poll | Trigger manual threat feed poll | Admin |
| GET | /api/v1/notifications/settings | Get notification configuration | Admin |
| PUT | /api/v1/notifications/settings | Update notification configuration | Admin |
| GET | /health | Service health check | Public |
| GET | /metrics | Prometheus metrics | Public |
| GET | /docs | Swagger UI | Public |