---
title: "Security"
description: "How to report a vulnerability, what counts as one in a system distributed as copied source, and where the advisories are published."
url: "https://opsinjs.pensievelabs.org/project/security"
source: "https://opsinjs.pensievelabs.org/project/security.md"
section: "Project"
kind: "project"
reviewed: "2026-09-20"
reviewer: "engineering"
aliases: ["vulnerability", "responsible disclosure", "report a security issue"]
---

> Elements written as `<PascalCase … />` below are opsinjs documentation
> components. Their attributes are the content: the values they render are
> generated from `tokens/*.json` and `registry/catalogue.ts` and are
> published separately at https://opsinjs.pensievelabs.org/r/index.json and under the Reference
> section.
> Nothing is missing from this page. The data simply does not live in
> the prose.

<PageTemplate kind="project" />

## Reporting a vulnerability [#reporting-a-vulnerability]

<Todo>
  GitHub private vulnerability reporting, the Security tab route described below, is
  a feature of public repositories, so it cannot be turned on while this repository
  is private. It will be enabled at the moment the repository is made public, and
  until then an outside reporter has no private route to us: the repository is not
  visible to them at all. Opening the repository is therefore a release blocker for
  this reason as much as for distribution. Do not read this as permission to
  disclose publicly. Take this note down once the repository is public and private
  vulnerability reporting is enabled, and check that the routes on
  [Community](./community.mdx) resolve at the same time.
</Todo>

**Do not open a public issue.** Use private vulnerability reporting on the
canonical repository, reached through the Security tab at "Report a
vulnerability", so that the report is visible only to the maintainers until
there is a fix.

The repository is named on [Official resources](./official-resources.mdx), which is
also the page to check before you trust any address claiming to be ours. There is
no security email address for this project, and anybody who gives you one is not
us.

In the report, please include: what you found, the smallest reproduction you can
manage, what an attacker gets from it, and which version or commit you were
looking at. If you are not sure whether something is a vulnerability, report it
anyway and say you are not sure. A false positive costs a short conversation; an
unreported one does not.

## What to expect [#what-to-expect]

This is a small, unfunded project and it will not pretend otherwise. There is no
service-level agreement, no bug bounty and no payment. What you get is an
acknowledgement, a genuine assessment, and credit in the advisory unless you ask
not to be named. If a report goes unanswered for a fortnight, escalate through
the channels on [Community](./community.mdx). Say that you have an unanswered
security report, and nothing more than that in public.

## What counts as a vulnerability here [#what-counts-as-a-vulnerability-here]

opsinjs is distributed as source you copy into your own repository, so the threat
model is not that of a runtime dependency:

* **Anything in code the registry emits** that leads to injection, script
  execution from data, or an unsafe DOM operation. A component that renders
  patient-supplied text is the obvious place to look.
* **Anything in the registry pipeline** that could serve a consumer different
  bytes from the ones documented, or that resolves a component name to an
  unexpected file path.
* **The documentation site** itself, which is this application. That includes
  its API routes.
* **A dependency advisory** that actually reaches consumers through what we ship,
  as opposed to one in a build-time tool that never leaves this repository.

## What is not a security issue [#what-is-not-a-security-issue]

**A clinical safety concern is not a vulnerability, and routing it here delays
it.** If a component, a piece of guidance or an example could lead a person to
misread their own health data, that is more urgent than most security reports and
belongs in a public issue where a clinical reviewer can see it. Opening one
needs a public issue tracker, which is not reachable until the repository is
public, for the reason in the note at the top of this page. Say clearly that it
is a safety concern; the
[safety review checklist](../health/safety-review-checklist.mdx) is the shape of
the argument that helps most.

Also not vulnerabilities: a missing hardening header on a documentation page with
no accounts and no data; the absence of a feature; a dependency advisory that
does not reach consumers; and anything requiring an attacker who already controls
the developer's machine.

## Advisories [#advisories]

No advisory has been published, and no version has been released, so there is no
released version to attach one to. That is not the same as saying there is no
code: every catalogue row is implemented and installable, and its source is
served through the registry for anybody to copy in.
A defect in one of those would be handled here
exactly as described above. It would simply have no version number to name,
which is one more reason to commit the files `shadcn add` writes, in their own
commit, so a later `--diff` has something to compare against.

<NoDataYet script="scripts/build-registry.mts" />

When there are advisories, each will name the affected versions and the fix.
Because you own the copied source, each will also name the exact change you need
to apply by hand if you are not taking a full upgrade. That last part is the
awkward consequence of
[ADR 0002](./decisions/0002-shadcn-registry-distribution.mdx): a fix published to
npm reaches everyone, and a fix published to a registry reaches only the people
who come back for it. Advisories here are written for people who will be patching
their own copy.

<LastUpdated />

<Reviewed />
