src/Form/UserSearchForm.php · 2 minutes ago CRITICAL · SQL injection
Raw $keyword concatenated into db_query(). Bypasses Drupal's prepared-statement layer. Use a placeholder.
A Drupal-aware reviewer that runs inside your network. The core — CLI reviewer, fine-tuned model, Claude Code skill — is free and open-source. It knows #[Hook], cache contexts, DI, and render-array XSS. Pro adds auto-fix, IDE (MCP), and the PR bot — bought once, no subscription. Nothing leaves the building either way.
src/Form/UserSearchForm.php · 2 minutes ago CRITICAL · SQL injection
Raw $keyword concatenated into db_query(). Bypasses Drupal's prepared-statement layer. Use a placeholder.
src/Controller/UserController.php · 2 minutes ago MEDIUM · DI antipattern
Static \Drupal::service('entity_type.manager') inside controller. Inject via create() instead — keeps the controller testable.
Illustration of the Pro PR-bot — the findings shown are real catches from our public demo diff.
No screenshots, no mockups. Below is a hunk from our public 10-issue demo diff and the
finding the CLI returns for it — verbatim from a real run in --use-mock
mode, which exercises the deterministic detectors and shows the exact output shape with
no GPU and no model download. The full fine-tuned model (24 GB GPU)
caught 8–9 of the 10 seeded bugs on this diff, including the SQL injection and the
unserialize() RCE.
+ public function importConfig(Request $request) { + $payload = unserialize($request->query->get('data')); + $expected = $this->config('acme_demo.settings')->get('api_token'); + if ($request->query->get('token') == $expected) { + \Drupal::service('acme_demo.importer')->import($payload); + } + return ['#markup' => 'ok']; + }
{
"severity": "medium",
"category": "security",
"file": "web/modules/custom/acme_demo/src/Controller/DashboardController.php",
"line": 41,
"message": "Loose comparison (`==`/`!=`) on a security-sensitive value (token/secret/hash). PHP type-juggling can bypass the check and non-constant-time comparison leaks via timing.",
"suggestion": "Use strict comparison `===`; for secret/token/HMAC equality use hash_equals($known, $user_supplied) (constant-time).",
"cwe": "CWE-697",
"owasp_category": "A07:2021",
"confidence": 0.6,
"citation": "CWE-697: Incorrect Comparison (see also CWE-208 timing)"
}
The same --use-mock run returns 3 more findings on this diff:
a hardcoded sk_live_… Stripe key (CWE-798), an
entityQuery() without accessCheck() (CWE-285),
and removed-API drupal_set_message(). Point the CLI at a local
model (ollama pull, one command — it's free) and the LLM passes
take over: SQLi, XSS, cache-context leaks, DI violations, access-logic bugs.
Download the demo diff and score it yourself —
it seeds 10 labeled issues.
CodeRabbit / Greptile / Copilot are trained on a generic corpus. They don't know #[Hook], cache contexts, or Drupal's service container — so they either silently pass or hallucinate.
Senior devs spend 6–9 hrs/week reviewing routine MRs. By the time they get to yours, the context is gone and the comment is "LGTM, ship it."
Hook attributes, OOP plugins, deprecated drupal_get_path(). The lint rules catch some — but missing them in review costs a sprint of refactor later.
Missing #cache.contexts, raw entity loads in loops, render arrays that won't BigPipe. Generic tools don't flag any of these — your prod alerts do.
The MR webhook fires, the model reviews, GitLab gets a comment back. The whole pipeline runs on infrastructure you already own — no API calls leave your VPC.
Webhook on push or comment trigger.
GitLab CE 16+FastAPI extracts changed hunks + file context.
FastAPI · Python 3.12Pulls relevant core docs, contrib patterns, prior fixes.
QdrantOllama runs gemma4-12b-dcr-v7 on your hardware.
Ollama · gemma4-12b-dcr-v7Findings posted inline. Severity, file, line.
GitLab API v4Minutes, not days
A full deep review of a typical MR finishes in a few minutes on one RTX 4090 — we parallelized the pipeline 3.4× and measured it, findings bit-identical.
Drupal-RAG
Grounded in api.drupal.org docs, coding standards, and security advisories. Pro also indexes your own custom modules — so the model knows your hooks too.
Same review pipeline, same local model, reached three ways. The CLI is the free core; the IDE (MCP) and PR-bot doors are Pro.
Pipe a diff in, get JSON or markdown back. Wire it into a pre-push hook so nothing merges unreviewed.
An MCP server, so Cursor, Claude Code, and Windsurf call it natively. Ask your agent to review the diff; it answers with Drupal-aware findings.
Drop it in CI. On each merge request it posts inline findings — severity, file, line — before a human opens the tab.
It fixes, not just flags
For mechanical Drupal mistakes — static calls that should be injected, missing cache metadata, deprecated APIs, render-array XSS — it writes the corrected code as a one-click suggestion block. Every patch is checked against PHPCS before you see it.
The fix never leaves either
A cloud reviewer round-trips your code and the patch to a vendor to "fix it." Drureview generates and validates the fix inside your network. For agencies and regulated shops, that's the whole point.
Claude Code skill — free
Core ships a dcr-review skill. Add it to Claude Code, then just say "review this Drupal diff" — your agent answers with Drupal-aware findings from your local model. Nothing leaves the machine.
Drureview is a high-specificity second reviewer — Drupal-idiom-aware, tuned for low false alarms. Not a magic 100% bug catcher; an extra pair of Drupal-trained eyes that never sees your code leave the building. Here is what we actually measured.
On 58 inverted real-fix pairs, the fine-tuned model raised zero false alarms on the clean side. A second reviewer that doesn't cry wolf.
Caught two-thirds of reintroduced real defects on the same 58-pair set — balanced accuracy 0.828 vs 0.655 for the untuned base model.
Fine-tuning lifted verdict accuracy 83.3% → 95.8% on a held-out set (n=48), specificity to 100%, and dropped invalid-JSON outputs to zero.
| Tool | Self-host | Data leaves your network | Drupal-aware | Auto-fix on-prem | Billing |
|---|---|---|---|---|---|
| Drureview | Yes | Never | Native | Yes | One-time |
| CodeRabbit | No | Vendor cloud | Generic | Cloud only | $24/seat/mo |
| Greptile | Enterprise only | Tier-dependent | Generic | Cloud only | $30+/seat/mo |
| GitHub Copilot | No | Microsoft cloud | Generic | Cloud only | $19/seat/mo |
| PHPStan / Drupal rules | Yes | Never | Static-only | No | $0 |
A perpetual license — twelve months of updates included, then keep what you have for good. No seats, no monthly bill.
The local engine, open-source (Apache-2.0) on GitHub. Review Drupal diffs on your own machine, free — forever.
For an individual developer who wants the Pro layer locally.
Everything in Solo for the whole team, plus CI. First 50 at $190 with lifetime updates.
Org-wide perpetual license ($1,250), full install + RAG + CI wiring, or a ~2-hour Quickstart session from $390. The code is the cheap part — we sell getting it running on your hardware.
A free, public scanner: drop in a drupal.org / GitHub / GitLab merge request and get a shareable Drupal-aware review. Public URLs only — for your private code, you run Drureview locally.
What a shared scan result will look like — severity, file:line, suggestion, one link you can drop in a Slack thread. (Sample data until the scanner is live; real runs from public MRs will replace it.)
Grab the free core, or claim a founding Agency seat. Set up in an afternoon — or have us do it.