Skip to content

tarinagarwal/Bugbash

Repository files navigation

LGTM

Looks Good To Meow — AI code review and CI/CD security, before bad code merges and before bad pipelines run.

LGTM has two product surfaces that share infrastructure:

  1. PR Review — open a PR, get an inline review from six specialist agents (security, bugs, performance, readability, best practices, documentation) plus a synthesized verdict, in about 30 seconds.
  2. LGTM Security — continuous CI/CD configuration scanning. Catches hardcoded secrets, the pull_request_target supply-chain RCE pattern, privileged containers, shell injection from PR titles, unpinned actions, and 12 more well-known classes of CI/CD risk. Three enforcement gates: inline PR comments, GitHub Check Runs that block the merge, and a runtime Action that halts CI jobs at step 1 before any other step runs.

Quick links

Repository layout

.
├── server/              Express API + BullMQ workers + agent orchestration
│   ├── src/agents/      6 review agents + ci-security agent + tree-sitter context
│   ├── src/security/    Pure-function rule library (16 detectors, no LLM)
│   ├── src/jobs/        review.job, context.job, security.job, security-cron
│   ├── src/models/      Mongoose schemas (User, Repo, Review, SecurityMonitor, …)
│   └── src/__tests__/   123 vitest tests, runs against in-memory Mongo
├── client/              React 19 + Vite + Tailwind v4 + custom claymorphism
│   └── src/pages/       Dashboard, Repos, Reviews, LgtmSecurity*, Settings, …
├── lgtm-cli/            `lgtm` CLI — login, repo, review (SSE-streamed), config
├── lgtm-action/         GitHub Action published as v1 — halts CI on block findings
├── security/            STEP-0 scope decisions doc
├── content/             Marketing content
├── theme/               Design tokens
└── HACKATHON.md         Story behind the build

What's actually inside

Server — Node 20 / TypeScript / Express. MongoDB (Atlas in prod, in-memory for tests) for everything durable. Redis for BullMQ queues + the runtime halt-decision cache. Three queues: context (tree-sitter parsing + dependency graphs + PageRank), review (the 6-agent review pipeline), security (CI/CD scans). Workers can run inline with the API or split into a separate process.

Rule libraryserver/src/security/rules/. Pure functions, no I/O, no LLM. The same library is consumed by both the PR-review path (agents/review/ci-security.ts) and the monitor worker (jobs/security.job.ts). 16 detectors covering hardcoded secrets, workflow YAML supply-chain patterns, Dockerfile misconfigurations, lockfile-only edits, and outbound-network risks.

Runtime watchdog Action — composite GitHub Action bundled with @vercel/ncc. Customers add it as the first step of their CI jobs. It calls GET /pipeline/decision?repo=...&sha=... against the LGTM API, and on halt: true calls core.setFailed so the job exits non-zero before any other step runs. Soft-fails on network errors so an LGTM outage never breaks customer CI.

Client — React 19 + Vite + Tailwind v4. Custom claymorphism design system; we built our own Button, Select, Modal, SearchInput primitives because native browser controls would've broken the visual coherence.

CLIlgtm commands: login, whoami, repo connect/list/index, config set-key, review (with SSE streaming so you see each agent finish in real time).

Feature surface

PR Review

  • 6 specialist agents run in parallel (security / bugs / performance / readability / best-practices / documentation), each with structured output schemas
  • A synthesizer agent combines them into one PR review with verdict (approve / request_changes / comment), confidence score, severity counts, top actions, and inline file/line comments
  • Auto-generated changelog entry per PR
  • Tree-sitter indexing across 12 languages (C, C++, C#, Go, Java, JavaScript, TypeScript, Kotlin, PHP, Python, Ruby, Rust)
  • BYO API key — OpenAI, Gemini, or Anthropic. Per-user, per-repo provider/model overrides
  • Real-time agent progress streamed to the dashboard and the CLI

LGTM Security

The 16 detectors:

Rule Severity Default action
secrets.hardcoded critical block
workflow.privileged-container critical block
workflow.untrusted-input-shell-injection critical block
workflow.pull-request-target-with-head-checkout critical block
workflow.self-hosted-runner-on-public-repo high block
workflow.unpinned-action-checkout high warn
workflow.unpinned-third-party-action high warn
workflow.permissions-write-all high warn
workflow.missing-job-permissions medium warn
workflow.trigger-weakening medium warn
workflow.external-reusable-workflow medium warn
dockerfile.privileged-flag high warn
dockerfile.user-root-final high warn
dockerfile.add-from-url medium warn
deps.lockfile-hash-mismatch high warn
network.unallowlisted-outbound medium warn

Each rule's action is tunable per-repo (block / warn / off). Allowlists for trusted action sources, internal mirror domains, and runner labels suppress findings on patterns the customer has explicitly approved.

Three enforcement gates:

  1. Inline PR review — when a PR touches CI/CD config, ci-security findings appear in the same review as the regular code-review comments
  2. Merge block via Check Run — block-action findings post a failed GitHub Check Run; branch protection respects it
  3. Runtime halt via Action — the lgtm-action/ watchdog runs as the first step of customer CI jobs and exits non-zero on block findings, before checkout, before tests, before deploys

Everything is recorded in an immutable SecurityAuditLog. The audit-log fields are immutable at the schema level (Mongoose pre("save") and pre("updateOne") hooks reject mutations); resolution fields (resolvedAt, resolution, resolvedBy) stay mutable so users can mark fixed / muted / false-positive.

Per-rule false-positive rates surface in the policy editor — surfaced after the user has resolved at least 5 findings on that rule, so we don't show a misleading "0%" before there's data.

Quickstart (local)

You'll need: Node 20+, Docker (for Redis), MongoDB Atlas (or any Mongo URI), Cloudflare Tunnel or ngrok (so GitHub webhooks can reach you).

# 1. Redis in Docker
docker run -d --restart unless-stopped --name lgtm-redis -p 6380:6379 redis:7-alpine

# 2. Server
cd server
cp .env.example .env   # fill in MONGODB_URI, JWT_SECRET, GITHUB_APP_*, REDIS_URL, OPENAI/GEMINI key
npm install --legacy-peer-deps
npm run dev            # starts API + workers on :3000

# 3. Client
cd ../client
npm install
npm run dev            # vite on :5173

# 4. Cloudflare tunnel for GitHub webhooks
cloudflared tunnel --url http://localhost:3000
# → copy the https://*.trycloudflare.com URL into your GitHub App's Webhook URL
# → also into server/.env as WEBHOOK_BASE_URL

# 5. CLI (optional)
cd ../lgtm-cli
npm install
npm run build
LGTM_API_URL=http://localhost:3000 node bin/lgtm.js login

For a real demo: install the tarin-lgtm GitHub App on a test repo, log into the dashboard, click Repos → Connect, then Security → Enroll that repo. The enrollment fires an immediate backfill scan against the default branch.

Tests

cd server
npm run test           # 123 vitest tests across 13 files

Test breakdown:

  • security.rules.test.ts — 27 unit tests, one good + one bad case per rule
  • ci-security.agent.test.ts — agent wrapper smoke tests
  • security.api.test.ts — enrollment + audit log + filter API
  • security.worker.test.ts — monitor worker e2e with mocked GitHub
  • security.worker.alerts.test.ts — alert wiring (in-app + email + dedup)
  • security.ruleStats.test.ts — per-rule false-positive aggregation
  • pipeline.api.test.ts + apiToken.api.test.ts — runtime halt endpoint + token auth
  • email.service.test.ts — nodemailer transport, escape XSS, soft-fail
  • health.api.test.ts + healthScore.*.test.ts — repo health score signals

Tests use mongodb-memory-server so they run without external Mongo. GitHub fetches and email sends are vi.mock'd.

Stack at a glance

Layer Choice
Server runtime Node 20, TypeScript, Express, ts-node-dev for HMR
Persistence MongoDB (Mongoose), Redis (ioredis + BullMQ)
AI providers OpenAI, Google Gemini, Anthropic — pluggable per user
Code parsing tree-sitter — 12 language grammars + per-language tag queries
Email nodemailer (SMTP)
Errors Sentry (server + client)
Billing Dodo Payments (Pro tier)
Frontend React 19, Vite, Tailwind v4, custom claymorphism
Tests Vitest 3, mongodb-memory-server, supertest
GitHub Action Composite action + bundled JS (@vercel/ncc), Node 20 runtime

Architecture in one paragraph

A push to a connected repo's default branch fires a push webhook, which enqueues a context-index job (tree-sitter parses the diff + updates the call graph) and, if the push touched CI files and the repo is enrolled in Security, a security scan job. A PR open/sync fires a pull_request webhook, which enqueues a review job that runs all six specialist agents plus the ci-security agent in parallel, runs the synthesizer, posts the GitHub PR review, and writes findings to the immutable audit log. Both review and monitor scans cache a halt decision in Redis at pipeline:decision:{repoId}:{sha} with 24h TTL — that's the cache the runtime watchdog Action reads to decide whether to halt CI. Socket.IO pushes scan progress to the dashboard so users see banners and posture refresh in real time without polling.

License

UNLICENSED for now. Public source for hackathon visibility; we'll pick a real license before any production deploy.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors