Skip to content

fix(create-blocks-app): harden demo template against Set-Cookie CRLF injection and single-quote XSS#204

Merged
hfurkanbozkurt merged 2 commits into
mainfrom
fix/demo-template-security
Jul 16, 2026
Merged

fix(create-blocks-app): harden demo template against Set-Cookie CRLF injection and single-quote XSS#204
hfurkanbozkurt merged 2 commits into
mainfrom
fix/demo-template-security

Conversation

@hfurkanbozkurt

Copy link
Copy Markdown
Contributor

Summary

Fixes two security defects in the demo template of @aws-blocks/create-blocks-app, surfaced by a security bench-audit of the demo template. Both are minimal, focused hardening changes to template code that ships to every user who scaffolds the demo template.

Defect 1 — Set-Cookie header (CRLF) injection

The public (no requireAuth) setCookie / deleteCookie API methods in templates/demo/aws-blocks/index.ts wrote a user-controlled cookie name/value straight into the Set-Cookie response header:

context.response.headers.set('set-cookie', `${name}=${value}; Max-Age=3600; Secure; SameSite=None; Partitioned`);

A name/value containing CR (\r) or LF (\n) can inject additional response headers (HTTP response splitting / header injection).

Fix: a small module-level assertNoCrlf(value, field) guard rejects any component containing CR/LF, invoked for name+value in setCookie and name in deleteCookie before the header is written. getCookie (read-only) is unchanged.

Defect 2 — Incomplete HTML escaping (XSS via single quote)

escapeHtml in templates/demo/src/index.ts escaped &, <, >, and " but not the single quote ('). The helper is interpolated into single-quoted JS attribute contexts, e.g.:

onchange="toggleTodo('${escapeHtml(todo.todoId)}', this.checked)"

A ' in the interpolated value breaks out of the JS string literal → XSS.

Fix: append .replace(/'/g, '&#39;') to the chain (& remains escaped first, so no double-encoding).

Tests

  • New src/cookie-crlf.test.ts — mirrors the guard + Set-Cookie builder; asserts valid headers build and that CRLF in name/value (plus bare CR, bare LF, and deleteCookie) is rejected.
  • Updated src/escape-html.test.ts — mirror now escapes '; added "escapes single quotes" and "prevents single-quote attribute breakout" tests; the all-special-chars test now includes '.
  • Full suite: 50 passed / 0 failed (tsc clean, node --test).

Changeset

Added .changeset/fix-demo-template-security.md (patch bump for @aws-blocks/create-blocks-app).

Notes

@hfurkanbozkurt
hfurkanbozkurt requested a review from a team as a code owner July 15, 2026 19:17
@hfurkanbozkurt
hfurkanbozkurt merged commit f6a7fc7 into main Jul 16, 2026
43 of 70 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants