Skip to main content
The safedep query command runs SQL-like queries against SafeDep Cloud’s analytics surface: the packages, projects, endpoints, events, and security findings collected across your tenant, enriched with global threat intelligence (vulnerabilities, EPSS, CISA KEV, OpenSSF Scorecard, and more).

Prerequisites

Install the CLI and sign in to SafeDep Cloud:
SafeDep scopes every query to your tenant. You never write a tenant filter yourself.

Your first query

Start by seeing what you can query. List the tables, then inspect one to view its columns, capability flags, and join edges:
See Discovering the schema for the full set of schema commands. Now run a query. It is mostly SQL. Select some columns, filter with WHERE, sort with ORDER BY:
Two things make this different from a generic database:
  1. Write every column as table.column using the real table name. No table aliases, no bare column names. Result aliases via AS work (COUNT(...) AS n, then ORDER BY n).
  2. Every query must filter on an indexed column or a bounded time range. Here projects.origin_source is indexed, so the query is accepted. This rule keeps queries cheap; the schema marks which columns are indexed.
safedep query exec reads the statement from --sql, --sql-file, or stdin:

How the data is organized

Tables come in two kinds:
  • Tenant tables hold your data: projects, project_versions, boms, packages, endpoints, the component_* finding tables, and the event tables (inventory_events, package_guard_events).
  • Join-only enrichment tables hold global reference data shared across all tenants: vulnerabilities, epss, kev, licenses, malware_analysis, open_source_packages, open_source_projects, scorecards, scorecard_checks, terraform_providers.
The most important rule: every query must reference at least one tenant table. You reach an enrichment table only by joining out from a tenant table. A typical query walks from a first-party project, through its bill of materials, to a package, to a finding, and out to global enrichment:

What SQL we support

Not supported: subqueries, CTEs (WITH), UNION and set operations, window functions, casts, arbitrary functions, and multiple statements.

Discovering the schema

You do not need to memorize tables or columns. The schema is self-describing, and this is the entry point for both humans and AI agents.
Each column carries capability flags that tell you what it can do: schema get also prints the join edges (which tables connect, and their cardinality) and the usage rules with example queries, so one call gives you everything needed to write a valid query.

Letting an AI agent write the queries

Point your AI coding agent at the safedep CLI. The schema is self-describing and server errors come back verbatim, so the agent can discover tables, write a query, and self-correct on its own. Prompt:

Examples

Anchor on the indexed ecosystem column (an OR across all severities would not satisfy the index rule):
EPSS is join-only enrichment, so anchor in the tenant packages table and join out. Sorting by EPSS surfaces the CVEs most likely to be exploited:
kev is the CISA Known Exploited Vulnerabilities catalog. Use a bounded range on the indexed kev.date_added to anchor the query:
is_malware is not indexed, so anchor on the indexed detected_at timestamp:
Walk from packages through component_licenses to the global licenses catalog for SPDX metadata. Anchor on the indexed packages.ecosystem:
endpoints are the machines and CI runners reporting to your tenant. The timestamp columns are indexed, so a bounded range anchors the query:
The endpoint_type and trust_level enums are not groupable, so use WHERE filters and listings rather than GROUP BY for endpoints. Filter them by name (endpoint_type = 'CI_RUNNER').
For “which endpoints…” questions you want a de-duplicated list, not one row per event. endpoints.identifier is not groupable, so use SELECT DISTINCT:
Join Package Guard events to the endpoint that produced them, newest first, for a full audit trail:
The package_ecosystem enum renders as its stored number in table output (2 = ECOSYSTEM_NPM, 3 = ECOSYSTEM_PYPI); use -o json for the enum name.
inventory_events captures items discovered by vet on each endpoint. Filter on the indexed item_kind to find AI-related items:

Output modes

Select with -o / --output. When omitted, the CLI auto-detects the format: a rendered table for an interactive terminal, plain text when piped. JSON shape:

Pagination

Pagination is caller-driven; the CLI does not auto-iterate. Fetch the first page, then re-run the same query with the returned token:

Troubleshooting

SafeDep Cloud Overview

What SafeDep Cloud collects to build the data you query.

Authentication

Sign in with safedep auth login before running queries.

Vet Filtering

Filter findings locally with Vet’s CEL query language.

API & Automation

Programmatic access to SafeDep’s APIs.