Skip to content

fix: apply all the deepsec recommendations for security fixes#88

Merged
nikilok merged 2 commits intomainfrom
feat/deepsec
May 4, 2026
Merged

fix: apply all the deepsec recommendations for security fixes#88
nikilok merged 2 commits intomainfrom
feat/deepsec

Conversation

@nikilok
Copy link
Copy Markdown
Owner

@nikilok nikilok commented May 4, 2026

Summary by CodeRabbit

  • New Features

    • Added DeepSec security scanning workspace for automated vulnerability detection and analysis.
  • Bug Fixes

    • Enhanced secret validation to ensure non-empty values before processing.
    • Updated CSV row deduplication logic for improved accuracy.
  • Documentation

    • Added comprehensive setup and usage guides for the scanning workspace.
  • Chores

    • Pinned Bun container image and GitHub Actions versions for consistency.

@vercel
Copy link
Copy Markdown

vercel Bot commented May 4, 2026

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

Project Deployment Actions Updated (UTC)
learn-tanstack-start Ready Ready Preview, Comment May 4, 2026 11:03pm

Request Review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 4, 2026

Warning

Rate limit exceeded

@nikilok has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 12 minutes and 48 seconds before requesting another review.

To keep reviews running without waiting, you can enable usage-based add-on for your organization. This allows additional reviews beyond the hourly cap. Account admins can enable it under billing.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 13325dec-5c43-4378-b535-a09390f144b8

📥 Commits

Reviewing files that changed from the base of the PR and between eee30c6 and 0b2d839.

📒 Files selected for processing (1)
  • .deepsec/data/learn-tanstack-start/INFO.md
📝 Walkthrough

Walkthrough

This PR introduces a DeepSec security scanning workspace and makes targeted infrastructure and security improvements: adding deepsec configuration files, documentation, and per-project setup guides; pinning Bun action and Docker image to specific versions; and updating CSV hash fingerprinting and secret validation logic.

Changes

DeepSec Workspace Integration

Layer / File(s) Summary
Configuration & Setup
.deepsec/package.json, .deepsec/deepsec.config.ts, .deepsec/.gitignore, .deepsec/pnpm-workspace.yaml
Package.json defines private ESM workspace with deepsec ^1.1.11 dependency; deepsec.config.ts configures the learn-tanstack-start project; .gitignore excludes node_modules/, .env*.local, and scan output under data/*/; pnpm-workspace.yaml declares empty packages list.
Documentation
.deepsec/README.md, .deepsec/AGENTS.md
README.md provides setup, daily commands, project-id selection, and directory layout; AGENTS.md documents common tasks and references deepsec skill docs.
Per-Project Setup
.deepsec/data/learn-tanstack-start/INFO.md, .deepsec/data/learn-tanstack-start/SETUP.md
INFO.md defines scan instruction template with sections for codebase overview, auth primitives, threat model, project-specific patterns, and known false-positives (excluding command injection due to use of fetch() and Bun primitives); SETUP.md provides step-by-step agent initialization workflow.

Security & Infrastructure Hardening

Layer / File(s) Summary
CI Action Pinning
.github/actions/run-phase5-sweep/action.yaml
Bun setup action reference pinned from floating v2 tag to specific commit SHA (v2.2.0).
Container Image Pinning
apps/ch-stream/Dockerfile
Bun base image pinned from tag-only to digest-based reference; container now runs as bun user before workdir and cmd.
Secret Validation
apps/web/server/utils/withSecret.ts
Handler invocation now requires both timing-safe equality check and non-empty expected.length gate, preventing execution when REVALIDATE_SECRET is unset.
CSV Fingerprinting
apps/web/scripts/ingest-hmrc-csv.ts
Hash fingerprinting switched from pipe-delimited string concatenation to JSON-serialized array (with normalized null fields as empty strings) for consistent deduplication.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 A scanning workspace hops in today,
With secrets locked tight in a safer way,
Digests pinned firm, no floating about,
Hash strings to JSON—no more doubt!
DeepSec arrives to sniff out the flaws! 🔍

🚥 Pre-merge checks | ✅ 4 | ❌ 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 (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix: apply all the deepsec recommendations for security fixes' clearly summarizes the main objective of the changeset, which is to implement security-related recommendations from a DeepSec analysis tool across multiple files.
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 unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/deepsec

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.

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: 4

🧹 Nitpick comments (1)
apps/web/server/utils/withSecret.ts (1)

11-14: 💤 Low value

Consider hashing to fixed length to prevent timing leakage on secret length.

The a.length === b.length check is necessary (since timingSafeEqual throws on length mismatch), but it can leak information about the expected secret's length through response timing. For defense-in-depth, hash both values to a fixed length before comparison.

🔐 Optional: constant-time length comparison via hashing
+import { createHash, timingSafeEqual } from 'node:crypto';
-import { timingSafeEqual } from 'node:crypto';
 import { defineEventHandler } from 'h3';
 
 export function withSecret(
   handler: () => void,
 ): ReturnType<typeof defineEventHandler> {
   return defineEventHandler((event) => {
     event.res.status = 202;
     const secret = event.req.headers.get('x-revalidate-secret') ?? '';
     const expected = process.env.REVALIDATE_SECRET ?? '';
-    const a = Buffer.from(secret);
-    const b = Buffer.from(expected);
-    const equal = a.length === b.length && timingSafeEqual(a, b);
+    const a = createHash('sha256').update(secret).digest();
+    const b = createHash('sha256').update(expected).digest();
+    const equal = timingSafeEqual(a, b);
     if (equal && expected.length > 0) {
       handler();
     }
     return { accepted: true };
   });
 }
🤖 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 `@apps/web/server/utils/withSecret.ts` around lines 11 - 14, The current
compare uses Buffer.from(secret)/Buffer.from(expected) and a.length === b.length
with timingSafeEqual, which leaks the expected secret length; instead, in
withSecret compute fixed-length hashes (e.g., SHA-256) of both secret and
expected using crypto.createHash and convert those digests to Buffers, then call
timingSafeEqual on the two fixed-size hash buffers (remove the a.length ===
b.length pre-check), and keep the existing expected.length > 0 guard or replace
it with a check against the raw expected being non-empty before hashing; update
references to a, b and equal to use the hashed buffers and the new
timingSafeEqual comparison.
🤖 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 @.deepsec/AGENTS.md:
- Around line 21-23: Update the install command in the text that reads "pnpm
install" to "bun install" so it matches README.md and the pinned Bun CI action;
specifically replace the literal string "pnpm install" in the .deepsec/AGENTS.md
copy ("The deepsec skill is at `node_modules/deepsec/SKILL.md`...") with "bun
install" and, if helpful, add a short parenthetical note clarifying that the
pnpm-workspace.yaml remains for workspace metadata only.

In @.deepsec/README.md:
- Line 74: Update the incorrect GitHub URL string
"https://github.com/vercel/deepsec/tree/main/docs" in the README to point to the
correct organization by replacing it with
"https://github.com/vercel-labs/deepsec/tree/main/docs" so links to the deepsec
docs resolve to the vercel-labs repository.

In `@apps/ch-stream/Dockerfile`:
- Line 1: The FROM line in the Dockerfile pins oven/bun:1.3.13 to an incorrect
digest; update the image digest to match your target architecture by replacing
the current sha256:87416c9... with the correct digest for your platform (use
sha256:bb35eafd10b2e969809384850ff0474ba36a491239d715864bc87787b4cdf0a4 for
amd64 or sha256:7e06b148ea46613dc8434fd11fafa49cc98e764367ead42e9f424356fce0fdfa
for arm64) so the FROM instruction references a valid manifest.

In `@apps/web/scripts/ingest-hmrc-csv.ts`:
- Around line 119-125: The change to build the slug input via
JSON.stringify([orgName, townCity ?? '', county ?? '', typeRating, route]) will
change all existing slug hashes (including rows where townCity or county were
null) and thus invalidate existing slugId URLs and CDN edge caches; before
merging, ensure the deployment plan: (1) run the ingestion and immediately
trigger a CDN/edge purge for all HMRC detail routes so stale cached old-hash
responses are removed, (2) implement a temporary redirect mapping (old-hash →
new-hash) or a 301 redirect layer populated during the ingestion swap to
preserve links/SEO, and (3) update the comment in the getHmrcBySlugId handler to
record the date and nature of this one-time slugId recalculation so future
maintainers know the hash scheme changed; reference the slug generation site
(the input variable built with JSON.stringify and the null-coercion '??' on
townCity/county) and the getHmrcBySlugId handler when applying these changes.

---

Nitpick comments:
In `@apps/web/server/utils/withSecret.ts`:
- Around line 11-14: The current compare uses
Buffer.from(secret)/Buffer.from(expected) and a.length === b.length with
timingSafeEqual, which leaks the expected secret length; instead, in withSecret
compute fixed-length hashes (e.g., SHA-256) of both secret and expected using
crypto.createHash and convert those digests to Buffers, then call
timingSafeEqual on the two fixed-size hash buffers (remove the a.length ===
b.length pre-check), and keep the existing expected.length > 0 guard or replace
it with a check against the raw expected being non-empty before hashing; update
references to a, b and equal to use the hashed buffers and the new
timingSafeEqual comparison.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: f4acce12-b2d9-476a-9dc5-3b9331b18e0e

📥 Commits

Reviewing files that changed from the base of the PR and between f1cd711 and eee30c6.

⛔ Files ignored due to path filters (1)
  • .deepsec/bun.lock is excluded by !**/*.lock
📒 Files selected for processing (12)
  • .deepsec/.gitignore
  • .deepsec/AGENTS.md
  • .deepsec/README.md
  • .deepsec/data/learn-tanstack-start/INFO.md
  • .deepsec/data/learn-tanstack-start/SETUP.md
  • .deepsec/deepsec.config.ts
  • .deepsec/package.json
  • .deepsec/pnpm-workspace.yaml
  • .github/actions/run-phase5-sweep/action.yaml
  • apps/ch-stream/Dockerfile
  • apps/web/scripts/ingest-hmrc-csv.ts
  • apps/web/server/utils/withSecret.ts

Comment thread .deepsec/AGENTS.md
Comment thread .deepsec/README.md
Comment thread apps/ch-stream/Dockerfile
Comment thread apps/web/scripts/ingest-hmrc-csv.ts Outdated
We do not want to handle the | bug because the practical possibility of
this happening is 0. HMRC won't allow company names to include | in
their name. But even if they did you would need 2 companies to have the
same name with the | in exactly the same spot. In which case it's fine
skipping the hash computes as they both can and should point to the same
slug.
@nikilok nikilok merged commit 619488b into main May 4, 2026
4 checks passed
@nikilok nikilok deleted the feat/deepsec branch May 4, 2026 23:40
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