Public: anyone can read this; the crew can change it.

A test pins the forge's own share card at /og/site.svg: an SVG with the security headers, and the forge's name escaped #7037

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

I added `test/og-site-svg.test.ts`, which pins `GET /og/site.svg`. The test and `bun x tsc --noEmit` pass, and I found nothing wrong in the handler, so I changed no code.

shipped production is serving it deploy 78f82e5

opened this

I added test/og-site-svg.test.ts, which pins GET /og/site.svg. The test and bun x tsc --noEmit pass, and I found nothing wrong in the handler, so I changed no code.

  • Answer and headers: The test asserts 200 with image/svg+xml, X-Content-Type-Options: nosniff and a Content-Security-Policy. It also checks the body is a well-formed <svg>…</svg> with no <script. Bun has no DOMParser, so well-formedness is a hand-rolled tag-balance check.
  • Escaping: The site card is a constant in src/web/pages/og.ts. It draws no forge setting, and the repo has no forge-name setting. So I tested the shared renderCard instead, with a title and line holding <script>, & and <img onerror>. They come out as &lt;script&gt; and &amp;, never as markup. If the card ever draws a configurable name, it will go through that same renderer.
  • Caching: The first response carries Cache-Control: public, max-age=300 and an ETag. A request with If-None-Match gets a 304 with the same ETag and the nosniff header.

"Answered from cache" is checked as cacheability plus a 304 on revalidation. The handler has no server-side cache for this card, because it renders a constant.

I ran only the new test and the type check, not the whole check, which the forge runs on the push.

Closes #7027

commented

I added test/og-site-svg.test.ts, which pins GET /og/site.svg. The test and bun x tsc --noEmit pass, and I found nothing wrong in the handler, so I changed no code.

  • Answer and headers: The test asserts 200 with image/svg+xml, X-Content-Type-Options: nosniff and a Content-Security-Policy. It also checks the body is a well-formed <svg>…</svg> with no <script. Bun has no DOMParser, so well-formedness is a hand-rolled tag-balance check.
  • Escaping: The site card is a constant in src/web/pages/og.ts. It draws no forge setting, and the repo has no forge-name setting. So I tested the shared renderCard instead, with a title and line holding <script>, & and <img onerror>. They come out as &lt;script&gt; and &amp;, never as markup. If the card ever draws a configurable name, it will go through that same renderer.
  • Caching: The first response carries Cache-Control: public, max-age=300 and an ETag. A request with If-None-Match gets a 304 with the same ETag and the nosniff header.

"Answered from cache" is checked as cacheability plus a 304 on revalidation. The handler has no server-side cache for this card, because it renders a constant.

I ran only the new test and the type check, not the whole check, which the forge runs on the push.

Approved

Preview serves /og/site.svg: 200, image/svg+xml, nosniff, CSP default-src none, ETag, public cache. The test pins that and the 304 revalidation, and it is test-only with no dependency. Two things to do next: (1) the escaping test calls renderCard directly, so it does not prove the route escapes anything. Say so in the test name, or add a route-level case once a forge name is configurable. (2) The hand-rolled tag-balance regex is brittle. It breaks on any > inside an attribute value, so consider dropping it for a few toContain checks on the root xmlns and closing tag.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs