Skip to content

Security: asheshgoplani/opengraphdb

Security

SECURITY.md

Security Policy

Reporting a Vulnerability

If you believe you have found a security vulnerability in OpenGraphDB, please report it privately. Do not open a public GitHub issue.

Private channels:

  • Preferred: open a GitHub Security Advisory. This gives a private workspace to coordinate a fix + disclosure. The repo's Private vulnerability reporting setting must be enabled on github.com for this URL to render the report form — verify the link returns a 200 (not a 404) before relying on it. The release runbook checks this.
  • Fallback: email security@opengraphdb.dev (or, until that alias is provisioned, the maintainer at ashesh.goplani96@gmail.com) with the subject prefix [opengraphdb-security]. The fallback address goes to one human's inbox, so response time may be longer than the GHSA path; if you have a critical or actively-exploited issue, please use both channels.

What to Include

  • A description of the vulnerability + the impact.
  • Steps to reproduce (a minimal .cypher query, sample input, or test case).
  • The OpenGraphDB version (ogdb --version) and platform.
  • Whether you believe the issue is exploitable remotely or requires local access.

What to Expect

  • Acknowledgement within 72 hours.
  • Triage within 7 days — we will tell you whether we accept the report and the severity we assign.
  • Fix timeline depends on severity:
    • Critical (remote code exec, data corruption): patch within 14 days.
    • High (auth bypass, integrity loss): patch within 30 days.
    • Medium / Low: patch in the next minor release.
  • Disclosure: coordinated. We will credit you in the release notes unless you prefer to remain anonymous.

Supported Versions

We patch security issues in the latest minor release only. Users on older versions should upgrade.

Version Supported
0.6.x
< 0.6.0

Out of Scope

  • Vulnerabilities in dependencies that have already been patched upstream and where we are tracking the upgrade.
  • Issues that require physical access to the server.
  • Self-XSS in user-supplied query results that the user themselves rendered with dangerouslySetInnerHTML after copying out of the playground.

Secure Deployment

OpenGraphDB ships as an embedded, single-process database (the SQLite model): by default the trust boundary is "whoever can reach the loopback socket / open the file," i.e. the OS user. For that use case the defaults are safe. The guidance below is for the networked / shared / multi-user deployment, where you must turn auth on and put the process behind TLS.

1. Bind to loopback (default) and front it with a TLS-terminating proxy

There is no in-process TLS today (see the roadmap note below). HTTP, Bolt, and gRPC are cleartext sockets. The supported way to get transport encryption is to bind the server to 127.0.0.1 (the default for every protocol) and terminate TLS at a reverse proxy on the same host.

  • All protocols default to 127.0.0.1. Exposing a server on all interfaces is an explicit opt-in (--bind 0.0.0.0:<port>), and OpenGraphDB prints a loud warning when you do, because that puts a cleartext, potentially unauthenticated graph DB on the LAN.
  • Keep ogdb on loopback and let the proxy be the only thing listening externally.

nginx (/etc/nginx/conf.d/ogdb.conf):

server {
    listen 443 ssl;
    server_name ogdb.example.com;

    ssl_certificate     /etc/letsencrypt/live/ogdb.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/ogdb.example.com/privkey.pem;
    ssl_protocols       TLSv1.2 TLSv1.3;

    location / {
        proxy_pass         http://127.0.0.1:8080;   # ogdb serve --http (loopback)
        proxy_set_header   Host              $host;
        proxy_set_header   X-Forwarded-For   $proxy_add_x_forwarded_for;
        proxy_set_header   X-Forwarded-Proto $scheme;
        # SSE: /query/trace streams — disable response buffering so events flush.
        proxy_buffering    off;
        proxy_read_timeout 1h;
    }
}

Caddy (Caddyfile) — automatic Let's Encrypt certificates:

ogdb.example.com {
    reverse_proxy 127.0.0.1:8080 {
        flush_interval -1   # stream Server-Sent Events (/query/trace) without buffering
    }
}

Traefik (dynamic config, file provider) — automatic ACME certs configured in your static config (certificatesResolvers.le):

# /etc/traefik/dynamic/ogdb.yml
http:
  routers:
    ogdb:
      rule: "Host(`ogdb.example.com`)"
      entryPoints: [websecure]
      service: ogdb
      tls:
        certResolver: le
  services:
    ogdb:
      loadBalancer:
        # Traefik streams SSE (/query/trace) without buffering by default.
        servers:
          - url: "http://127.0.0.1:8080"   # ogdb serve --http (loopback)

Start the backend on loopback:

ogdb serve --http --bind 127.0.0.1:8080 --require-auth /path/to/graph.ogdb

Bolt over TLS (bolt+s://): terminate with an L4 TLS proxy (nginx stream {}, HAProxy, or stunnel) in front of ogdb serve --bolt --bind 127.0.0.1:7687. The Bolt wire protocol is not HTTP, so use a TCP/stream proxy, not an HTTP location block.

2. Turn authentication on (RBAC bootstrap + fail-closed)

The token + role engine is dormant until the first user exists. Bootstrap it, then serve fail-closed:

# Create the first user with a bearer token and an admin role.
ogdb user add admin --token "$(openssl rand -hex 32)" --role admin --db /path/to/graph.ogdb
ogdb user list --db /path/to/graph.ogdb            # never prints token values

# Serve fail-closed: every data route (reads + writes) needs a valid bearer, and the
# server refuses to start until a user exists. Also honored via OGDB_REQUIRE_AUTH=1.
ogdb serve --http --bind 127.0.0.1:8080 --require-auth /path/to/graph.ogdb
  • --require-auth (env OGDB_REQUIRE_AUTH=1): fail closed. Anonymous requests get 401; /health stays open for liveness probes.
  • --require-auth-reads (env OGDB_REQUIRE_AUTH_READS=1): keep writes/exports gated as usual but also require a bearer for reads (/query, /schema, /metrics) once users exist. Use this when you want the open browser playground gone but don't need the full fail-closed posture.
  • Clients authenticate with Authorization: Bearer <token>.

Roles: admin, read_write, read_only (default for a new user). Grant/revoke with ogdb user grant <name> <role> / ogdb user revoke <name> <role>.

Roadmap: native in-process TLS

In-process TLS (rustls) is not implemented and is intentionally deferred. The HTTP, Bolt, and MCP servers each manage raw TcpStreams with hand-rolled framing (including an SSE streaming path), so adding TLS cleanly means threading a rustls config, PEM cert loading/reload UX, SNI/ALPN, and handshake-error handling through three transports plus a new test surface — a cross-cutting feature, not a small patch. Terminating TLS at a reverse proxy (above) gives the same transport security today with zero code risk, so that is the supported path. Native TLS will be revisited when there is a concrete requirement a proxy cannot satisfy.

There aren't any published security advisories