
Security News
Happy Birthday, Shai-Hulud
It has been one year since Shai-Hulud made its first appearance on npm.
Pre-production checklists for solo founders — 4,337 items, 88% portable to any stack, 26 stack supplements. CLI + MCP server.
Checklists to run before you ship to production.
Built for solo founders and small teams who own the whole stack — the code, the infrastructure, the deploy pipeline, and increasingly the AI agents too — and who don't have a security team to hand it to.
4,337 items across 96 checklists in 5 domains. 88% of them apply to any stack.
Built and maintained by the team at Arioo — where we ship the kind of product this checklist was written for.
I'm a founder at Arioo. Getting ready to launch, I needed a pre-production security review that covered the whole surface we actually ship: a TypeScript backend, a web app, native clients, a deploy pipeline, and a set of AI agents with real tools attached. Nothing I could find covered more than a fraction of that, so I built the checklist myself.
This repository is the checklist, not a report. It is the set of questions, generalized away from our stack and rewritten as a working document anyone can run against their own product.
Two things made it worth publishing rather than keeping:
Solo founders have no security team. You write the code, configure the infrastructure, set up the pipeline, and then you're also the one who has to decide whether it's safe to launch. There's no one to hand it to, and no obvious place to find out what you should have asked. Most public checklists are either too shallow to catch anything real or written for enterprises with a security function.
AI-assisted development changed the shape of the problem. A large part of this
checklist — the ai/ and vibe-coding/ folders, over 1,300 items — didn't need to exist
a few years ago. When you ship an agent with tools, or when a model writes code you review
faster than you'd review a colleague's, you inherit failure modes that standard security
checklists don't cover. Those two folders are the part I couldn't find anywhere else, and
the reason I bothered.
It's published under CC BY 4.0 so you can copy it into your own repo and make it yours. If it catches something before it reaches your users, it did its job.
You are not meant to read this top to bottom. In order of signal-per-minute:
| 1 | Findings that should block release | If any are true, stop and fix them first |
| 2 | The "must not exist" search | A grep list. Fastest real signal in the repo |
| 3 | Authentication & authorization | Where almost every exploitable bug actually lives |
| 4 | Prompt injection | Only if you ship an LLM feature — but then, urgently |
| 5 | Your service as a weapon | The one nobody looks for until the suspension email arrives |
| 6 | Core Web Vitals | If users say it's slow, start here rather than with a score |
| 7 | Before you launch | Six items. One of them is noindex still being on |
| 8 | Can you act at all | Whether you could respond today, if you had to |
Then work section by section. Switching between edge config and database policies costs more than it saves.
checklists/
├── security/ 2,812 not getting breached, abused or taken down
│ ├── core/ 1,491 application, data, infrastructure, delivery
│ ├── ai/ 773 LLM features, agents, tools, RAG, MCP
│ └── ai-generated-code/ 548 the bugs AI coding assistants actually write
├── performance/ 313 Lighthouse, and what users actually feel
├── scale/ 286 surviving 10× the load
├── integrations/ 192 search, analytics, monitoring
├── post-launch/ 192 when it goes wrong anyway
└── stacks/ 542 26 products, spanning every domain
Counts above are what each folder holds. A domain total is larger, because the stack supplements contribute to whichever domain each of their sections extends:
security 3,306 performance 338 scale 301 integrations 200 post-launch 192 post-launch 192
Domains are the top level because that is the question you arrive with: is this about security, or speed, or scale?
security/core/ — applies to you regardless of languageWritten originally against a TypeScript stack, but the controls are not
TypeScript-specific and the files no longer pretend otherwise. "Verify CORS does not use
wildcard origins with credentials" is as true in Django as in Express. Everything that
genuinely named a product was moved out to stacks/.
If you write Python, Go, Ruby, PHP, Java, Rust or Elixir: this folder is your checklist, all 1,491 items of it.
security/ai/ — the part you won't find in a standard checklistIf your product calls a model, gives it tools, retrieves documents into its context, or runs an agent, this folder is the reason this repo exists. It is stack-agnostic and provider-agnostic.
Prompt injection is not a filtering problem. It is an authorization problem wearing a text costume — untrusted text reaching a privileged execution path.
security/ai-generated-code/ — bugs AI assistants writeAlso known as vibe coding. 548 items organized by class of bug, not by which assistant produced it. Written from real review findings on AI-generated code. Browse →
performance/ — Lighthouse, and what users actually feelAimed at the highest achievable score across all four Lighthouse categories, with one constraint that decides what goes in: an item has to be about something a real user experiences. Lighthouse is the scoreboard, not the goal — anything whose only justification is "raises the score" was left out.
| Items | Items | |||
|---|---|---|---|---|
| Measurement | 29 | CSS & rendering | 28 | |
| Core Web Vitals | 41 | Backend & delivery | 40 | |
| Loading & critical path | 37 | Accessibility | 41 | |
| JavaScript | 43 | Release gate | 21 | |
| Images & media | 33 |
Lighthouse is a lab tool: one run, one simulated device, one network. It is excellent for finding problems and unreliable for proving them fixed. Field data at the 75th percentile is the scoreboard that matters.
Accessibility sits here because it is scored alongside performance, and because the overlap is real — a page that is fast for a screen reader is usually a page with less unnecessary markup and JavaScript. The Lighthouse accessibility category is treated as a floor, not a ceiling; it catches roughly a third of real issues.
integrations/ — being findable, measured and watchedEverything a project has to be connected to before launch. Configuration you do once and then never think about, which is exactly why it deserves a checklist.
| Items | Items | |||
|---|---|---|---|---|
| Search engines | 38 | Answer engines & AI crawlers | 25 | |
| SEO fundamentals | 42 | Analytics & consent | 28 | |
| Structured data & social previews | 27 | Monitoring & alerting | 32 |
Verify
noindexis removed from production. A staging robots meta tag that shipped is the most common launch mistake there is, and it can cost weeks before anyone notices.
The answer-engine file is written as decisions to make rather than settled practice —
whether GPTBot, ClaudeBot, PerplexityBot and the rest may read your site is a
choice, and not making it is also a choice.
scale/ — surviving ten times the loadWritten to be read before the traffic arrives, not during the incident.
| Items | Items | |||
|---|---|---|---|---|
| Capacity model | 29 | Multiple instances & regions | 35 | |
| Statelessness | 26 | Cost at scale | 19 | |
| Database at scale | 60 | Load testing & scale gates | 23 | |
| Caching | 25 | Service levels | 30 | |
| Async work & queues | 39 |
"Will it scale?" is unanswerable. "Will it survive 500 requests per second with a 40:1 read/write ratio and one tenant holding 30% of the rows?" has an answer, and the work to find it is mostly arithmetic.
Start with the capacity model; the rest of the domain is much less useful until you know which resource runs out first. Then service levels, because without a stated target "is it fast enough" is an argument rather than a measurement, and every scaling decision after that is made on vibes. Cost is in here rather than in a domain of its own because scaling problems and billing problems are the same problem seen from two sides.
post-launch/ — when it goes wrong anywayEvery other domain is about building something that does not break. This one assumes it broke.
Everything here is used after launch and has to be prepared before it. The question each item asks is not did you respond well — it is is the answer already decided?
| Items | Items | |||
|---|---|---|---|---|
| Can you act at all | 27 | Outages & dependency failure | 27 | |
| The first fifteen minutes | 20 | Rollback & kill switches | 20 | |
| You have been breached | 35 | Telling people | 18 | |
| Data loss & corruption | 26 | Learning & drills | 19 |
The rest of the repository makes sure you find out — monitoring is covered in
security/core/16 and
integrations/06. Neither asks
what happens next. Whether an immediate action exists for being breached, for a corrupted
database, for the connection going away, is a different question, and it is the one that
gets answered badly at 3am if it was not answered in daylight.
The plan for data loss is a backup you have restored, not a backup you have taken.
Can you act at all counts as a release gate. Launching without a prepared response is a decision, and it should be a recorded one.
stacks/ — only if you use them374 items across 19 supplements. Skip any file for a product you don't use; the core checklists stand on their own without them.
Backend & web Django · FastAPI · Ruby on Rails · Laravel · Spring Boot · Go / Gin · Express · NestJS · Next.js / React · GraphQL
Mobile iOS / Swift · Android / Kotlin · React Native · Flutter · macOS
Data & platform PostgreSQL · Supabase · Firebase · Docker · Kubernetes · AWS · Google Cloud · Vercel · Cloudflare · GitHub · Stripe
Your stack missing? That's the most useful contribution you can make. The format is
documented end to end in _TEMPLATE.md — a worked
example, what every field drives, and the one rule that decides whether an item belongs
in a stack file at all. Open issues exist for AWS, Vercel, Fly.io, Kubernetes, Firebase,
Stripe, FastAPI and GraphQL; see CONTRIBUTING.md.
[N/A] aggressively. No product on earth needs all 3,093 items. No mobile
app? core/11 and core/12 are 147 instant [N/A]s. Being honest about scope is what
makes the remainder trustworthy.* [ ] Not checked
* [x] Verified secure
* [!] Security issue found
* [N/A] Not applicable
For each [!]: affected component · exact endpoint/file/config · attack precondition ·
proof of exploitability · business impact · severity · remediation · regression test ·
owner · date verified
Do not accept "the frontend hides it", "the route is hard to guess", "the user needs a valid JWT", or "the WAF blocks it" as authorization controls by themselves.
Enforce every control at the lowest trustworthy layer available:
Browser/mobile UI → application/API → authorization layer
→ database (RLS) → storage → infrastructure/IAM → CI/CD → edge
ALL.md is every checklist concatenated — convenient for printing, or for
pasting into an AI tool. It's generated; edit the files under checklists/ instead.
MCP is a feature of the client, not the model — Cursor running DeepSeek can use it; DeepSeek's website cannot. Config for Claude Code, Claude Desktop, Cursor, VS Code Copilot, Gemini CLI, OpenAI Codex CLI, Qwen Code, Cline, Roo, Continue, Windsurf, Zed and Cherry Studio is in docs/mcp-clients.md.
| n8n · Dify · Flowise | Automation and agent platforms |
| OpenRouter | Any model, through an MCP client |
| DeepSeek, Qwen, Kimi, GLM | Base URLs and which clients accept them |
| Open WebUI, LibreChat | Self-hosted chat |
| The JSON API | No install at all — one HTTP GET |
| CI | Keep the file current, gate on blockers |
claude mcp add prodcheck -- npx -y --package=prodcheck prodcheck-mcp
For a chat window with no MCP — ChatGPT, Gemini, DeepSeek, Kimi, Qwen, GLM — generate a
file and paste it after one of the ready-made prompts. Each is
built on three rules, because without them an assistant will tell you the code is fine:
cite file:line for every claim, treat unknown as a real answer, and never mark
anything verified on the reader's behalf.
Generate a checklist scoped to your project, instead of reading 3,093 items:
npx prodcheck security --stack django -o SECURITY.md
npx prodcheck performance -o PERFORMANCE.md
npx prodcheck integrations -o LAUNCH.md
npx prodcheck scale -o SCALE.md
npx prodcheck post-launch -o INCIDENT-RESPONSE.md
npx prodcheck list # domains, areas and counts
npx prodcheck stacks # what supplements exist
npx prodcheck security --area ai -o AI-SECURITY.md
npx prodcheck --gate --stack supabase,cloudflare # release blockers, every domain
npx prodcheck --search cors --format text
npx prodcheck security --stack rails --format json
npx prodcheck performance --stack nextjs-react -o PERF.md
The domain is a positional argument — prodcheck security, and in time
prodcheck performance — because that is how you would say it. Omit it for everything.
--stack X returns every stack-agnostic item plus the supplements for X. An
unrecognized stack isn't an error — you get the stack-agnostic core, which stands on
its own. That's the whole design: it works for a stack nobody has written a file for yet.
Zero dependencies, Node 18+.
The MCP server gives an agent the items. This gives it the procedure:
npx prodcheck init
It writes a skill into .claude/skills/, .cursor/rules/ or AGENTS.md — whichever the
project already uses — and then you can ask your agent:
review this repo against the prodcheck release gate
What the skill enforces matters more than what it enables:
FINDING with a
file:line citation, an UNKNOWN, or an N/A with a reason. There is no "pass" it can
write; that stays yours.UNKNOWN stays visible. Most items on a checklist this size depend on production
configuration a repository cannot show. The list of things a human still has to check is
usually the most useful part of the report.This repository contains a folder about the bugs AI assistants write, and a section on why AI review misses them — fluent, confident output produced whether or not anything was established. The skill is written against that, not in spite of it.
Those three constraints are measured, not asserted. evals/ holds a fixture
app with nine planted defects and a clean control of the same app: a deterministic grader
resolves every citation against the real file, matches verdict phrasing, counts unknowns,
and counts findings on the control — where any finding is a false positive by construction.
No model grades another model's output, because a grader that is itself a model has the
same failure mode as the thing it grades.
It does one thing: check whether what you built is ready to ship. For skills that teach an agent how to build well — testing, debugging, planning, git workflow — see agent-skills. They compose; use both.
Let your coding agent query the checklist directly while it works, instead of you pasting it in. Read-only, no filesystem or network access beyond its own bundled data.
Claude Code
claude mcp add prodcheck -- npx -y --package=prodcheck prodcheck-mcp
Anything else — add to your MCP client config:
{
"mcpServers": {
"prodcheck": {
"command": "npx",
"args": ["-y", "--package=prodcheck", "prodcheck-mcp"]
}
}
}
Four tools: list_checklists, checklist_for_stack, release_gate, search_checklist.
Then ask your agent things like "check this repo against the release gate for a
Next.js + Supabase app" and it pulls the relevant items itself.
Both of the above read data/checklist.json, validated against
data/schema.json. Use it directly if you're building something else
— it's CC BY 4.0.
The Markdown under checklists/ is the source of truth; the JSON is generated from it by
./scripts/build.sh. There is deliberately no severity field —
here's why.
Shipped
npx prodcheck — generate a filtered checklist for your stackDomains
All five domains have shipped. The structure has room for more — launch, social and legal are the obvious next ones — and the plan is written before the content, not after.
performance/ — shipped: 313 items across 9 checklists.integrations/ — shipped: 192 items across 6 checklists.scale/ — shipped: 286 items across 9 checklists.post-launch/ — shipped: 192 items across 8 checklists. Added after the other
four, because a gap showed up once they were all in front of a reader: every domain
described how to build something that does not break, and none asked whether the
response was prepared for when it breaks anyway.Next
scale/ — 214 → 286. Added service levels and error budgets, search and
analytics engines, realtime fan-out, contract and event versioning, and tenant-shape
capacity. The gaps were measured rather than guessed at.npx prodcheck init writes the review procedure into
.claude/skills/, .cursor/rules/ or AGENTS.md. Usable today: the MCP server
already supplies the items, what was missing was the discipline.launch/, social/, legal/. The structure absorbs them without
moving anything else.Later
Parked deliberately, and last. Everything above is content and tooling that works today; this is a different product built on top of it, and shipping it half-done would be worse than not shipping it. Recorded here so the design decisions are not lost.
The idea: a tool that checks a codebase against the checklist, writes a report to the repo root, and re-opens items when the relevant code changes.
prodcheck scan detect stack and features from the repo -> .prodcheck/profile.json
prodcheck check deterministic rules, no model involved -> findings
prodcheck review model-assisted review, citations verified -> findings
prodcheck report render SECURITY-REVIEW.md from state
prodcheck gate exit non-zero if a blocking item is unresolved (for CI)
scan — profile the repo. Read package.json, requirements.txt, go.mod,
Dockerfile, CI config and the shape of the source tree to work out which stack is
in use and which features exist — file upload, webhooks, multi-tenancy, background
jobs, an LLM surface. Selects the applicable items before any model is involved.
A Django app with no mobile client and no file uploads does not need 1,435 items;
it needs closer to 400.
check — the deterministic tier. Roughly 160 items are answerable by search
alone: the must-not-exist list, unpinned CI
actions, secrets in a Dockerfile, dangerouslySetInnerHTML, wildcard CORS. These
need no model, cost nothing, cannot hallucinate, and run in CI on every push.
review — the model-assisted tier, built not to be trusted. Most items need
someone to read the code, so this runs inside whatever agent you already use
(Claude Code, Cursor, Copilot) over MCP plus a skill file — no API key, no token
cost from us. The design constraints matter more than the feature:
[x]. Its output is evidence, not a verdict. Results are
deterministic-pass, model-flagged (needs a human), or human-verified. Only the
first and last count toward the gate. There is no green tick a model put there.file:line; the tool confirms
that line exists and that the quoted code matches before accepting it. Findings that
fail this check are dropped, which removes most hallucination for almost no cost.unknown is a real result. A model may say it could not determine something, and
unknown never silently becomes pass. It is reported separately. State that survives re-runs. .prodcheck/state.json, keyed by the stable item
ids already in data/checklist.json, storing status,
justification, date, and a hash of the code it was decided against. Items you marked
[N/A] stay marked — until the relevant code changes, at which point they re-open
with "verified at abc1234; that file has changed since." This is what makes it a
living document rather than a report that rots.
gate in CI. Without a build that fails, the report gets stale and stops being
read. This is the part that makes the rest stick.
Skill file for agents. prodcheck init --skill writes the review procedure into
.claude/skills/ or AGENTS.md, so an agent knows how to run all of the above.
Building an AI code reviewer on top of a checklist whose
vibe-coding/folder warns that AI review confirms AI-written code is fine, only makes sense if the design takes that warning seriously. That is what the three constraints above are for.
Stack files, corrections, missing items, and war stories are all welcome. See CONTRIBUTING.md.
Open a discussion or an issue — that way the answer is public and the next person finds it.
For anything that does not fit there, @farzam_habibi on X.
See SECURITY.md. That includes an item in this checklist that is wrong in a way that would make a reader less safe — a checklist that gives false confidence is worse than no checklist, so those are treated as the highest-priority reports.
The single most useful contribution is a stack file for a stack that isn't covered.
There are open issues for FastAPI,
AWS,
Kubernetes,
Vercel,
Firebase,
Stripe and
GraphQL,
each labelled good first issue. Copy
_TEMPLATE.md and open a PR.
A starting point, not a guarantee, not a compliance certification, and not a substitute for a professional security audit. Completing every item does not make an application secure. Use it to find problems, not to declare their absence.
Dual-licensed, because the two halves of this repository are different kinds of thing:
| License | ||
|---|---|---|
Content — checklists/, data/, ALL.md | CC BY 4.0 | Copy it, adapt it, ship it commercially. Keep the attribution. |
Code — cli/, scripts/, the prodcheck package | MIT | Creative Commons licenses aren't designed for software, and a CC-licensed npm package gets rejected by corporate legal review. MIT removes that friction. |
This repository was compiled and expanded with Claude (Anthropic) and ChatGPT (OpenAI), working from a real pre-production review rather than generating checklist items from scratch. They did the parts that don't fit in one person's head: cross-referencing hundreds of findings against OWASP categories, keeping 3,093 items consistent in wording and structure, and spotting the gaps between sections.
That's worth stating plainly for two reasons.
It's the honest provenance. A security checklist asks you to trust it. You should know how it was made.
The vibe-coding/ folder applies to this repository too. It says AI-generated work
needs review that assumes the AI was confidently wrong somewhere, and that "the tests
pass" is not a security argument. Both were true here — the test suite for the CLI caught
three real bugs in AI-written code, including an MCP server that silently truncated
every response over 8 KB. The checklist is not exempt from its own advice, and neither are the
tools shipped alongside it.
If you find an item that's wrong, plausible-sounding but false, or subtly misleading,
that's exactly the failure mode vibe-coding/07-review-blind-spots.md warns about.
Open an issue — that
correction is worth more than three new items.
Written and maintained by the founding team at Arioo, out of the work of getting our own product ready to ship.
Contributions from everyone who opens an issue or a PR are what will keep it accurate — see the contributors.
FAQs
Pre-production checklists for solo founders — 4,372 items, 88% portable to any stack, 26 stack supplements. CLI + MCP server.
The npm package prodcheck receives a total of 98 weekly downloads. As such, prodcheck popularity was classified as not popular.
We found that prodcheck demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.

Security News
It has been one year since Shai-Hulud made its first appearance on npm.

Research
/Security News
Operators behind PolinRider used a compromised GitHub account to plant malware in four development versions of a Packagist package with 700,000+ downloads.

Security News
GitHub Actions now supports cache-mode, a least-privilege control on the Actions cache aimed at the cache poisoning technique behind recent compromises.