This project is in active pre-1.0 development; only the main branch is supported. There is no formal release channel yet (see README for the phase ledger). When a versioned release ships, this section will be updated to enumerate supported version ranges.
Please do not open a public GitHub issue for security findings. Use one of the private channels below.
- GitHub Security Advisories (preferred): open a private security advisory on this repository.
- Email:
jacobwucs@gmail.comwith[LOP-SECURITY]in the subject line.
When reporting, please include:
- A clear description of the vulnerability and the affected surface (which markdown helper, which auth flow, which route).
- A minimal reproduction — ideally a unit test or a curl request.
- Your assessment of impact (information disclosure / privilege escalation / DOS / XSS / etc.).
- Any constraints on disclosure timing.
We will acknowledge receipt within 5 business days and aim to ship a fix or a documented mitigation within 30 days for high-severity issues, or 90 days for medium / low.
Surfaces of particular concern, in order of priority:
Per ADR-0018, the project renders four user-facing markdown surfaces server-side: bio, reviewNotes, rationale, actionRationale. Each surface is passed through unified → remark-parse → remark-gfm → remark-rehype → rehype-sanitize (allow-list mode) → rehype-stringify. The output is the only thing that crosses the dangerouslySetInnerHTML boundary.
In scope: any payload that produces unsanitized HTML, javascript:-URI links, onerror= / onload= attributes, dangerous data: URIs, or unescaped <script> content in any of the four surfaces. Test files under lib/markdown/*.test.ts contain the live XSS-payload corpus; please reference test names in your report.
Out of scope: payloads in plain-text fields that are never rendered as HTML (displayName, email, search inputs); these are rendered with React text-escaping, so HTML injection there is not exploitable.
ADR-0012 + ADR-0020: NextAuth v5 with multi-provider OAuth (GitHub + Google) over Drizzle adapter + DB sessions. The verificationToken table is the bottleneck against unauthenticated mailflow spam.
In scope: session-token leak, CSRF on POST route handlers, OAuth state reuse, verification-token replay, unauthenticated access to /curator/* routes (env-var gated via LOP_CURATOR_LOGINS).
ADR-0024: four surfaces (bio · avatar · rating-challenge · subscribe) flow through the framework-only ContentModerator interface. The default NoopModerator lets everything pass; production deployments will swap in a concrete provider (ADR-0025 TBD).
In scope: bypassing the moderation hook entirely (e.g., a path that writes to one of the four surfaces without invoking the moderator); surface-level differences (e.g., bio being moderated but rating-challenge prose not). Concrete-provider bypasses are out of scope until ADR-0025 ships.
ADR-0019: user-uploaded avatars are passed through sharp server-side for EXIF stripping + auto-rotation. The Vercel Blob imageOverride URL is the only thing that should reach the public — never the upload buffer.
In scope: EXIF survival after strip, server-side path traversal on the upload form, orphan-blob accumulation that's not reachable through pnpm cleanup-orphan-blobs.
ADR-0005 is the brand-defining invariant: every rating change ships as a net-new YAML file under content/problems/*/ratings/. A pre-commit hook blocks modify / delete / rename / copy on existing files.
In scope: any commit that ships a non-net-new rating action — including history rewrites via git filter-branch, git rebase -i, or --amend — that bypasses the hook. Out of scope: ratings that have not been committed yet (the hook fires on commit, by design).
- Hosting / DNS / Vercel-account compromise — that's an operational concern for the deployer, not the codebase.
- Third-party services (GitHub OAuth, Google OAuth, Resend, Turso, Vercel Blob, Anthropic API) — please report directly to the vendor.
- Denial-of-service via expensive content — the project is file-first; CI catches malformed content. If you find a way to make
pnpm buildtake forever, that's a CI-cost concern but not a security issue. - Vulnerable transitive dependencies surfaced by
npm audit— please open a regular issue with the advisory ID; we triage these as routine dependency bumps unless they're exploitable in our specific usage.
We follow coordinated disclosure: once a fix is in main and a CHANGELOG entry has shipped under the relevant Phase / Unit, the reporter is credited (with permission) in the CHANGELOG and in the GitHub Security Advisory. We are happy to embargo for a reasonable period if the reporter needs time to publish a write-up.
Thank you for helping keep LLM OpenProblems trustworthy.