Skip to the content.

dograh-hq/dograh — security scan

Repository: dograh-hq/dograh — 2.5k★, BSD-2-Clause, an open-source voice-agent platform (Python API backend + Next.js UI). Commit scanned: 21951eca18cd (HEAD of main at scan time) Scan date: 2026-05-21 Disclosure status: Public courtesy issue filed on the dograh repo. Every finding traces to a published CVE or a best-practice pattern — no private coordination required.

Summary

Severity Count
Critical 0
High 41
Medium 28
Low 0
Info 0 (filtered)

69 total findings. After curation: one dominant real cluster (an outdated Next.js across two front-ends), three smaller best-practice items, and ~8 false positives.

dograh is a right-sized target: a focused two-component codebase (Python api/ + Next.js ui/, plus an evals/visualizer/ tool), and the scan tells a clean single-headline story rather than burying it. It’s also one of the most responsive repos in the series — issues closed within days, external PRs merged within 24 hours — which is exactly the kind of project where a courtesy issue is most likely to land.

Top findings (curated)

1. Outdated Next.js across ui/ and evals/visualizer/ — ~45 findings, one root cause

Tool: Trivy (high/medium confidence — named advisories) Verdict: Real — a single dependency upgrade clears the whole cluster.

The next package is pinned to a vulnerable version in three lockfiles (ui/package-lock.json, evals/visualizer/package-lock.json, evals/visualizer/pnpm-lock.yaml). Trivy surfaces the full advisory set against that version. The sub-classes, roughly in descending order of concern:

None of these is a dograh code bug — they are all the standard Next.js advisory backlog that accumulates when the framework pin drifts. The fix is a single next upgrade per front-end to the current patched release, then a re-lock. Given dograh ships the UI as a container image (dograhai/dograh-ui), the upgrade also needs an image rebuild to actually reach deployments.

2. evals/visualizer/ ships two lockfiles — package-lock.json and pnpm-lock.yaml

Verdict: Real hygiene issue — drift hazard.

The evals/visualizer/ directory carries both an npm lockfile and a pnpm lockfile. Whichever one a given developer’s (or CI’s) package manager honours, the other silently goes stale — and the scan confirms it: the Next.js advisories fire against both lockfiles, which means both are present and both are out of date. Pick one package manager for the sub-project, delete the other lockfile, and the dependency surface stops being ambiguous.

3. docker-compose.yaml:180OSS_JWT_SECRET defaults to ChangeMeInProduction

Verdict: Self-aware placeholder, but still a fail-open footgun.

OSS_JWT_SECRET: "${OSS_JWT_SECRET:-ChangeMeInProduction}"

The ${VAR:-default} shape means a deployment that never sets OSS_JWT_SECRET silently runs with the secret literally being the string ChangeMeInProduction — a value committed in a public repo. Anyone can then forge JWTs against that deployment. The naming shows the maintainer is aware of the risk, which is good — but a self-documenting placeholder is not the same as a guardrail. The robust pattern is to not provide a default and fail fast at startup:

# compose: require the var, no default
OSS_JWT_SECRET: "${OSS_JWT_SECRET:?OSS_JWT_SECRET must be set}"

${VAR:?message} makes docker compose up abort with the message if the variable is unset — the deployment fails loudly instead of silently running with a known-public signing key. Same class as the PraisonAI SurrealDB root/root finding, which was fixed by raising on missing credentials.

4. api/Dockerfile — missing USER, missing --no-install-recommends

Verdict: Minor best-practice.

The API container runs as root (no USER directive) and its apt-get install omits --no-install-recommends. The first is the standard container-hardening item flagged on several prior scans; the second is image-hygiene (smaller image, fewer packages, smaller attack surface). Both mechanical.

5-N. False positives

Finding Verdict
6× “secret detected” in docs/**/*.mdx FP — API-reference documentation showing example Authorization headers / token placeholders
POSTHOG_API_KEY / POSTHOG_KEY = phc_ItizB1dP6yv7ZYobbcqrpxTdbomDA8hJFSEmAMdYvIr FP — PostHog phc_ public project key, write-only event ingestion, designed to be shipped. Same FP class as openllmetry, PraisonAI, Giskard

Patterns observed

One headline, cleanly told. After Klavis’ 1,556-finding monorepo sprawl, dograh is the contrast case: a focused codebase where the scan produces a single actionable headline (upgrade Next.js) plus a short tail. This is what a “right-sized” target looks like — the curation isn’t a fight against volume, it’s a quick separation of one real cluster from a handful of best-practice items. The target-selection refinement that picked dograh — bias toward responsive, focused repos over sprawling ones — produced exactly the scan it was supposed to.

Front-end framework drift is its own dependency-hygiene category. Where guardrails’ finding was a Python dep (litellm) and Klavis’ was npm sprawl across 50 servers, dograh’s is a single framework — Next.js — whose advisory cadence is unusually high. Next.js ships security releases often; a pin that’s a few minor versions behind accumulates a long advisory list fast. The middleware-bypass sub-class in particular is worth treating as higher-priority than the DoS variants, because middleware is where authorization decisions commonly sit.

The ChangeMeInProduction default is a good intention one step short of a guardrail. It’s genuinely better than a silent random-looking default (the developer reading the compose file sees the warning). But ${VAR:-default} still fails open — an unset variable produces a running service with a public key. ${VAR:?message} fails closed. The one-character difference (:- vs :?) is the whole security property.

Notes on the tool

Disclosure timeline

Reproduce

git clone https://github.com/elfrost/ai-patchlab
cd ai-patchlab
pip install -e ".[dev]"
python scanner/run_scan.py \
  --from-git-url "https://github.com/dograh-hq/dograh" \
  --reports-dir reports/dograh-hq-dograh \
  --min-severity medium

External tools (Semgrep, Gitleaks, Trivy, pip-audit) need to be installed separately — see the project README.