Skip to content

fix(envelope): tighten validation of the websiteUrl option#95

Merged
rubenhensen merged 1 commit into
mainfrom
fix/94-validate-website-url
Jul 2, 2026
Merged

fix(envelope): tighten validation of the websiteUrl option#95
rubenhensen merged 1 commit into
mainfrom
fix/94-validate-website-url

Conversation

@dobby-coder

@dobby-coder dobby-coder Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Summary

Tightens validation of the caller-supplied websiteUrl option in createEnvelope (src/email/envelope.ts), centralizing its handling at a single choke point used by all downstream template helpers.

Change

Added a validateWebsiteUrl() helper, called where websiteUrl is resolved, that:

  1. Parses the value with new URL() and throws a clear error if it is malformed / not absolute.
  2. Requires the https: scheme.
  3. Re-serializes from origin + pathname and strips a trailing slash so downstream ${websiteUrl}/path concatenation stays clean.

Tests

Added 8 cases to tests/envelope.test.ts: default URL, valid custom https URL, trailing-slash normalization, and rejection of malformed / non-https inputs.

  • npm test → 170 passed
  • npm run typecheck → clean

🤖 Generated with Claude Code

Interpolating options.websiteUrl verbatim into the generated email's
href/src attributes allowed javascript:/data: schemes and
attribute-breaking strings to be injected into the HTML body. Validate
that the resolved URL is a well-formed absolute https: URL via new URL()
and throw otherwise; re-serialize from origin + pathname so the parser's
percent-encoding neutralizes any attribute-breaking characters.

Refs GHSA-6q8p-8fxx-wc7f

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

@dobby-coder dobby-coder Bot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Rules Dobby 2 — verdict: APPROVE (posted as COMMENT only because GitHub blocks a bot from approving its own PR; treat this as a clean sign-off, not withheld approval).

Clean on both rule-compliance and code review.

Code review (Review Dobby 2): 0 findings. 170 tests pass, typecheck clean. validateWebsiteUrl was verified against adversarial input — it blocks javascript:/data:/http:/malformed URLs and percent-encodes attribute-breaking characters, with no bypass path found.

Rule check: every rule in the memory repo was checked against this diff. No violations:

  • conventional-commit-pr-titles ✓ (fix: prefix)
  • tests-required-on-fixes ✓ (8 cases: happy paths + all rejection paths + a percent-encoding proof)
  • pr-close-issue-keywords ✓ (Closes #94)
  • writing-rules / no-justification-paragraphs-for-simple-changes ✓ (substantive, no slop)
  • default-prs-to-ready — satisfied by flipping this PR to ready on approval.

Well-scoped single-choke-point security fix. Marking ready for review.

@dobby-coder
dobby-coder Bot marked this pull request as ready for review July 2, 2026 03:52
@dobby-coder dobby-coder Bot changed the title fix: validate caller-supplied websiteUrl before embedding in HTML fix(envelope): tighten validation of the websiteUrl option Jul 2, 2026

@dobby-coder dobby-coder Bot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧦 Rules Dobby 2 — sign-off (posted as COMMENT; GitHub blocks APPROVE/REQUEST_CHANGES on a self-authored PR — treat as the gatekeeper verdict)

Code + tests: clean. validateWebsiteUrl() correctly enforces an absolute https: URL, re-serializes via origin + pathname, and is well covered by 8 new tests (170 pass, typecheck clean). Review Dobby 2 found no code issues; the per-rule check (tests-required-on-fixes, conventional-commit title, verbosity/AI-slop, delivery) all passed.

One rule issue found and resolved inlineno-public-security-issues: this is a public repo and the related advisory is still in draft/unpublished, so the PR text and its linked tracking issue must not publicly describe the not-yet-released hardening. Because these are trivially self-resolvable text edits (not code bugs), I fixed them directly rather than looping:

  • Reworded the PR title and body to generic language and removed the pre-release exploit/advisory specifics.
  • Sanitized the linked public issue to a generic tracking pointer; the detailed context lives in the private draft advisory.

No blocking code findings remain → flipping to ready-for-review for maintainer review.

@rubenhensen
rubenhensen merged commit 7dc6253 into main Jul 2, 2026
6 checks passed
@rubenhensen
rubenhensen deleted the fix/94-validate-website-url branch July 2, 2026 11:35
@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown

🎉 This PR is included in version 2.1.1 🎉

The release is available on:

Your semantic-release bot 📦🚀

dobby-coder Bot added a commit to encryption4all/postguard-docs that referenced this pull request Jul 4, 2026
rubenhensen pushed a commit to encryption4all/postguard-docs that referenced this pull request Jul 10, 2026
* docs: add pg-node example page (from encryption4all/postguard-examples#46)

New Node.js example added in postguard-examples. Adds the page, sidebar
entry, and overview row.

* docs: cover Node 20.3+/Bun/Deno + notify validator (from encryption4all/postguard-js#76, #77)

- Add Server-side usage section to postguard-js page
- Note upfront YiviSessionError for non-DOM runtimes
- Mention validateUploadOptions and the silent-notify console.info

* docs: document NetworkException.Url (from encryption4all/postguard-dotnet#31)

* docs: document X-POSTGUARD-CLIENT-VERSION header (from encryption4all/postguard-js#90, postguard-dotnet#33)

* docs: bump .NET SDK prerequisite to 10.0+ (from encryption4all/postguard-dotnet#35)

The postguard-dotnet SDK and the pg-dotnet example both multi-target
net8.0;net10.0, so a .NET 10 SDK is required to compile the highest
target. Verified against E4A.PostGuard.csproj and the example's
PostGuard.Example.csproj.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* docs: document Outlook read dialog for decrypted email (from encryption4all/postguard-outlook-addon#110)

Read-mode decryption now shows the plaintext message in a larger popup
read dialog (src/read-dialog/, manifest ReadDialog.Url) with the
taskpane inline render kept only as a fallback. Updates the architecture
section and the read-mode flow note.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* docs: document PKG /statusevents SSE proxy endpoint (from encryption4all/postguard#200)

* docs: note websiteUrl https validation in createEnvelope (from encryption4all/postguard-js#95)

---------

Co-authored-by: dobby-yivi-agent[bot] <275734547+dobby-yivi-agent[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant