Repository navigation
Releases: sabahattink/codediag
Release list
v0.13.0 - Scope
The "Scope" release: Elysia analysis. In Elysia, a hook is local to the plugin that registers it unless it says { as: 'scoped' } or { as: 'global' }, and it applies only to routes registered after it. An auth plugin that forgets the scope, or a route registered one line too early, leaves a route open while the code looks protected. CodeDiag now models both.
npx @sabahattink/codediag scan .Highlights
- Routes followed through plugins. Routes on
new Elysia()instances are traced throughprefix,group(),guard(), anduse()across files, functional plugins and tsconfig path aliases included, and replayed in registration order. - Auth where Elysia runs it.
onBeforeHandle(), aderive()orresolve()that rejects with 401 or 403,guard(), auth macros such as better-auth's{ auth: true },onRequest(), or a check in the handler. Aderive()that only addsuserto the context does not count. - The hook that did not reach. When an auth hook exists but stays local to its plugin, or comes after the route, the finding names the hook and its line.
- Body validation from TypeBox, Zod, or any Standard Schema in the route options or a
guard(), only for handlers that actually read the body. - "Routes not analyzed." On a Koa, Hapi, Nuxt, Astro, or other server CodeDiag has no analyzer for, the report says so instead of showing no route findings.
Checked against db-studio, ConvertX, ohmyblog, and two Elysia starters. Suggested by a reader on Indie Hackers. See the changelog.
v0.12.0 - Rows
The "Rows" release. In a Supabase app the browser holds the anon key and queries the database directly, so row level security, not your API routes, decides who can read and write a table. CodeDiag now checks it in your migrations.
npx @sabahattink/codediag scan .Highlights
- Tables without RLS are critical. CodeDiag replays
supabase/migrationsin order: renames, schema moves, drops,disable row level security, andrevoke allfrom anon and authenticated. Any table that ends up in an exposed schema without RLS is reported at itscreate tableline. Exposed schemas arepublicby default, or the ones insupabase/config.toml. - Policies open to every row. CodeDiag flags
update,delete, orallpolicies whoseusingistrue, and anoninsertpolicies whosewith checkistrue. Public read policies are left alone. - SQL-aware. Comments, strings, and function bodies never count. A table that is public on purpose can be suppressed with a
-- codediag-ignore-next-linecomment and a reason. - What a clean scan does not mean is now spelled out in the README: object-level authorization, policy conditions, Server Actions, and more.
Checked against vercel/nextjs-subscription-payments, Basejump, and chatgpt-your-files. Suggested by a reader on Indie Hackers. See the changelog.
v0.11.2 - Signed webhooks
A false-positive fix from launch feedback.
- Signed webhooks count as authenticated in Next.js, Express, Fastify, Hono, and NestJS. SvelteKit and React Router already counted them. A webhook has no session by design; it proves the sender with a signature. Those routes were reported as missing auth. CodeDiag now recognizes:
- Stripe
constructEvent(); - Svix
verify(); - an HMAC compared with
timingSafeEqual(); - helpers or middleware such as
verifyGithubSignatureorverifySlackSignature, including in a named handler function.
- Stripe
Thanks to the Indie Hackers reader who reported it. See the changelog.
v0.11.1 - Plugin fix
A fix for the Claude Code plugin.
- The plugin's MCP server now starts
@sabahattink/codediag@latest. With a bare package name,npxused a copy already installed in the project. Inside the CodeDiag repository that copy can't run, so the server didn't start. In a project with an older devDependency, it would run a version that has nomcpcommand.
If you installed the plugin on 0.11.0, update it from /plugin and the server will connect.
See the changelog.
v0.11.0 - Agents
The "Agents" release: your coding agent can now ask CodeDiag which API routes anyone can call, through an MCP server, an Agent Skill, or a Claude Code plugin.
/plugin install codediag --marketplace sabahattink/codediag
Highlights
-
MCP server —
codediag mcp: three read-only tools for any MCP client.find_unprotected_routes: routes, form actions, and procedures with no recognizable auth check or input validation. Always offline.scan_project: the 0–100 score and findings, most severe first. The dependency audit runs only when you ask for it.explain_rule: what a rule detects and how to suppress it.
Results are structured and schema-checked. The server adds no runtime dependencies, and a test runs it against the official MCP SDK client.
-
Claude Code plugin: one install adds the server and a skill.
-
Agent Skill:
npx skills add sabahattink/codediag. It tells any agent where each framework runs auth, and to check a finding before calling a route vulnerable. -
MCP Registry: listed as
io.github.sabahattink/codediag.
Setup for Claude Code, Cursor, VS Code, and Claude Desktop is in the AI agents guide. The changelog has the details.
v0.10.0 - Reach
The "Reach" release: SvelteKit and React Router/Remix get API Health analysis, Next.js middleware is judged for each route the way it runs, tRPC perimeters cover Hono, Fastify, and Auth.js, pnpm workspaces stop reporting each other's vulnerabilities, and password and secret checks stop flagging ordinary sign-up code.
npx @sabahattink/codediag@0.10.0 scan .Highlights
- SvelteKit:
+serverendpoints and form actions, with auth in thehandlehook or the handler. CodeDiag says so when the only auth check sits in a layoutload, which never runs for actions. It also flags missing body validation and disabled CSRF origin checks. - React Router and Remix: actions and loaders from
app/routes.tsor flat-route files, with routemiddlewareas a perimeter. A separate rule covers auth that only lives in a parent's or the route's own loader, since neither runs before an action. - Next.js middleware, run per route: a guard for
/dashboardno longer protects/api, andclerkMiddleware()alone no longer counts as auth. Auth.jsauthorizedcallbacks and Supabase'supdateSession()are understood. - tRPC perimeters: auth before Hono's
trpcServer(), auth hooks over Fastify's tRPC plugin, and Auth.js v5 middleware. - One pnpm audit per workspace: each package reports only the advisories its own dependencies reach.
- Fewer false positives: sign-up validation, error messages, test fixtures, Pwned Passwords lookups, and
MOCK_placeholders are no longer critical findings. On the Remix indie-stack, Security goes from 3 to 78; on the Epic Stack, from 0 to 72. - VS Code 0.8.0 runs the new engine.
This release also ships 0.9 "Perimeter", which was not published on its own:
- tRPC auth in
createContext, Express mounts, and Next.js middleware; - dependency audits cached for an hour and run concurrently across workspace packages;
- Dependabot updates that rebuild the Action bundle.
See the changelog for details.
v0.8.0 - Depth
The "Depth" release: tRPC procedures, request data followed through fields, constructors, callbacks, and injected providers, fastify-cli projects as @fastify/autoload loads them, secrets that Git history still holds, gates that a good average cannot hide, and fixes you apply from the editor.
npx @sabahattink/codediag@0.8.0 scan .Highlights
- tRPC: procedures are followed from
initTRPCthrough.use()chains, exported builders such asprotectedProcedure, and nested or merged routers across files. New warnings:missing-trpc-auth-middleware,unvalidated-trpc-input,trpc-stack-trace-exposed. The checks run inside whichever server hosts tRPC, so T3 App Router projects get a real API Health score. Procedureinputcounts as request data for the security rules, even after.input(schema). - Deeper taint: request data is followed into fields a class stores it in, through constructors, into
map/forEach/reduce/thencallbacks andfor...of, and to NestJS providers behind an interface or@Inject()token. Findings stay on the sink line with unchanged fingerprints. - Fastify autoload:
fastify-cliprojects get directory prefixes,autoPrefix, and autohooks the way@fastify/autoloadapplies them, instead of false missing-auth warnings. - Secrets in Git history (opt-in):
--secret-historyreports credentials that a commit added and a later one deleted. Secrets are compared by digest and never printed. - Gates:
--fail-on criticalfails on any active critical finding whatever the score;--package-threshold 70gates every monorepo package on its own score. Both work in the GitHub Action (fail-on,package-threshold). - VS Code 0.6.0: remediation quick fixes for disabled TLS verification, ignored JWT expiration, and the JWT
nonealgorithm.
Fixes
- NestJS
@Param()/@Query()/@Body()/@Headers()parameters now make shell command and SQL findings critical; parameters behind a parsing pipe (ParseIntPipe, ...) are not request data. - Action annotation messages no longer show commas and colons as
%2Cand%3A. - The JSON schema accepts combined workspace reports with Hono packages.
See the changelog for details and known limitations.
v0.7.0 — Across
Across: CodeDiag follows request data through your own helper functions and services, scans whole monorepos as one report, analyzes Hono apps, tracks your score over time, and measures pull requests against the base branch.
npx @sabahattink/codediag@0.7.0 scan . --workspaces --history .codediag/historyCross-file taint
Request data passed into project helpers and services is followed up to two calls deep:
// src/lib/convert.ts
export function convert(file: string) { exec(`convert ${file}`); } // ← critical now
// src/routes/upload.ts
router.post("/convert", auth, (req, res) => convert(req.body.file));- All import styles, class methods, and NestJS
this.service.method(dto.x)are followed. - Pass-through helpers such as
getName(req)carry request data back to the caller. - Findings stay on the sink line with unchanged messages and fingerprints, marked
confidence: "medium". The fix text names the calling line. - On every existing fixture the findings are the same as before, and CodeDiag's own scan got faster.
Monorepos
--workspaces scans every package of an npm, pnpm, or Yarn workspace, a Lerna repository, or an Nx workspace:
- Each package gets its own stack detection and its own config.
- The combined report lists every package and averages each analyzer over the packages it ran in.
- Baselines,
--compare,--changed-since, and SARIF work across the whole repository. - The GitHub Action (
workspaces: true) and the VS Code extension support it too.
Hono
The new API Health analyzer reads Hono apps:
- routes,
basePath(), and sub-apps mounted withapp.route()across files, replayed in Hono's registration order jwt(),bearerAuth(), and custom auth middlewarezValidatorbody validationonErrorand health endpoints
There are four new rules (80 → 84). Hono servers are also checked for secure headers, rate limiting, and open hono/cors.
Score history
--history <dir> records every scan. The terminal shows a sparkline. The HTML report shows a line chart with grade guides, keyboard-reachable readouts, and a table view.
Base-branch delta in pull requests
Give the Action your base branch's report with compare: codediag-main.json. The comment then reads ▼ −3 vs. the base branch (81) · 1 new · 2 fixed, and new findings are marked.
Also
- Vulnerability findings name the affected packages and their advisories.
audit: productionskips devDependencies.--format promptgroups findings by rule and includes the rule documentation.- VS Code extension 0.5.0 (attached).
Full changelog: https://github.com/sabahattink/codediag/blob/main/CHANGELOG.md
v0.6.0 — Deep Scan
Deep Scan: CodeDiag now covers Fastify, finds JWT and session misconfiguration, template injection, prototype pollution, and secrets outside source code. It can compare two scans or limit a scan to the files a branch changes.
npx @sabahattink/codediag@0.6.0 scan . --compare previous.json
npx @sabahattink/codediag@0.6.0 scan . --changed-since origin/mainFastify
The API Health analyzer now reads Fastify apps:
- routes from
fastify.get()andfastify.route(), including routes insideregister()-ed plugins andfastify-pluginplugins onRequest,preParsing,preValidation, andpreHandlerauth hooks on the route or its encapsulation context- body schemas on mutating routes
setErrorHandler- health endpoints
There are four new rules: no-fastify-routes, missing-auth-hook, missing-route-schema, and missing-error-handler.
New security rules
jwt-none-algorithm(critical):algorithms: ['none'],algorithm: 'none', or jose'sUnsecuredJWTjwt-expiration-ignored:ignoreExpiration: trueinsecure-cookie: session and token cookies withouthttpOnlyandsecure, and session middleware that turns either flag offserver-side-template-injection(critical): request data compiled as an EJS, Pug, Handlebars, Nunjucks, Eta, doT, or lodash templateprototype-pollution:target[a][b] = valuewith keys from request data (critical), and recursive merges without a__proto__guard (warning)dynamic-command-executionnow also coversspawn()andexecFile()withshell: true
Secrets beyond source code
hardcoded-secret now scans these files for provider tokens and for long, high-entropy values of secret-like keys:
- JSON, YAML, TOML, INI, XML, and properties files
- Dockerfiles
.npmrcand.yarnrc
The new committed-env-secret rule reports secrets in .env files that Git tracks. Ignored .env files are never read, and no report includes a secret's value.
Compare scans, or scan only what changed
--compare <report.json>shows score and per-analyzer deltas since an earlier JSON report, plus new findings (NEW,isNew) and fixed findings. It works in every output format; SARIF results getbaselineState.--changed-since <revision>reports and scores only the findings in files changed since a Git revision. That includes commits since the merge base, staged and unstaged edits, and untracked files.
Redesigned HTML report and project page
The HTML report adds:
- a score gauge
- analyzer weights and deltas
- a change panel and a scope banner
- search and a "New" filter
- rule links and print styles
It still loads nothing from the network.
The project page was redesigned as well.
VS Code extension 0.4.0
Quick fixes on each problem suppress the rule on that line or in that file (you type the reason), or open the rule's documentation. The .vsix is attached to this release.
Known limitations
- Fastify plugins loaded with
@fastify/autoloadare not followed yet. - Fastify auth and validation are recognized by naming, as with Express.
Rules: 70 → 80 · Full changelog: https://github.com/sabahattink/codediag/blob/main/CHANGELOG.md
v0.5.0 — Pull Request Comments
Pull request comments: CodeDiag now keeps one comment on each pull request with the score and the findings in the files that pull request changes.
permissions:
contents: read
pull-requests: write
jobs:
codediag:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: sabahattink/codediag@v0
with:
threshold: 80
comment: trueWhat the comment shows
- ✅ or ❌: the score and grade against your threshold.
- The change since the previous push, such as
▲ +3 since the last run. - The analyzer table.
- Findings in the files this pull request adds or modifies. Critical findings come first, and each rule links to its documentation.
- A count of findings elsewhere in the project, plus suppressed and baseline findings.
Every push updates the same comment, so the pull request never collects duplicates.
Safe by default
commentis off unless you set it totrue.- Runs outside a pull request skip the comment.
- If the comment can't be written (for example, a fork's read-only token), the Action logs a warning. The scan result, outputs, and threshold gate work as before.
- No new dependencies. The comment uses the workflow's
GITHUB_TOKENthrough the REST API.
See the GitHub Action guide.
Full changelog: https://github.com/sabahattink/codediag/blob/main/CHANGELOG.md