Skip to content

Security hardening: CI permissions, dependency overrides, error handling#15

Merged
finallyjay merged 1 commit into
mainfrom
security-hardening
Jun 15, 2026
Merged

Security hardening: CI permissions, dependency overrides, error handling#15
finallyjay merged 1 commit into
mainfrom
security-hardening

Conversation

@finallyjay

@finallyjay finallyjay commented Jun 15, 2026

Copy link
Copy Markdown
Owner

Resolves the open CodeQL warnings and Dependabot advisories surfaced in the repo review.

CodeQL

  • actions/missing-workflow-permissions — added least-privilege permissions: { contents: read } to ci.yml.
  • js/stack-trace-exposure (x2)bookmarks/index.ts and bookmarks/[id].ts no longer return String(err) to the client; errors are logged server-side and a generic message is returned.

Dependabot (transitive)

Added overrides to force patched versions without downgrading Astro:

  • esbuild^0.28.1 (high + low advisories)
  • path-to-regexp^6.3.0 (high — ReDoS)

npm audit now reports 0 vulnerabilities.

Verification

  • npm run lint (oxlint)
  • npm run format:check (oxfmt)
  • npm run build
  • npm audit → 0 vulnerabilities

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Chores

    • Updated CI workflow permissions configuration
    • Pinned dependency versions for esbuild and path-to-regexp
  • Bug Fixes

    • Improved error handling in bookmark API endpoints with consistent error messaging for failed operations

- ci.yml: add least-privilege `permissions: contents: read`
  (fixes CodeQL actions/missing-workflow-permissions)
- package.json: override esbuild ^0.28.1 and path-to-regexp ^6.3.0
  to clear 3 transitive Dependabot advisories (npm audit: 0 vulns)
- bookmarks API: stop returning raw error strings to clients;
  log server-side and return generic messages
  (fixes CodeQL js/stack-trace-exposure x2)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@vercel

vercel Bot commented Jun 15, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
daily-dev-roulette Ready Ready Preview, Comment Jun 15, 2026 9:49am

@coderabbitai

coderabbitai Bot commented Jun 15, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Two independent hardening efforts: bookmark API routes replace raw String(err) error serialization with fixed 502 messages and add structured logging; CI workflow gains explicit least-privilege token permissions; package.json pins esbuild and path-to-regexp via an overrides block.

Changes

API Error Response Hardening

Layer / File(s) Summary
Bookmark API catch blocks: fixed messages + logging
src/pages/api/bookmarks/[id].ts, src/pages/api/bookmarks/index.ts
DELETE route replaces String(err) in the 502 body with "Failed to delete bookmark". GET list route adds console.error("[bookmarks:list] ", err) and returns "Failed to load bookmarks" instead of String(err).

CI and Dependency Security Hardening

Layer / File(s) Summary
CI token permissions + transitive dependency pins
.github/workflows/ci.yml, package.json
Workflow adds permissions: contents: read to restrict the default GITHUB_TOKEN. package.json adds an overrides block pinning esbuild to ^0.28.1 and path-to-regexp to ^6.3.0.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~4 minutes

Poem

🐇 A rabbit tidied up the burrow one day,
Swapped leaky errors for safe words to say,
Locked the CI gate with a contents-read key,
Pinned the deps so supply chains run free.
No secrets escape — just tidy, hop-hop hooray! 🌿

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly and concisely summarizes the three main changes: CI permissions hardening, dependency override enforcement, and error handling improvements.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.

✏️ 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 security-hardening

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@package.json`:
- Around line 30-33: Update the path-to-regexp override version in the overrides
object from ^6.3.0 to ^8.4.0 to address the critical ReDoS security
vulnerabilities. This involves changing only the version string value for the
path-to-regexp field while keeping the esbuild override unchanged.

In `@src/pages/api/bookmarks/index.ts`:
- Line 18: Both API routes have JSON error responses that omit the Content-Type
header, while the success response in index.ts line 14 includes it. In
src/pages/api/bookmarks/index.ts at line 18, add headers: { "Content-Type":
"application/json" } to the 502 error Response constructor. In
src/pages/api/bookmarks/[id].ts at line 18, do the same for the 502 error
response. Match the header format used in the success response on line 14 of
index.ts to ensure consistency across all API responses.
- Around line 17-18: The error response in the bookmarks list handler is missing
the Content-Type header that is present in the success response. Modify the
Response object returned in the console.error error handling block to include a
headers object with Content-Type set to application/json in the second parameter
of the Response constructor, matching the format used in the success response
above it.
- Around line 17-18: The catch block in the bookmarks list endpoint currently
returns HTTP 502 for all errors from listAllBookmarks, but this masks client
errors (4xx) from the upstream API. Modify the error handling to inspect the
error response and extract the actual HTTP status code from the upstream API
response. Return the appropriate status code to the client—such as 401 for
authentication failures, 403 for forbidden, 404 for not found, and other 4xx
codes as-is, while only returning 500 or 502 for actual server-side errors. This
ensures clients receive semantically correct HTTP status codes that reflect the
actual problem.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: a3af4841-36ed-479c-8e0f-e58a5ad342c9

📥 Commits

Reviewing files that changed from the base of the PR and between 095d113 and 3717d47.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (4)
  • .github/workflows/ci.yml
  • package.json
  • src/pages/api/bookmarks/[id].ts
  • src/pages/api/bookmarks/index.ts

Comment thread package.json
Comment on lines +30 to 33
"overrides": {
"esbuild": "^0.28.1",
"path-to-regexp": "^6.3.0"
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🌐 Web query:

What are the latest patched versions of esbuild and path-to-regexp that fix known security vulnerabilities as of June 2026?

💡 Result:

As of June 15, 2026, the latest patched versions for esbuild and path-to-regexp are as follows: esbuild: The latest patched version is 0.28.1 [1]. This release addresses two security vulnerabilities published in June 2026: - Arbitrary file read on Windows: A path traversal vulnerability in the development server (GHSA-g7r4-m6w7-qqqr), where HTTP requests could access files outside the serve directory using backslash characters [2][1]. - Deno API integrity check: A vulnerability related to missing binary integrity verification in the Deno module (GHSA-gv7w-rqvm-qjhr), which could enable remote code execution via the NPM_CONFIG_REGISTRY [1][3][4]. path-to-regexp: The latest patched version is 8.4.0 [5]. This release addresses multiple Regular Expression Denial of Service (ReDoS) vulnerabilities [6]: - CVE-2026-4926: Vulnerability caused by sequential optional groups [7][6]. - CVE-2026-4923: Vulnerability caused by multiple wildcards [8][6]. - CVE-2026-4867: Vulnerability caused by multiple route parameters within a single segment [9][6]. Users are encouraged to upgrade to these versions (or later) to ensure their applications are protected against these known security issues [1][6].

Citations:


🏁 Script executed:

#!/bin/bash
# Description: Check Astro's esbuild peer dependency requirements

# Search for esbuild version constraints in Astro and its adapters
rg -nP --type=json '"esbuild":\s*"' package-lock.json | head -20

# Check if Astro 6.4.5 or `@astrojs/vercel` 10.0.8 have specific esbuild requirements
echo "=== Astro dependency tree for esbuild ==="
npm ls esbuild 2>/dev/null || echo "Check manually: does Astro 6.4.5 require a specific esbuild range?"

Repository: finallyjay/daily-dev-roulette

Length of output: 381


Upgrade path-to-regexp override to ^8.4.0 to address June 2026 security vulnerabilities.

The esbuild override at ^0.28.1 is correct and matches the latest patched version. However, path-to-regexp ^6.3.0 is significantly outdated. As of June 2026, the latest patched version is 8.4.0, which fixes three critical ReDoS vulnerabilities (CVE-2026-4926, CVE-2026-4923, CVE-2026-4867) that the ^6.3.0 version does not address. Update the override:

"path-to-regexp": "^8.4.0"
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@package.json` around lines 30 - 33, Update the path-to-regexp override
version in the overrides object from ^6.3.0 to ^8.4.0 to address the critical
ReDoS security vulnerabilities. This involves changing only the version string
value for the path-to-regexp field while keeping the esbuild override unchanged.

Comment on lines +17 to +18
console.error("[bookmarks:list] ", err);
return new Response(JSON.stringify({ error: "Failed to load bookmarks" }), { status: 502 });

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add Content-Type header to error response for consistency.

The success response at line 14 explicitly sets Content-Type: application/json, but the error response at line 18 omits it. This inconsistency could cause issues with strict HTTP clients. Since the response body is JSON, the header should be present.

📋 Proposed fix to add Content-Type header
-    return new Response(JSON.stringify({ error: "Failed to load bookmarks" }), { status: 502 });
+    return new Response(JSON.stringify({ error: "Failed to load bookmarks" }), { 
+      status: 502,
+      headers: { "Content-Type": "application/json" }
+    });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
console.error("[bookmarks:list] ", err);
return new Response(JSON.stringify({ error: "Failed to load bookmarks" }), { status: 502 });
console.error("[bookmarks:list] ", err);
return new Response(JSON.stringify({ error: "Failed to load bookmarks" }), {
status: 502,
headers: { "Content-Type": "application/json" }
});
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/pages/api/bookmarks/index.ts` around lines 17 - 18, The error response in
the bookmarks list handler is missing the Content-Type header that is present in
the success response. Modify the Response object returned in the console.error
error handling block to include a headers object with Content-Type set to
application/json in the second parameter of the Response constructor, matching
the format used in the success response above it.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Examine the implementation of listAllBookmarks to understand error types

# Find the implementation of listAllBookmarks
ast-grep --pattern $'export function listAllBookmarks($$$) {
  $$$
}'

# Also search for error handling patterns in lib/daily.ts
rg -n "throw|Error" src/lib/daily.ts -C3

Repository: finallyjay/daily-dev-roulette

Length of output: 1088


🏁 Script executed:

# Search for listAllBookmarks definition and usage
rg -n "listAllBookmarks" -A 10 -B 2

Repository: finallyjay/daily-dev-roulette

Length of output: 2345


🏁 Script executed:

# Get the full implementation of listAllBookmarks
rg -n "export async function listAllBookmarks" -A 30 src/lib/daily.ts

Repository: finallyjay/daily-dev-roulette

Length of output: 1257


🏁 Script executed:

# Get the full implementation of listBookmarks to see all error sources
rg -n "export async function listBookmarks" -A 20 src/lib/daily.ts

Repository: finallyjay/daily-dev-roulette

Length of output: 991


Verify that HTTP 502 is appropriate for all error types.

The catch block returns HTTP 502 (Bad Gateway) for all errors from listAllBookmarks, but this status code is inappropriate when the upstream daily.dev API returns client errors (4xx). If the API returns 401 (token expired), 403 (forbidden), 404, or other 4xx responses, those should not be masked as 502 to the client. Consider inspecting the error message or response status and returning semantically correct codes (e.g., 401 for auth failures, 500 for actual server errors).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/pages/api/bookmarks/index.ts` around lines 17 - 18, The catch block in
the bookmarks list endpoint currently returns HTTP 502 for all errors from
listAllBookmarks, but this masks client errors (4xx) from the upstream API.
Modify the error handling to inspect the error response and extract the actual
HTTP status code from the upstream API response. Return the appropriate status
code to the client—such as 401 for authentication failures, 403 for forbidden,
404 for not found, and other 4xx codes as-is, while only returning 500 or 502
for actual server-side errors. This ensures clients receive semantically correct
HTTP status codes that reflect the actual problem.

} catch (err) {
return new Response(JSON.stringify({ error: String(err) }), { status: 502 });
console.error("[bookmarks:list] ", err);
return new Response(JSON.stringify({ error: "Failed to load bookmarks" }), { status: 502 });

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

JSON error responses missing Content-Type header in both API routes.

Both bookmark API routes return JSON error payloads but omit the Content-Type: application/json header, while the success response in index.ts (line 14) includes it. This inconsistency could cause issues with strict HTTP clients.

  • src/pages/api/bookmarks/index.ts#L18: Add headers: { "Content-Type": "application/json" } to the 502 error response
  • src/pages/api/bookmarks/[id].ts#L18: Add headers: { "Content-Type": "application/json" } to the 502 error response
📍 Affects 2 files
  • src/pages/api/bookmarks/index.ts#L18-L18 (this comment)
  • src/pages/api/bookmarks/[id].ts#L18-L18
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/pages/api/bookmarks/index.ts` at line 18, Both API routes have JSON error
responses that omit the Content-Type header, while the success response in
index.ts line 14 includes it. In src/pages/api/bookmarks/index.ts at line 18,
add headers: { "Content-Type": "application/json" } to the 502 error Response
constructor. In src/pages/api/bookmarks/[id].ts at line 18, do the same for the
502 error response. Match the header format used in the success response on line
14 of index.ts to ensure consistency across all API responses.

@finallyjay finallyjay merged commit ca01e0a into main Jun 15, 2026
7 checks passed
@finallyjay finallyjay deleted the security-hardening branch June 15, 2026 10:19
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.

1 participant