Skip to content

fix: resolve all audit report issues - #35

Merged
NehanAhmed merged 2 commits into
mainfrom
fix/audit-issues-2026-07-17
Jul 17, 2026
Merged

fix: resolve all audit report issues#35
NehanAhmed merged 2 commits into
mainfrom
fix/audit-issues-2026-07-17

Conversation

@NehanAhmed

@NehanAhmed NehanAhmed commented Jul 17, 2026

Copy link
Copy Markdown
Owner

🔴 C-1: Implement CSRF protection (csrf-csrf, double-submit cookie pattern)
🔴 C-2: Add missing ENCRYPTION_KEY/LINK_ACCESS_SECRET/FINGERPRINT_SECRET to .env.example
🔴 C-3: Mount generalLimiter on /api before route handlers
🟠 H-1: Gate bulk ops, CSV import, and scheduled links behind isFeatureEnabled
🟠 H-2: Validate URL safety on each chain hop in resolveChain
🟡 M-1: Delete orphaned apps/api/.env.local
🟡 M-2: Remove @types/sharp (sharp bundles its own types)
🟡 M-3: Rename BLOCKLIST_TLDS to BLOCKLIST_DOMAINS
🟡 M-4: Already gitignored (apps/*/dist/)
🔵 L-1: Fix docs/PROJECT.md reference (blockedDomains -> blocklistDomains)
🔵 L-2: Move pino-http after stripe webhook route
🔵 L-3: Already resolved (getRateLimiter doesn't exist in current code)
🔵 L-4: Add .length(64) validation for secret env vars

Summary by CodeRabbit

  • New Features
    • Added CSRF protection to API requests, including a CSRF token endpoint and hardened cookie behavior.
    • Introduced rate limiting for API traffic.
    • Added feature-flag controls for bulk operations and scheduled link creation.
  • Bug Fixes
    • Strengthened URL safety checks during link resolution.
    • Applied updated domain blocklist matching for unsafe URLs.
  • Documentation
    • Updated CSRF documentation and API blocklist references.
  • Chores
    • Updated example environment variables and tightened required secret formats.

🔴 C-1: Implement CSRF protection (csrf-csrf, double-submit cookie pattern)
🔴 C-2: Add missing ENCRYPTION_KEY/LINK_ACCESS_SECRET/FINGERPRINT_SECRET to .env.example
🔴 C-3: Mount generalLimiter on /api before route handlers
🟠 H-1: Gate bulk ops, CSV import, and scheduled links behind isFeatureEnabled
🟠 H-2: Validate URL safety on each chain hop in resolveChain
🟡 M-1: Delete orphaned apps/api/.env.local
🟡 M-2: Remove @types/sharp (sharp bundles its own types)
🟡 M-3: Rename BLOCKLIST_TLDS to BLOCKLIST_DOMAINS
🟡 M-4: Already gitignored (apps/*/dist/)
🔵 L-1: Fix docs/PROJECT.md reference (blockedDomains -> blocklistDomains)
🔵 L-2: Move pino-http after stripe webhook route
🔵 L-3: Already resolved (getRateLimiter doesn't exist in current code)
🔵 L-4: Add .length(64) validation for secret env vars
@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 5ccd2894-288f-4214-8c55-a58376b6b677

📥 Commits

Reviewing files that changed from the base of the PR and between 6e5e89a and 3614a10.

📒 Files selected for processing (8)
  • apps/api/.env.example
  • apps/api/AUDIT_REPORT.md
  • apps/api/src/app.ts
  • apps/api/src/middleware/csrf.ts
  • apps/api/src/services/link.service.ts
  • apps/api/src/services/url.services.ts
  • apps/api/src/utils/env.ts
  • apps/dashboard/AUDIT_REPORT.md

📝 Walkthrough

Walkthrough

The API adds CSRF protection and token issuance, tightens secret validation, gates bulk and scheduled operations, validates redirect targets, and renames the domain blocklist export. API and dashboard audit reports document verification results and findings.

Changes

API security and feature controls

Layer / File(s) Summary
CSRF protection and request wiring
apps/api/.env.example, apps/api/src/middleware/csrf.ts, apps/api/src/app.ts, apps/api/src/routes/auth.routes.ts, apps/api/package.json, docs/API.md
Adds CSRF token generation, protected API middleware, environment configuration, dependency wiring, and updated API documentation.
Secret validation and test configuration
apps/api/src/utils/env.ts, apps/api/src/utils/__tests__/env.test.ts, apps/api/vitest.config.ts
Requires four secrets to use 64-character lowercase hexadecimal values and updates test fixtures.
Feature-gated operations
apps/api/src/controllers/link.controller.ts, apps/api/src/controllers/url.controllers.ts, apps/api/src/services/url.services.ts
Bulk operations, CSV imports, and scheduled-link creation return 403 FEATURE_NOT_AVAILABLE when disabled.
Blocklist and redirect safety
apps/api/src/constants/blocklistDomains.ts, apps/api/src/services/urlSafety.ts, apps/api/src/services/link.service.ts, docs/PROJECT.md
Renames the blocklist export, applies it during domain validation, validates chain targets, and updates the documented module name.

Audit documentation

Layer / File(s) Summary
API audit report
apps/api/AUDIT_REPORT.md
Documents API audit metrics, categorized findings, documentation drift, and reviewed areas.
Dashboard audit report
apps/dashboard/AUDIT_REPORT.md
Documents dashboard checks, phase implementation status, findings, configuration gaps, specification drift, and executed commands.

Estimated code review effort: 3 (Moderate) | ~30 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant AuthRoutes
  participant csrfTokenHandler
  participant csrfProtection
  participant ExpressAPI
  Client->>AuthRoutes: GET /api/auth/csrf-token
  AuthRoutes->>csrfTokenHandler: Generate token
  csrfTokenHandler-->>Client: Return token and set CSRF cookie
  Client->>csrfProtection: Send protected request with x-csrf-token
  csrfProtection->>ExpressAPI: Forward validated request
Loading

Possibly related PRs

🚥 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 matches the PR’s main goal of fixing audit report issues across CSRF, feature flags, safety checks, and docs.
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.
✨ 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 fix/audit-issues-2026-07-17

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.

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

🤖 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 `@apps/api/.env.example`:
- Around line 38-40: Update the CSRF_SECRET entry in the environment example to
use the same 64-character hexadecimal placeholder format as the other secrets,
while preserving the existing CSRF configuration key.

In `@apps/api/src/app.ts`:
- Line 42: Update the Express middleware registration in the app initialization
to call express.json() without configuration arguments. Remove the custom 1mb
limit while preserving the middleware placement and behavior otherwise.

In `@apps/api/src/middleware/csrf.ts`:
- Around line 21-24: Update getCsrfTokenFromRequest to read the CSRF token
exclusively from the x-csrf-token request header. Remove the fallback to
req.cookies[CSRF_COOKIE_NAME], while preserving the existing undefined-to-null
behavior when the header is absent.
- Line 5: Update the CSRF cookie name definition around CSRF_COOKIE_NAME to use
the __Host- prefixed name only in production and a regular cookie name in
non-production environments, matching the secure setting in cookieOptions so
local browsers accept the cookie.

In `@apps/api/src/services/link.service.ts`:
- Around line 174-177: Update the error-handling path in the link URL processing
function so malformed targets that cause URL parsing to throw are passed through
validateUrlSafety before being returned. Preserve the existing AppError
handling, and ensure non-AppError parsing failures do not return targetUrl
without validation.

In `@apps/api/src/services/url.services.ts`:
- Around line 104-106: Update the AppError message in the ScheduledLinks feature
check to remove the “on your plan” wording, while preserving the existing status
code and error code.

In `@apps/api/src/utils/env.ts`:
- Around line 10-13: Update the LINK_ACCESS_SECRET, ENCRYPTION_KEY,
FINGERPRINT_SECRET, and CSRF_SECRET validators in the environment schema to use
regex validation that accepts only hexadecimal characters and requires exactly
64 characters. Preserve the existing validation error messages and reject
spaces, symbols, and other non-hex input.
🪄 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

Run ID: 64fc9e8a-a656-44ca-85ac-951fb98e9fd0

📥 Commits

Reviewing files that changed from the base of the PR and between d5d70e4 and 6e5e89a.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (16)
  • apps/api/.env.example
  • apps/api/package.json
  • apps/api/src/app.ts
  • apps/api/src/constants/blocklistDomains.ts
  • apps/api/src/controllers/link.controller.ts
  • apps/api/src/controllers/url.controllers.ts
  • apps/api/src/middleware/csrf.ts
  • apps/api/src/routes/auth.routes.ts
  • apps/api/src/services/link.service.ts
  • apps/api/src/services/url.services.ts
  • apps/api/src/services/urlSafety.ts
  • apps/api/src/utils/__tests__/env.test.ts
  • apps/api/src/utils/env.ts
  • apps/api/vitest.config.ts
  • docs/API.md
  • docs/PROJECT.md

Comment thread apps/api/.env.example
Comment thread apps/api/src/app.ts Outdated
Comment thread apps/api/src/middleware/csrf.ts Outdated
import type { Request, Response, NextFunction } from 'express'
import { env } from '../utils/env'

const CSRF_COOKIE_NAME = '__Host-linkify.x-csrf-token'

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Avoid the __Host- prefix in non-production environments to prevent cookie rejection.

The __Host- cookie prefix enforces strict browser rules, one of which requires the Secure attribute to be present. Because your cookieOptions sets secure: env.NODE_ENV === 'production', the Secure attribute will be missing in local development. As a result, the browser will actively reject the cookie, completely breaking CSRF functionality locally.

To fix this, dynamically use a regular cookie name in non-production environments.

🐛 Proposed fix
-const CSRF_COOKIE_NAME = '__Host-linkify.x-csrf-token'
+const CSRF_COOKIE_NAME = env.NODE_ENV === 'production' ? '__Host-linkify.x-csrf-token' : 'linkify.x-csrf-token'
📝 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
const CSRF_COOKIE_NAME = '__Host-linkify.x-csrf-token'
const CSRF_COOKIE_NAME = env.NODE_ENV === 'production' ? '__Host-linkify.x-csrf-token' : 'linkify.x-csrf-token'
🤖 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/api/src/middleware/csrf.ts` at line 5, Update the CSRF cookie name
definition around CSRF_COOKIE_NAME to use the __Host- prefixed name only in
production and a regular cookie name in non-production environments, matching
the secure setting in cookieOptions so local browsers accept the cookie.

Comment thread apps/api/src/middleware/csrf.ts
Comment thread apps/api/src/services/link.service.ts
Comment thread apps/api/src/services/url.services.ts
Comment thread apps/api/src/utils/env.ts Outdated
@NehanAhmed
NehanAhmed merged commit 2e4880c into main Jul 17, 2026
1 of 3 checks passed
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