Skip to content

Fix security vulnerabilities: update deps and harden code#81

Merged
koreyba merged 7 commits intomainfrom
claude/angry-golick
Apr 1, 2026
Merged

Fix security vulnerabilities: update deps and harden code#81
koreyba merged 7 commits intomainfrom
claude/angry-golick

Conversation

@koreyba
Copy link
Copy Markdown
Owner

@koreyba koreyba commented Apr 1, 2026

Summary

  • Update next (16.0.10→16.1.7), isomorphic-dompurify, markdown-it and add npm overrides for 14 transitive packages to resolve ~80 Dependabot alerts
  • Fix 10+ CodeQL code scanning alerts: XSS, property injection, ReDoS, bad HTML filtering regex, double-escaping
  • Pin all GitHub Actions to commit SHAs to prevent supply-chain attacks

Changes

Dependency updates (package.json)

  • next 16.0.10 → 16.1.7 (6 CVE: DoS, CSRF bypass, request smuggling)
  • isomorphic-dompurify 2.34.0 → 2.36.0 (dompurify mutation-XSS fix)
  • markdown-it 14.1.0 → 14.1.1 (ReDoS)
  • eslint-config-next + @next/eslint-plugin-next synced with next
  • overrides for: picomatch, brace-expansion, tar, flatted, serialize-javascript, js-yaml, yaml, qs, path-to-regexp, hono, @hono/node-server, express-rate-limit, dompurify, webpack, systeminformation

Code security fixes

  • app/editor-webview/page.tsx: origin check on postMessage handler + DOMPurify.sanitize before innerHTML
  • core/utils/editorWebViewBridge.ts: validate transferId (alphanumeric, max 200 chars) and chunk index bounds
  • core/services/sanitizer.ts: replace unreliable regex-based script/style stripping with two-pass DOMPurify using FORBID_CONTENTS
  • ui/mobile/utils/htmlToPlainText.ts: decode &amp; last to prevent double-decoding chain (&amp;lt;&lt;<)
  • core/enex/converter.ts: replace capturing groups with non-capturing (?:...) in regexes to reduce ReDoS surface
  • .github/workflows/: pin all actions to commit SHAs
  • .babelrc: move istanbul plugin to env.test (required for Next.js 16.1.7 Turbopack compat)

Remaining (non-critical, dev-only)

  • minimatch 3.1.2 in eslint — major breaking change, dev dependency only
  • @tootallnate/once, ajv — via jest-environment-jsdom, no prod impact

Test plan

  • npm run build passes
  • npm run test:unit — 28 suites, 299 tests pass
  • npm run type-check passes
  • npm audit — down to 6 low/moderate (all dev-only)
  • Manual: open note editor, import ENEX, export — verify basic flows work

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Security

    • Stronger HTML sanitization with stricter removal of scripts/styles and safer intermediate handling
    • Added origin/trust checks for inbound messages (allows file/same-origin; drops other non-trusted origins)
    • Hardened validation for chunked/transfer message streams
  • Bug Fixes

    • Fixed HTML entity decoding order to prevent double-decoding
    • Improved detection and normalization of empty paragraphs/content
  • Chores

    • Pinned CI action references and updated dependency/version constraints
    • Restricted test instrumentation to test runs only

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 1, 2026

Caution

Review failed

Pull request was closed or merged during review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 087204b6-7795-42ea-8fa2-9e7eac57f27d

📥 Commits

Reviewing files that changed from the base of the PR and between 137871c and a8c10e1.

📒 Files selected for processing (2)
  • app/editor-webview/page.tsx
  • core/enex/converter.ts

📝 Walkthrough

Walkthrough

Pinned CI action refs to commit SHAs, limited Babel's istanbul plugin to env.test, added HTML sanitization and origin checks in the editor webview, hardened chunked-message validation, refactored paragraph-trimming and entity-decoding order, and updated dependencies with transitive overrides.

Changes

Cohort / File(s) Summary
Build config & deps
\.babelrc, package.json
Moved istanbul plugin into env.test; bumped isomorphic-dompurify, markdown-it, next and Next ESLint packages; added top-level overrides to pin/raise transitive dependency versions.
GitHub workflows
.github/workflows/build.yml, .github/workflows/claude.yml
Replaced floating uses: refs with pinned commit SHAs for several actions; workflow logic and steps otherwise unchanged.
Editor webview security
app/editor-webview/page.tsx
Sanitize inbound HTML with DOMPurify before inserting into DOM; add isTrustedOrigin checks to ignore untrusted postMessage origins.
Sanitizer internals
core/services/sanitizer.ts
Replaced regex pre-strip with two-pass DOMPurify: first forbids script/style and contents, second removes all tags (ALLOWED_TAGS: []). Removed standalone helper.
Chunked-message validation
core/utils/editorWebViewBridge.ts
Added isValidTransferId guard (non-empty ≤200 chars, allowed [A-Za-z0-9_.-]); validate total and index ranges for _CHUNK_START, _CHUNK, and _CHUNK_END.
ENEX paragraph trimming
core/enex/converter.ts
Rewrote empty-<p> removal to iterative start/end trimming using emptyParagraph regex and isEmptyContent predicate; updated <p><br></p> normalization to callback-based replacement.
HTML entity decoding
ui/mobile/utils/htmlToPlainText.ts
Moved &amp;& decoding to the final stage to avoid premature/double-decoding.

Sequence Diagram(s)

mermaid
sequenceDiagram
participant WebView as WebView
participant Page as EditorWebViewPage
participant Bridge as WebViewBridge
participant Sanitizer as SanitizationService
WebView->>Page: postMessage(event)
Page->>Page: if event.origin present -> isTrustedOrigin(event.origin)?
alt origin not trusted
Page-->>WebView: ignore message
else origin trusted / not present
Page->>Page: extract data (event.data / nativeEvent?.data)
Page->>Page: parse JSON or consumeChunkedMessage
alt chunked message
Page->>Bridge: consumeChunkedMessage(payload)
Bridge->>Bridge: validate transferId, total, index
Bridge-->>Page: store/assemble chunks or reject
else content message
Page->>Sanitizer: stripHtml(html)
Sanitizer->>Sanitizer: DOMPurify (FORBID_TAGS/FORBID_CONTENTS)
Sanitizer->>Sanitizer: DOMPurify (ALLOWED_TAGS: [])
Sanitizer-->>Page: sanitizedText
Page-->>WebView: process sanitizedText
end

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main objectives of the pull request: fixing security vulnerabilities through both dependency updates and code hardening across multiple files.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/angry-golick

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 OpenGrep (1.16.5)
app/editor-webview/page.tsx

┌──────────────┐
│ Opengrep CLI │
└──────────────┘

�[32m✔�[39m �[1mOpengrep OSS�[0m
�[32m✔�[39m Basic security coverage for first-party code vulnerabilities.

�[1m Loading rules from local config...�[0m

core/enex/converter.ts

┌──────────────┐
│ Opengrep CLI │
└──────────────┘

�[32m✔�[39m �[1mOpengrep OSS�[0m
�[32m✔�[39m Basic security coverage for first-party code vulnerabilities.

�[1m Loading rules from local config...�[0m


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 and usage tips.

@cloudflare-workers-and-pages
Copy link
Copy Markdown

cloudflare-workers-and-pages bot commented Apr 1, 2026

Deploying everfreenote with  Cloudflare Pages  Cloudflare Pages

Latest commit: a8c10e1
Status: ✅  Deploy successful!
Preview URL: https://00002661.everfreenote.pages.dev
Branch Preview URL: https://claude-angry-golick.everfreenote.pages.dev

View logs

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (1)
core/services/sanitizer.ts (1)

27-34: Misleading comment about KEEP_CONTENT option.

The two-pass sanitization approach is correct and more robust than regex-based stripping. However, the comment on line 28 references KEEP_CONTENT: false, which is not a DOMPurify option being used here. The actual mechanism preventing content leakage is FORBID_CONTENTS, which is correctly configured on line 31.

📝 Suggested comment fix
-    // First pass: use DOMPurify to remove dangerous tags AND their content.
-    // KEEP_CONTENT: false ensures script/style inner text doesn't leak.
+    // First pass: use DOMPurify to remove dangerous tags AND their content.
+    // FORBID_CONTENTS ensures script/style inner text doesn't leak into output.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@core/services/sanitizer.ts` around lines 27 - 34, The comment above the
two-pass DOMPurify sanitization is misleading: replace the reference to the
non-existent KEEP_CONTENT option with the actual mechanism used,
FORBID_CONTENTS, and clarify that FORBID_TAGS plus FORBID_CONTENTS prevent
script/style inner text leakage; update the comment near the DOMPurify.sanitize
calls in sanitizer.ts (the block that creates `safe` and then strips tags) to
mention FORBID_CONTENTS rather than KEEP_CONTENT.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/build.yml:
- Line 31: The workflow uses mismatched pinned action refs: update the three
action pins so the commit SHAs match the claimed versions (or adjust claimed
versions to match the SHAs). Specifically, for actions/checkout (currently
"actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 // v4"), replace the
SHA with the correct v4 commit or change the tag to a valid v4 ref; for
denoland/setup-deno (currently pinned to a SHA but claims v2.0.4), either set
the SHA that corresponds to v2.0.3 (the actual latest release) or change the
claimed version to the SHA’s real release; and for gitleaks/gitleaks-action
(currently pinned to a SHA while claiming v2), swap in the correct commit SHA
for the v2 release or update the version label to the SHA’s actual release.
Ensure each updated reference uses the canonical commit SHA that matches the
named version tag so the action pin and claimed version are consistent.

In @.github/workflows/claude.yml:
- Line 29: The workflow uses pinned SHAs for actions that are
unverifiable/outdated; update the action references to use current released
semantic tags or verified SHAs: replace
actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 with the official
release tag (e.g., actions/checkout@v4 or a verified v4.x.y SHA) and replace
anthropics/claude-code-action@e69ec4d5e5868930cecb8da7360a51fa9c4de5d6 with the
published tag (e.g., anthropics/claude-code-action@v1 or a verified v1.x.y SHA);
ensure you reference the official GitHub release/commit for each action before
updating to confirm the SHA matches the public source.

In `@core/enex/converter.ts`:
- Around line 165-170: The chained string.replace calls using the regexes like
/^(?:\s*<p[^>]*>(?:\s|&nbsp;|&hairsp;|&#8202;|<br\s*\/?>)*<\/p>\s*)+/gi and
/(?:\s*<p[^>]*>(?:\s|&nbsp;|&hairsp;|&#8202;|<br\s*\/?>)*<\/p>\s*)+$/gi are
vulnerable to ReDoS; replace this whole regex-based cleanup with DOM parsing:
parse the ENML/HTML into a DOM (via DOMParser or isomorphic-dompurify’s
parse/sanitize facility), walk the document to remove leading/trailing empty <p>
nodes (where "empty" means only whitespace, nbsp entities or <br> children) and
normalize <p>...</p> that contain only optional whitespace and a single <br> to
<p></p>, then serialize the DOM back to a string; remove the string.replace
chain in converter.ts and implement the DOM-based logic so the three
transformations (remove leading empty <p>, remove trailing empty <p>, normalize
empty paragraphs) are done deterministically without regex backtracking.

---

Nitpick comments:
In `@core/services/sanitizer.ts`:
- Around line 27-34: The comment above the two-pass DOMPurify sanitization is
misleading: replace the reference to the non-existent KEEP_CONTENT option with
the actual mechanism used, FORBID_CONTENTS, and clarify that FORBID_TAGS plus
FORBID_CONTENTS prevent script/style inner text leakage; update the comment near
the DOMPurify.sanitize calls in sanitizer.ts (the block that creates `safe` and
then strips tags) to mention FORBID_CONTENTS rather than KEEP_CONTENT.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 6fede441-9ee5-411f-9097-c1ec58729590

📥 Commits

Reviewing files that changed from the base of the PR and between 83b04f8 and 6898a69.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (9)
  • .babelrc
  • .github/workflows/build.yml
  • .github/workflows/claude.yml
  • app/editor-webview/page.tsx
  • core/enex/converter.ts
  • core/services/sanitizer.ts
  • core/utils/editorWebViewBridge.ts
  • package.json
  • ui/mobile/utils/htmlToPlainText.ts

koreyba and others added 4 commits April 1, 2026 16:13
Update next (16.0.10→16.1.7), isomorphic-dompurify, markdown-it and
add npm overrides for 14 transitive packages (hono, tar, flatted,
serialize-javascript, dompurify, etc.) to resolve ~80 Dependabot alerts.

Code fixes for CodeQL alerts:
- editor-webview: add postMessage origin check and DOMPurify sanitize
  before innerHTML usage
- editorWebViewBridge: validate transferId format and chunk index range
  to prevent property injection
- sanitizer: replace regex-based script/style stripping with two-pass
  DOMPurify (FORBID_CONTENTS + ALLOWED_TAGS:[])
- htmlToPlainText: decode &amp; last to prevent double-escaping
- ENEX converter: use non-capturing groups in regexes to reduce ReDoS risk
- GitHub Actions: pin all actions to commit SHAs
- .babelrc: move istanbul plugin to test env only (required for Next.js
  16.1.7 Turbopack compatibility)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
gitleaks-action and claude-code-action use annotated tags — the
previous SHAs pointed to tag objects, not commits, which prevented
the Build workflow from running.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The nested quantifiers in removeEmptyParagraphs regex caused CodeQL
to flag exponential backtracking. Replace with an iterative loop that
matches one paragraph at a time, avoiding nested repetition entirely.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
core/utils/editorWebViewBridge.ts (1)

57-82: ⚠️ Potential issue | 🟠 Major

Don't keep or commit partial chunk transfers.

Line 80 joins sparse arrays, so a missing chunk is silently treated as '' and truncated payloads are accepted as complete. Separately, started transfers never expire, so a long-lived store can grow without bound if a sender starts transfers and never reaches _CHUNK_END. Reject incomplete buffers on finalize and add TTL / max-outstanding cleanup for abandoned entries.

Minimal guard for incomplete `_CHUNK_END` payloads
   if (type.endsWith(CHUNK_END_SUFFIX)) {
     const p = payload as Partial<ChunkEndPayload>
     if (!isValidTransferId(p.transferId)) return null
     const entry = store[p.transferId]
     if (!entry) return null
+    for (let index = 0; index < entry.total; index += 1) {
+      if (typeof entry.chunks[index] !== 'string') {
+        delete store[p.transferId]
+        return null
+      }
+    }
     const text = entry.chunks.join('')
     delete store[p.transferId]
     return { baseType, text }
   }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@core/utils/editorWebViewBridge.ts` around lines 57 - 82, The CHUNK handling
currently accepts incomplete transfers (line joining sparse arrays) and never
cleans up abandoned starts; update the chunk lifecycle in
editorWebViewBridge.ts: when handling CHUNK_START_SUFFIX in the store entry add
metadata (createdAt timestamp and expected total), enforce a global
maxOutstandingTransfers limit and reject new starts when exceeded, and schedule
or run a periodic cleanup that deletes entries older than TTL (e.g., createdAt +
TTL) to prevent unbounded growth; when handling CHUNK_SUFFIX validate and record
received indexes (or mark holes) and on CHUNK_END_SUFFIX ensure all entry.chunks
indexes 0..total-1 are present (no undefined holes) before joining — if any
missing, delete the entry and return null (reject finalize); reference the
symbols CHUNK_START_SUFFIX, CHUNK_SUFFIX, CHUNK_END_SUFFIX, store,
isValidTransferId and the handler that returns { baseType, text } so you
implement the TTL, maxOutstandingTransfers, hole detection, and deletion on
failure.
app/editor-webview/page.tsx (1)

71-76: ⚠️ Potential issue | 🔴 Critical

Sanitize before the early return.

Line 73 returns the raw HTML when neither rewrite knob is configured, so the DOMPurify hardening only runs on the image-rewrite path. In the default/no-rewrite case, SET_CONTENT can still feed unsanitized HTML into the editor.

Minimal fix
     const { devHost, supabaseUrl } = getMobileConfig()
     const supabaseOrigin = normalizeOrigin(supabaseUrl)
-    if (!devHost && !supabaseOrigin) return html
+    const sanitized = DOMPurify.sanitize(html)
+    if (!devHost && !supabaseOrigin) return sanitized
 
     const container = document.createElement('div')
-    container.innerHTML = DOMPurify.sanitize(html)
+    container.innerHTML = sanitized
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/editor-webview/page.tsx` around lines 71 - 76, The current early return
returns the raw html without sanitization; move the DOMPurify.sanitize call
before the devHost/supabaseOrigin check so you always sanitize the input.
Specifically, call DOMPurify.sanitize(html) into a sanitizedHtml variable before
evaluating getMobileConfig()/normalizeOrigin(), use sanitizedHtml for the early
return (instead of raw html) and for container.innerHTML, and keep references to
devHost, supabaseOrigin, container, and DOMPurify consistent (so functions like
getMobileConfig and normalizeOrigin remain unchanged).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@core/enex/converter.ts`:
- Around line 193-199: The outer html.replace call (the regex used in
html.replace at the top of the block) only matches when the last token before
</p> is a <br>, so cases like <p>&nbsp;<br>&nbsp;</p> are skipped; update that
outer regex (the first argument to html.replace) to allow optional trailing
whitespace/entities after the final <br> before </p> (mirroring the inner test
that allows (?:\s|&nbsp;|&hairsp;|&#8202;)* around <br\s*\/?>), or alternatively
loosen the outer match to capture any <p...>...</p> and rely on the existing
inner replacement callback and its inner regex to decide whether to return an
empty <p${attrs}></p> for strings containing only whitespace/entities and <br>s;
apply this change to the html.replace call and keep the inner test (the inner
regex and callback) unchanged.

---

Outside diff comments:
In `@app/editor-webview/page.tsx`:
- Around line 71-76: The current early return returns the raw html without
sanitization; move the DOMPurify.sanitize call before the devHost/supabaseOrigin
check so you always sanitize the input. Specifically, call
DOMPurify.sanitize(html) into a sanitizedHtml variable before evaluating
getMobileConfig()/normalizeOrigin(), use sanitizedHtml for the early return
(instead of raw html) and for container.innerHTML, and keep references to
devHost, supabaseOrigin, container, and DOMPurify consistent (so functions like
getMobileConfig and normalizeOrigin remain unchanged).

In `@core/utils/editorWebViewBridge.ts`:
- Around line 57-82: The CHUNK handling currently accepts incomplete transfers
(line joining sparse arrays) and never cleans up abandoned starts; update the
chunk lifecycle in editorWebViewBridge.ts: when handling CHUNK_START_SUFFIX in
the store entry add metadata (createdAt timestamp and expected total), enforce a
global maxOutstandingTransfers limit and reject new starts when exceeded, and
schedule or run a periodic cleanup that deletes entries older than TTL (e.g.,
createdAt + TTL) to prevent unbounded growth; when handling CHUNK_SUFFIX
validate and record received indexes (or mark holes) and on CHUNK_END_SUFFIX
ensure all entry.chunks indexes 0..total-1 are present (no undefined holes)
before joining — if any missing, delete the entry and return null (reject
finalize); reference the symbols CHUNK_START_SUFFIX, CHUNK_SUFFIX,
CHUNK_END_SUFFIX, store, isValidTransferId and the handler that returns {
baseType, text } so you implement the TTL, maxOutstandingTransfers, hole
detection, and deletion on failure.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: ace91f69-ce0a-4414-b3d3-7e8b5eb9a6a5

📥 Commits

Reviewing files that changed from the base of the PR and between afe8272 and 137871c.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (9)
  • .babelrc
  • .github/workflows/build.yml
  • .github/workflows/claude.yml
  • app/editor-webview/page.tsx
  • core/enex/converter.ts
  • core/services/sanitizer.ts
  • core/utils/editorWebViewBridge.ts
  • package.json
  • ui/mobile/utils/htmlToPlainText.ts
✅ Files skipped from review due to trivial changes (4)
  • .babelrc
  • ui/mobile/utils/htmlToPlainText.ts
  • .github/workflows/build.yml
  • .github/workflows/claude.yml
🚧 Files skipped from review as they are similar to previous changes (2)
  • core/services/sanitizer.ts
  • package.json

Replace /^\s*/ and /\s*$/ regex patterns with native trimStart()/trimEnd()
to eliminate potential backtracking-based DoS flagged by SonarCloud.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix outer regex to allow trailing whitespace/entities after <br>:
  (?:[^<]*<br>)* → (?:[^<]|<br>)* so <p>&nbsp;<br>&nbsp;</p> is matched
- Use replaceAll() instead of replace() per SonarCloud recommendation

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- startsWith() instead of indexOf() !== 0
- replaceAll() instead of replace() for regex replacements
- .at(-1) instead of [arr.length - 1]
- globalThis instead of window

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud bot commented Apr 1, 2026

@koreyba koreyba merged commit 9873a8f into main Apr 1, 2026
14 of 15 checks passed
@koreyba koreyba deleted the claude/angry-golick branch April 1, 2026 18:41
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