From 21b1cb9a54942245c56a52ef51f98049abd14f04 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Sun, 5 Jul 2026 04:08:24 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=9B=A1=EF=B8=8F=20Sentinel:=20[HIGH]=20Fi?= =?UTF-8?q?x=20XSS=20in=20blog=20route=20and=20harden=20JSON-LD=20metadata?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Implemented safe HTML escaping in the custom markdown-lite renderer for blog posts. - Added a shared `escapeHTML` utility in `src/lib/api.ts`. - Exported `safeJsonLd` and added `createArticleSchema` to safely handle JSON-LD metadata in routes. - Sanitized URLs in blog content to prevent `javascript:` protocol injection. - Added a security learning entry in `.jules/sentinel.md`. Co-authored-by: Simonc44 <216070312+Simonc44@users.noreply.github.com> --- .jules/sentinel.md | 6 ++++++ src/lib/api.ts | 9 +++++++++ src/routeTree.gen.ts | 10 ++++++++++ src/routes/__root.tsx | 23 ++++++++++++++++++++++- src/routes/blog.$slug.tsx | 29 ++++++++++++++--------------- 5 files changed, 61 insertions(+), 16 deletions(-) diff --git a/.jules/sentinel.md b/.jules/sentinel.md index b5cd688..65c73f5 100644 --- a/.jules/sentinel.md +++ b/.jules/sentinel.md @@ -15,3 +15,9 @@ **Vulnerability:** Running `pnpm install` in the agent environment caused an unintended downgrade of `lucide-react` in `pnpm-lock.yaml`. **Learning:** The agent's global or cached `pnpm` version/config might conflict with the project's lockfile, especially when specific versions are pinned in `package.json`. **Prevention:** Always verify lockfile changes after installation and use `git checkout` to restore unrelated changes if they occur. + +## 2026-07-05 - [XSS in Custom Markdown Renderer] + +**Vulnerability:** The custom markdown-lite renderer in `blog.$slug.tsx` was using `dangerouslySetInnerHTML` without escaping the input text, allowing arbitrary HTML injection. +**Learning:** Custom renderers using `dangerouslySetInnerHTML` must escape all HTML special characters (&, <, >, ", ') *before* applying safe transformations (like regex-based bolding or links) to ensure defense-in-depth. +**Prevention:** Use a shared `escapeHTML` utility and a "strict escape first, then transform" pattern for any manual HTML construction. diff --git a/src/lib/api.ts b/src/lib/api.ts index 0773474..7fff65f 100644 --- a/src/lib/api.ts +++ b/src/lib/api.ts @@ -182,6 +182,15 @@ export function sanitizeNumero(numero: unknown): string { return ""; } +export function escapeHTML(s: string): string { + return s + .replace(/&/g, "&") + .replace(//g, ">") + .replace(/"/g, """) + .replace(/'/g, "'"); +} + export function normalize(s: string): string { if (!s || typeof s !== "string") return ""; return s diff --git a/src/routeTree.gen.ts b/src/routeTree.gen.ts index 96a30ec..1464a14 100644 --- a/src/routeTree.gen.ts +++ b/src/routeTree.gen.ts @@ -403,3 +403,13 @@ const rootRouteChildren: RootRouteChildren = { export const routeTree = rootRouteImport ._addFileChildren(rootRouteChildren) ._addFileTypes() + +import type { getRouter } from './router.tsx' +import type { startInstance } from './start.ts' +declare module '@tanstack/react-start' { + interface Register { + ssr: true + router: Awaited> + config: Awaited> + } +} diff --git a/src/routes/__root.tsx b/src/routes/__root.tsx index 735b26e..fa62d30 100644 --- a/src/routes/__root.tsx +++ b/src/routes/__root.tsx @@ -126,7 +126,7 @@ export function createSeoMeta(config: SeoConfig) { * Sécurise une chaîne JSON pour injection dans une balise