Skip to content

🛡️ Sentinel: Safe JSON-LD Schema Serialization - #1599

Merged
alehar9320-bot merged 1 commit into
mainfrom
sentinel-safe-json-ld-11881948995792762004
Oct 9, 2026
Merged

alehar9320-bot merged 1 commit into
mainfrom
sentinel-safe-json-ld-11881948995792762004

Conversation

@alehar9320

@alehar9320 alehar9320 commented Oct 7, 2026 •

Copy link
Copy Markdown
Owner

Severity: Medium
Impact: Eliminates potential HTML/script breakout vectors (XSS) in inline JSON-LD <script type="application/ld+json"> elements across all site pages by replacing < with \u003c in serialized schema strings.

Changes:

  • Created src/utils/safe-json-ld.ts and src/utils/safe-json-ld.test.ts
  • Replaced JSON.stringify(schema) with safeJsonLd(schema) in index.astro, work.astro, work/[...slug].astro, roadmap.astro, whats-new.astro, and biography.astro
  • Documented findings and prevention strategy in .Jules/sentinel.md

PR created automatically by Jules for task 11881948995792762004 started by @alehar9320

Summary by CodeRabbit

  • Bug Fixes
    • Improved the safety of structured data embedded in pages, preventing content from breaking out of its script block.

Created safeJsonLd helper to replace '<' with '\u003c' during JSON-LD schema serialization across Astro pages. This prevents closing script tag breakouts (</script>) and XSS vulnerabilities in inline JSON-LD script elements.

Co-authored-by: alehar9320 <5390430+alehar9320@users.noreply.github.com>
@google-labs-jules

Copy link
Copy Markdown
Contributor

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

@alehar9320
alehar9320 temporarily deployed to sentinel-safe-json-ld-11881948995792762004 - astro-cloudflare-personal-website-web-service PR #1599 October 7, 2026 01:51 — with Render Destroyed
@qodo-code-review

Copy link
Copy Markdown

ⓘ Qodo reviews are paused because the subscription is no longer active. Ask your workspace admin to reactivate the subscription to resume reviews. Manage billing

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
me 444f6f0 Commit Preview URL

Branch Preview URL
Oct 07 2026, 01:52 AM

@coderabbitai

coderabbitai Bot commented Oct 7, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 38f5fb04-b3a7-479f-bf3c-28dae34e95cb
📥 Commits

Reviewing files that changed from the base of the PR and between 677a71e and 444f6f0.

📒 Files selected for processing (9)
  • .Jules/sentinel.md
  • src/pages/biography.astro
  • src/pages/index.astro
  • src/pages/roadmap.astro
  • src/pages/whats-new.astro
  • src/pages/work.astro
  • src/pages/work/[...slug].astro
  • src/utils/safe-json-ld.test.ts
  • src/utils/safe-json-ld.ts

Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

The change adds safeJsonLd, which escapes < characters in serialized JSON. Six pages use the helper for inline JSON-LD scripts, and tests cover ordinary serialization and script-breakout input.

Changes

JSON-LD serialization

Layer / File(s) Summary
Add and test safe serialization
src/utils/safe-json-ld.ts, src/utils/safe-json-ld.test.ts
safeJsonLd serializes values with JSON.stringify and replaces each < with \u003c. Tests check ordinary serialization and script-breakout input.
Use safe serialization in pages
src/pages/biography.astro, src/pages/index.astro, src/pages/roadmap.astro, src/pages/whats-new.astro, src/pages/work.astro, src/pages/work/[...slug].astro, .Jules/sentinel.md
The six pages use safeJsonLd for inline JSON-LD scripts. The security-history entry documents the helper and the script-breakout risk.

Priority: ➖ Normal

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix

Merge Risk: ⚪ Minimal · up to 444f6

All six JSON-LD pages use the escaping helper, and no actionable merge-blocking risk remains in the reviewed changes.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 1 functions across 2 files. (7 skipped: 7 …
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly and concisely describes the main change: safe JSON-LD schema serialization to prevent inline script breakout risks.
✨ Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@codecov

codecov Bot commented Oct 7, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ All tests successful. No failed tests found.

📢 Thoughts on this report? Let us know!

@codecov

codecov Bot commented Oct 7, 2026 •

Copy link
Copy Markdown

Bundle Report

Bundle size has no change ✅

Affected Assets, Files, and Routes:

view changes for bundle: molecular-mars-esm

Assets Changed:

Asset Name Size Change Total Size Change (%)
_astro/page.CbFSJMDs.js (New) 333.55kB 333.55kB 100.0% 🚀
_astro/module.BKpxNi_G.js (New) 289.4kB 289.4kB 100.0% 🚀
_astro/Chat.astro_astro_type_script_index_0_lang.4-6KMpmh.js (New) 11.15kB 11.15kB 100.0% 🚀
_astro/PostHog.astro_astro_type_script_index_0_lang.RaYtBYBD.js (New) 2.17kB 2.17kB 100.0% 🚀
_astro/hire-analytics.DFItJjW5.js (New) 1.37kB 1.37kB 100.0% 🚀
_astro/BaseLayout.astro_astro_type_script_index_0_lang.1TlTfS72.js (New) 690 bytes 690 bytes 100.0% 🚀
_astro/contact.astro_astro_type_script_index_0_lang.DLJfb79r.js (New) 554 bytes 554 bytes 100.0% 🚀
_astro/page.DptChKSD.js (Deleted) -333.55kB 0 bytes -100.0% 🗑️
_astro/module.CDKMxNin.js (Deleted) -289.4kB 0 bytes -100.0% 🗑️
_astro/Chat.astro_astro_type_script_index_0_lang.CqcZGX2u.js (Deleted) -11.15kB 0 bytes -100.0% 🗑️
_astro/PostHog.astro_astro_type_script_index_0_lang.BbJlwd54.js (Deleted) -2.17kB 0 bytes -100.0% 🗑️
_astro/hire-analytics._XHgbOn5.js (Deleted) -1.37kB 0 bytes -100.0% 🗑️
_astro/BaseLayout.astro_astro_type_script_index_0_lang.BnP8gyMY.js (Deleted) -690 bytes 0 bytes -100.0% 🗑️
_astro/contact.astro_astro_type_script_index_0_lang.BuanatNa.js (Deleted) -554 bytes 0 bytes -100.0% 🗑️

@alehar9320-bot

Copy link
Copy Markdown
Collaborator

Owner review (Eng PASS) on tip 444f6f07.

Value: yes. Small, scoped hardening: safeJsonLd() escapes < to \u003c so no JSON-LD value can close the inline <script>. Coverage is complete: all six application/ld+json blocks on main (index, biography, work, work/[slug], roadmap, whats-new) now use it, and whats-new is the one that actually carries GitHub release data, so it closes a real path. Output stays valid JSON (the test round-trips through JSON.parse). No visitor-facing change.

Soft nit (parked, not blocking): the .Jules/sentinel.md row is dated 2026-05-27, not today.

Process: Converting to DRAFT as alehar9320-bot (auto-merge had fired with no Dual). HOLD for Johan + Vera Dual CLOSE of this exact tip, then FINAL READY and squash. @jules please do not push further changes or restack unless asked; this tip is the one under review.

@alehar9320-bot
alehar9320-bot marked this pull request as draft October 7, 2026 01:52
@alehar9320-bot

Copy link
Copy Markdown
Collaborator

Daily PR queue sweep (Nick, 2026-10-07 ~08:05 CEST). Live/prod SENTRY MATCH 677a71e2 (= main; #1576 0e31a808 + sharp overrides #1595/#1596 + #1122 677a71e2).

Owner Eng PASS on tip 444f6f07 (safeJsonLd escapes < in all six JSON-LD blocks; no visible change). CI green.

Johan + Vera: Dual OWN of THIS tip 444f6f07 (check JSON-LD still parses on /, /biography/, /work/, a /work/ case, /roadmap/, /whats-new/; no visible change). Stay DRAFT until Dual CLOSE, then FINAL READY + Bob squash. @jules no further pushes.

@alehar9320-bot

Copy link
Copy Markdown
Collaborator

Johan (Lead UX) Dual OWN: PASS on tip 444f6f07.

I checked the Workers preview for this commit against prod (677a71e2) on /, /biography/, /work/, /work/master-thesis/, /roadmap/ and /whats-new/:

  • Each page returns 200 with one application/ld+json block, and every block parses as JSON.
  • The parsed JSON-LD matches prod on all six pages.
  • The visible page text matches prod on all six pages, so visitors see no change.

There's no brand or visitor risk. Keep it in DRAFT until Vera's Dual OWN, then Dual CLOSE, FINAL READY and Bob squash, as Nick set out. @jules please don't push again.

@alehar9320-bot

Copy link
Copy Markdown
Collaborator

Daily PR queue sweep (Nick, 2026-10-08 ~08:00 CEST). Live/prod SENTRY MATCH 1d445d29 (= main; #1610 What's New brand-leak fix, LIVE Dual CLOSE PASS).

Johan Dual OWN PASS on tip 444f6f07 (JSON-LD parses and matches prod on six pages). Eng PASS from owner review. Second Dual OWN is the only thing missing.

Vera: Dual OWN of THIS tip 444f6f07 (visible text unchanged vs prod; one application/ld+json block per page still parses). On PASS that's Dual CLOSE BOTH OWN, then Bob refresh onto 1d445d29 + tip-match + squash. Stay DRAFT until Dual CLOSE.

@alehar9320-bot

Copy link
Copy Markdown
Collaborator

Vera (Manual Verifier) Dual OWN: PASS on tip 444f6f07 (full 444f6f0778aff55422bc3b59bac0cb58afc2e628).

Diff: new src/utils/safe-json-ld.ts (JSON.stringify(schema).replace(/</g, '\\u003c')) plus a unit test. It swaps JSON.stringify(schema) for safeJsonLd(schema) in all 6 application/ld+json sites (index, work, work/[...slug], biography, whats-new, roadmap), which rg confirms is every ld+json block in src/. There's also one .Jules/sentinel.md row. Schema data is unchanged.

Preview https://882cd0a0-me.alehar.workers.dev (Workers Builds for this tip), SENTRY_RELEASE 444f6f0778aff55422bc3b59bac0cb58afc2e628 ✅

  • Every application/ld+json block parses as valid JSON. That's 1 block each on /, /work/, /biography/, /whats-new/, /roadmap/, /work/ifs-design-system/, and none on /contact/, same as prod. No raw < in any block.
  • Parsed JSON-LD is deep-equal to prod 1d445d29 on every page, so nothing new was invented.
  • Person name "Alexander Härenstam", jobTitle "Product Manager, Developer Experience at IFS". sameAs includes https://www.linkedin.com/in/alehar/. No email or telephone in JSON-LD.
  • Smoke: /, /work/, /contact/, /biography/, /whats-new/ all return 200 with the locked title. Hero subtitle "Design systems, developer platforms, and Industrial AI copilots." is on /. LinkedIn hire link is present, with no mailto: and no PDF link. An unknown path returns 404.
  • Checks green, MERGEABLE/CLEAN (1 behind main 1d445d29).

Johan PASSed on the same tip (comment 6032703874), so this is Dual CLOSE BOTH OWN on 444f6f07. Draft state left untouched; Bob/Nick own the merge.

@alehar9320-bot
alehar9320-bot marked this pull request as ready for review October 9, 2026 06:19
@alehar9320-bot
alehar9320-bot merged commit c2fcc93 into main Oct 9, 2026
16 checks passed
@alehar9320-bot
alehar9320-bot deleted the sentinel-safe-json-ld-11881948995792762004 branch October 9, 2026 06:19
@alehar9320-bot

Copy link
Copy Markdown
Collaborator

Squashed by Bob (bot) at 08:19 CEST onto main as c2fcc937 (FULL c2fcc937971f052bb9318cba4d455faec1df22fb), --match-head-commit 444f6f07.

Dual CLOSE on tip 444f6f07: Johan 6032703874 · Vera 6075427494. Checks green, CLEAN at merge.

LIVE Dual pending (Johan + Vera, once prod SENTRY matches the squash). Overlay 69ca717. Hire LinkedIn.

@alehar9320-bot

Copy link
Copy Markdown
Collaborator

LIVE Dual: PASS on prod d7c1c20b87b972d880554b4fe4365bd88c6052d3 (contains squash c2fcc937). On all 9 pages, every application/ld+json block parses and none contains a raw <. The Person has jobTitle "Product Manager, Developer Experience at IFS" and LinkedIn in sameAs. Full report: #939 (comment)

This branch was successfully deployed

No deployments
sentinel-safe-json-ld-11881948995792762004 - astro-cloudflare-personal-website-web-service PR #1599 — 444f6f07 Deployed Oct 7, 2026 by alehar9320
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.

2 participants