Skip to content

Vectasec · Get started

Quick start

Run the Vectasec engine locally, scan a deliberately misconfigured Kafka and Redis, and read your first cited findings in about ten minutes.

On this page

This guide takes you from a fresh clone to a cited finding using the CLI. You run the engine on your machine against a Supabase Postgres control plane and three deliberately misconfigured dev targets. The API, worker and console are optional and come last.

Prerequisites#

  • Docker, for the dev scan targets
  • uv. The engine is a Python 3.12 uv project and requires Python 3.12 (not 3.13).
  • A Supabase database: a hosted Supabase project (the free tier works) or a self-hosted Supabase stack. The migrations rely on Supabase's auth schema and roles and on the pgmq, pg_cron and supabase_vault extensions, so a plain Postgres server is not enough.
  • Node 20.9 or later and pnpm 9, only if you want the console

1. Get the source and configure#

Book a demo to get the Vectasec source. From the root of that checkout:

bash
cp .env.example .env

Fill in DATABASE_URL and the SUPABASE_* values. The AI keys (ANTHROPIC_API_KEY, OPENAI_API_KEY, GEMINI_API_KEY) are optional. If you leave them unset, triage writes a deterministic, rule-based summary instead.

The CLI and the API load the nearest .env at or above the directory you run them from, so the file at the repository root covers every engine command below. Variables already set in your shell take precedence. Every setting is listed in Configuration.

2. Apply the schema#

Apply every database migration shipped with the release, in order. There are 16 today. You can use the Supabase SQL editor, psql or the Supabase CLI:

bash
supabase db push

The first migration seeds a demo tenant, 00000000-0000-0000-0000-000000000001. The CLI writes to it unless you pass --tenant, so you can scan before any user exists.

3. Start the dev targets#

bash
docker compose -f deploy/dev/docker-compose.yml up -d

This starts:

  • Kafka 3.9.0 on port 9092
  • RabbitMQ 3.13 with the management API on 15672 (AMQP on 5672)
  • Redis 7.2.4 on 6379

A one-shot seed container then creates the topics payments, customer-pii, orders, audit-events and internal-metrics. The services report healthy in about 30 seconds.

4. Check the wiring#

From the engine directory of the release:

bash
uv run vectasec doctor

The first uv run builds the engine's environment. The output should show 39 connectors and 448 detectors, a connected database with its table count, and extensions: pg_cron, pgmq. It also reports the scan queue depth. If the database is unreachable or an extension is missing, doctor prints PROBLEMS FOUND and exits non-zero.

5. Run a scan#

Save a connection, then scan it:

bash
uv run vectasec connections add --type kafka --name dev-kafka --bootstrap localhost:9092
uv run vectasec scan --connection dev-kafka

connections add checks your flags against the fields the Kafka connector declares and saves the connection without scanning it. To check that the broker is reachable before you scan, run uv run vectasec connections test dev-kafka.

You can also scan without saving a connection first:

bash
uv run vectasec scan --type redis --host localhost --port 6379 --name dev-redis

An ad-hoc scan still records the connection under the name you give, so you can rescan it later with --connection dev-redis. Both examples need no credentials. The dev RabbitMQ does: scan it with --type rabbitmq --url http://localhost:15672, plus --username and --password for the image's built-in default account. That account is itself one of the findings (RABBITMQ.USER.DEFAULT_GUEST_PRESENT).

Each scan prints how many resources, edges, findings and observations it wrote, how many detectors ran, and the scan id. The engine collects from the target first, then writes the results in a single database transaction: it upserts resources and graph edges, runs every matching detector, and writes each finding together with the observation it cites. Findings dedupe on a fingerprint of tenant, connection, rule and resource. Running the same scan again updates existing findings instead of duplicating them, and a status a person set, such as resolved, stays as it is.

After that write, the engine checks the component versions it found against the public OSV and NVD vulnerability feeds. On a machine without internet access, set VECTASEC_OSV_DISABLED=1 and VECTASEC_NVD_DISABLED=1 in .env. Otherwise an unreachable feed is recorded as a coverage gap.

6. Read the results#

bash
uv run vectasec findings      # worst first, with an evidence count per finding
uv run vectasec identities    # non-human identity inventory
uv run vectasec posture       # score and grade, beside the raw counts
uv run vectasec connections   # health, resources and open findings per connection
uv run vectasec scans         # scan history with status and duration
uv run vectasec rules         # every loaded detector, grouped by rule-id prefix

Against the dev Kafka, expect findings such as:

  • KAFKA.LISTENER.PLAINTEXT
  • KAFKA.INTERBROKER.PLAINTEXT
  • KAFKA.AUTHZ.NO_AUTHORIZER
  • KAFKA.TOPIC.AUTO_CREATE_ENABLED

Against the dev Redis, expect findings such as REDIS.AUTH.NO_PASSWORD, REDIS.NETWORK.PROTECTED_MODE_OFF, REDIS.NETWORK.BIND_ALL, REDIS.TLS.DISABLED and REDIS.VERSION.RCE_CVE. The Redis image is pinned to an old version on purpose.

The exact set depends on what each target reports, because some rules only apply under certain conditions. For example, KAFKA.AUTHZ.ALLOW_EVERYONE_IF_NO_ACL is evaluated only when an authorizer is configured. This broker has none, so KAFKA.AUTHZ.NO_AUTHORIZER reports the problem instead. Likewise, the broker sets unclean.leader.election.enable=true, but KAFKA.DURABILITY.UNCLEAN_LEADER_ELECTION stays silent because every dev topic has a single replica, so there is no out-of-sync replica to promote.

Every finding cites at least one observation: the evidence the detector actually read. The evidence count in the findings output is the number of those observations. Each rescan adds new observations, so the count grows as you rescan.

posture weights open findings by severity and turns them into a score from 1 to 100 with a grade from A to F. It also reports how many coverage gaps are open: checks that ran but couldn't read their evidence. Findings, evidence and compliance explains the model.

7. Optional: API, worker and console#

The console reads Postgres under row-level security and sends changes, such as new connections and scans, to the engine API. Scans it starts go onto a queue that the worker drains. Run each process in its own terminal.

Start the engine API with its bundled entry point from the engine directory of the release (it reads .env, ENGINE_HOST and ENGINE_PORT); don't start it with bare uvicorn, which skips the .env load.

It serves on http://127.0.0.1:8000, with the OpenAPI docs at /docs. The API binds to localhost by default. Keep it that way for local work, and read Deployment before you expose it.

Start the worker, from the engine directory of the release:

bash
uv run vectasec worker

The worker drains the pgmq scan queue. If it isn't running, scans started from the console stay queued, and vectasec doctor shows them waiting.

Create the console's environment file: from the console directory of the release, copy its .env.example to .env.local.

Fill in NEXT_PUBLIC_SUPABASE_URL and NEXT_PUBLIC_SUPABASE_ANON_KEY. By default the engine API accepts only verified callers, so set VECTASEC_ENGINE_TOKEN to the same random value (for example from openssl rand -hex 32) in the console's .env.local and in the root .env, then restart the API. Neither .env.example file lists this variable yet. Without it, the engine rejects the console's calls with 401, so actions such as adding a connection fail.

Don't add SUPABASE_SERVICE_ROLE_KEY or DATABASE_URL to the console's .env.local. Both bypass row-level security, and the console never needs them. The RESEND_API_KEY and EMAIL_FROM lines in that file are optional. Delete them if you don't use Resend. The console then skips the emails it sends itself, and sign-in works as normal.

Start the console:

bash
pnpm install
pnpm dev

The console runs on http://localhost:3000.

Create an account on the sign-up page with an email and password. If email confirmation is on in your Supabase project, which is the Supabase default, confirm the address first. An account with no organization goes to onboarding, which creates one and makes you its admin. Your CLI scans belong to the demo tenant, so a new organization starts empty. Open Systems in the sidebar, choose + Connect a system, and follow the scan on Scans. To point the CLI at your organization instead, pass --tenant with your tenant id.

Next steps#