foxguard 0.12.0

A security scanner as fast as a linter, written in Rust. 200+ built-in rules across 12 source languages.
Documentation
---
import Base from '../layouts/Base.astro';
import SiteNav from '../components/ui/SiteNav.astro';
import Footer from '../components/sections/Footer.astro';
import {
  matrixTools,
  matrixRows,
  coreRows,
  performanceFeatures,
  uniqueFeatures,
  pricingRows,
  type ToolKey,
  type Cell,
  type MatrixRow,
} from '../data/compare';

const multiTables: { num: string; title: string; rows: MatrixRow[]; minW: string; footnote?: string }[] = [
  {
    num: '01',
    title: 'Capability matrix',
    rows: matrixRows,
    minW: 'min-w-[820px]',
    footnote:
      '✓ out of the box · — not available · text = caveat (paid tier / partial / different mechanism). Check each vendor for current details.',
  },
  {
    num: '02',
    title: 'Core attributes',
    rows: coreRows,
    minW: 'min-w-[860px]',
  },
];
---

<Base
  title="foxguard vs Semgrep, OpenGrep, CodeQL, Snyk Code & SonarQube"
  description="foxguard vs Semgrep, OpenGrep, CodeQL, Snyk Code, and SonarQube on speed, taint analysis, post-quantum auditing, and price."
>
  <div class="sticky top-0 z-40 bg-noir-950 border-b border-noir-800">
    <div class="max-w-5xl mx-auto px-6">
      <SiteNav backLabel="compare" />
    </div>
  </div>

  <main class="pt-8 pb-24">
    <div class="max-w-5xl mx-auto px-6">

      <header class="mb-12 max-w-3xl">
        <h1 class="font-heading text-3xl sm:text-4xl text-noir-50 tracking-tight mb-3">How foxguard compares</h1>
        <p class="text-noir-500 text-base leading-relaxed">
          How foxguard compares with Semgrep, OpenGrep, CodeQL, Snyk Code, and SonarQube on speed,
          taint analysis, post-quantum readiness, and price. Figures come from each vendor's docs.
        </p>
      </header>

      {/* 01 Capability matrix + 02 Core attributes share the multi-tool table layout */}
      {multiTables.map((tbl) => (
        <section class="mb-16">
          <h2 class="font-heading text-noir-50 text-xl sm:text-2xl mb-6 flex items-center gap-2">
            <span class="text-fox-light font-mono text-sm">{tbl.num}</span>
            {tbl.title}
          </h2>
          <div class="rounded-xl border border-noir-800 overflow-hidden">
            <div class="overflow-x-auto">
              <table class={`w-full text-left ${tbl.minW}`}>
                <thead>
                  <tr class="border-b border-noir-800 bg-noir-900/50">
                    <th class="px-4 py-2.5 text-xs font-medium text-noir-500 uppercase tracking-wider sticky left-0 bg-noir-900/50">
                      {tbl.title === 'Core attributes' ? 'Attribute' : 'Capability'}
                    </th>
                    {matrixTools.map((tool) => (
                      <th class={`px-4 py-2.5 text-xs font-medium uppercase tracking-wider ${tool.key === 'foxguard' ? 'text-fox-light' : 'text-noir-500'}`}>
                        <span class="block whitespace-nowrap">{tool.label}</span>
                        <span class="block text-[10px] font-normal normal-case tracking-normal text-noir-600 mt-0.5">{tool.tagline}</span>
                      </th>
                    ))}
                  </tr>
                </thead>
                <tbody>
                  {tbl.rows.map((row) => (
                    <tr class="border-b border-noir-800/40 last:border-b-0">
                      <td class="px-4 py-2.5 text-sm text-noir-300 align-top sticky left-0 bg-noir-950">
                        <span class="block whitespace-nowrap">{row.capability}</span>
                        {row.note && <span class="block text-[11px] text-noir-600 mt-0.5 whitespace-normal max-w-[260px]">{row.note}</span>}
                      </td>
                      {matrixTools.map((tool) => {
                        const val: Cell = row.cells[tool.key as ToolKey];
                        const isFox = tool.key === 'foxguard';
                        return (
                          <td class="px-4 py-2.5 text-sm align-top">
                            {val === 'yes' ? (
                              <span class="text-sage-light">&#10003;</span>
                            ) : val === 'no' ? (
                              <span class="text-noir-700">&mdash;</span>
                            ) : (
                              <span class={isFox ? 'text-noir-100 font-medium' : 'text-noir-400'}>{val}</span>
                            )}
                          </td>
                        );
                      })}
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>
          </div>
          {tbl.footnote && <p class="text-noir-600 text-xs mt-3">{tbl.footnote}</p>}
        </section>
      ))}

      {/* 03 Performance — the one head-to-head we actually measured */}
      <section class="mb-16">
        <h2 class="font-heading text-noir-50 text-xl sm:text-2xl mb-6 flex items-center gap-2">
          <span class="text-fox-light font-mono text-sm">03</span>
          Performance
        </h2>
        <div class="rounded-xl border border-noir-800 overflow-hidden">
          <div class="overflow-x-auto">
            <table class="w-full text-left min-w-[520px]">
              <thead>
                <tr class="border-b border-noir-800 bg-noir-900/50">
                  <th class="px-4 py-2.5 text-xs font-medium text-noir-500 uppercase tracking-wider">Metric</th>
                  <th class="px-4 py-2.5 text-xs font-medium text-fox-light uppercase tracking-wider">foxguard</th>
                  <th class="px-4 py-2.5 text-xs font-medium text-noir-500 uppercase tracking-wider">Semgrep</th>
                </tr>
              </thead>
              <tbody>
                {performanceFeatures.map((row) => (
                  <tr class="border-b border-noir-800/40 last:border-b-0">
                    <td class="px-4 py-2.5 text-sm text-noir-300">{row.feature}</td>
                    <td class="px-4 py-2.5 text-sm text-noir-100 font-medium">{row.foxguard}</td>
                    <td class="px-4 py-2.5 text-sm text-noir-400">{row.semgrep}</td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        </div>
        <p class="text-noir-600 text-xs mt-3">
          Same hardware and rulesets; reproduce with <code class="text-noir-500">./benchmarks/run.sh</code>.
          OpenGrep forks the Semgrep engine, so its numbers track Semgrep. CodeQL builds a database before it can query
          and SonarQube runs as a server. Both are heavier by design and are not sub-second local tools.
        </p>
      </section>

      {/* 04 Unique to foxguard */}
      <section class="mb-16">
        <h2 class="font-heading text-noir-50 text-xl sm:text-2xl mb-6 flex items-center gap-2">
          <span class="text-fox-light font-mono text-sm">04</span>
          Unique to foxguard
        </h2>
        <div class="rounded-xl border border-noir-800 bg-noir-900/30 p-6 sm:p-8">
          <p class="text-noir-500 text-sm mb-6">None of the other five ship these out of the box:</p>
          <ul class="grid sm:grid-cols-2 gap-x-8 gap-y-5 list-none pl-0">
            {uniqueFeatures.map((f) => (
              <li>
                <div class="flex items-baseline gap-2">
                  <span class="text-fox-light flex-shrink-0">&#10003;</span>
                  <span class="text-noir-100 text-sm font-medium">{f.feature}</span>
                </div>
                <p class="text-noir-500 text-xs leading-relaxed mt-1 pl-6">{f.note}</p>
              </li>
            ))}
          </ul>
        </div>
      </section>

      {/* 05 Pricing & licensing */}
      <section class="mb-16">
        <h2 class="font-heading text-noir-50 text-xl sm:text-2xl mb-6 flex items-center gap-2">
          <span class="text-fox-light font-mono text-sm">05</span>
          Pricing &amp; licensing
        </h2>
        <div class="rounded-xl border border-noir-800 overflow-hidden">
          <div class="overflow-x-auto">
            <table class="w-full text-left min-w-[680px]">
              <thead>
                <tr class="border-b border-noir-800 bg-noir-900/50">
                  <th class="px-4 py-2.5 text-xs font-medium text-noir-500 uppercase tracking-wider">Tool</th>
                  <th class="px-4 py-2.5 text-xs font-medium text-noir-500 uppercase tracking-wider">License</th>
                  <th class="px-4 py-2.5 text-xs font-medium text-noir-500 uppercase tracking-wider">Cost model</th>
                </tr>
              </thead>
              <tbody>
                {pricingRows.map((row) => {
                  const isFox = row.tool === 'foxguard';
                  return (
                    <tr class="border-b border-noir-800/40 last:border-b-0">
                      <td class={`px-4 py-2.5 text-sm align-top whitespace-nowrap ${isFox ? 'text-fox-light font-medium' : 'text-noir-300'}`}>{row.tool}</td>
                      <td class="px-4 py-2.5 text-sm text-noir-400 align-top">{row.license}</td>
                      <td class="px-4 py-2.5 text-sm align-top">
                        <span class={isFox ? 'text-noir-100 font-medium' : 'text-noir-400'}>{row.cost}</span>
                        <span class="block text-[11px] text-noir-600 mt-0.5 whitespace-normal">{row.note}</span>
                      </td>
                    </tr>
                  );
                })}
              </tbody>
            </table>
          </div>
        </div>
        <p class="text-noir-600 text-xs mt-3">
          Terms change; figures reflect each vendor's published model, not a quote.
        </p>
      </section>

      {/* Summary */}
      <section class="mb-16">
        <div class="rounded-xl border border-noir-800 bg-noir-900/30 p-8">
          <h2 class="font-heading text-noir-50 text-xl mb-4">When to pick foxguard</h2>
          <ul class="space-y-2 text-sm text-noir-400 leading-relaxed list-none pl-0">
            <li class="flex gap-3"><span class="text-fox-light flex-shrink-0">&#10003;</span>You want a fast, free scanner that runs without a login or token limits.</li>
            <li class="flex gap-3"><span class="text-fox-light flex-shrink-0">&#10003;</span>You need post-quantum crypto auditing (CNSA 2.0) or a CBOM.</li>
            <li class="flex gap-3"><span class="text-fox-light flex-shrink-0">&#10003;</span>You want a single static binary that runs without a runtime or database build.</li>
            <li class="flex gap-3"><span class="text-fox-light flex-shrink-0">&#10003;</span>You need cross-file taint for Python, JS, Go, Java, Ruby, PHP, C#, or Kotlin without a paid license.</li>
          </ul>

          <h2 class="font-heading text-noir-50 text-xl mt-8 mb-4">When another tool might fit better</h2>
          <ul class="space-y-2 text-sm text-noir-400 leading-relaxed list-none pl-0">
            <li class="flex gap-3"><span class="text-noir-500 flex-shrink-0">&#8594;</span><span><span class="text-noir-300">Semgrep / OpenGrep</span> for a native custom-rule DSL, or 30+ languages including Scala and Terraform.</span></li>
            <li class="flex gap-3"><span class="text-noir-500 flex-shrink-0">&#8594;</span><span><span class="text-noir-300">CodeQL</span> for GitHub Advanced Security with deep QL queries and in-platform code scanning.</span></li>
            <li class="flex gap-3"><span class="text-noir-500 flex-shrink-0">&#8594;</span><span><span class="text-noir-300">Snyk Code / SonarQube</span> for a managed SaaS or server with team dashboards, policy gates, and quality metrics.</span></li>
          </ul>
        </div>
      </section>

      {/* CTA */}
      <section class="text-center">
        <h2 class="font-heading text-noir-50 text-2xl sm:text-3xl mb-4">Try foxguard on your codebase</h2>
        <p class="text-noir-500 text-sm mb-6">Run one command to scan your code for free. No config or signup required.</p>
        <div class="inline-flex rounded-xl border border-noir-800 overflow-hidden">
          <code class="px-5 py-3 font-mono text-sm text-fox-light">npx foxguard .</code>
        </div>
        <div class="flex items-center justify-center gap-4 mt-6">
          <a href="/docs" class="text-sm text-noir-500 hover:text-noir-100 transition-colors no-underline">Read the docs &#8594;</a>
          <a href="/rules" class="text-sm text-noir-500 hover:text-noir-100 transition-colors no-underline">Browse all rules &#8594;</a>
        </div>
      </section>

    </div>
  </main>

  <Footer />
</Base>