Skip to content

Resolve remaining security scan comments#350

Merged
bdamokos merged 1 commit into
mainfrom
codex/resolve-security-comments-2026-05-23
May 24, 2026
Merged

Resolve remaining security scan comments#350
bdamokos merged 1 commit into
mainfrom
codex/resolve-security-comments-2026-05-23

Conversation

@bdamokos

@bdamokos bdamokos commented May 24, 2026

Copy link
Copy Markdown
Owner

Summary

  • Set host-sensitive map and calendar pages to Cache-Control: no-store so admin/planning data is not eligible for shared CDN caching.
  • Guard public map/embed post anchors with http/https URL checks before rendering links.
  • Bound and dedupe YNAB transaction category sync requests before contacting YNAB.
  • Remove accommodation and location names from temp-location cleanup logs.
  • Document the map/calendar cache rule in AGENTS.md.

Validation

  • bun run test:unit -- src/app/__tests__/api/ynab-token-boundary.test.ts src/app/__tests__/unit/nextConfigCache.test.ts src/app/__tests__/lib/serverPrivacyUtils.test.ts --modulePathIgnorePatterns="<rootDir>/.worktrees" --modulePathIgnorePatterns="<rootDir>/.next"
  • bun run lint (passes with existing warnings)
  • bun run build

Summary by CodeRabbit

  • New Features

    • Added URL validation for external post links in maps and embeds to ensure safe rendering.
  • Improvements

    • Transaction category imports now validate inputs with a maximum limit to prevent errors.
    • Optimized cache behavior for admin-sensitive route pages.
  • Tests

    • Added test coverage for cache-control headers and transaction API input boundaries.

Review Change Stack

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request implements security and caching improvements across several areas. It disables public CDN caching for host-sensitive map and calendar routes to prevent leaking admin data and adds a corresponding unit test. The YNAB transaction sync API now includes category ID deduplication, trimming, and a limit of 25 categories per request to prevent excessive fan-out. Additionally, URL safety checks were integrated into the map and embed pages for social media and blog links. I have no feedback to provide as there were no review comments.

@coderabbitai

coderabbitai Bot commented May 24, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

@bdamokos, we couldn't start this review because you've used your available PR reviews for now.

Your plan currently allows 1 review/hour. Refill in 50 minutes and 19 seconds.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more review capacity refills, 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 trial, open-source, and free plans. In all cases, review capacity refills continuously over time.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 21d08ede-4e63-4360-b830-82110beb2870

📥 Commits

Reviewing files that changed from the base of the PR and between f19c7e1 and fc5984c.

📒 Files selected for processing (10)
  • AGENTS.md
  • next.config.js
  • src/app/__tests__/api/ynab-token-boundary.test.ts
  • src/app/__tests__/unit/nextConfigCache.test.ts
  • src/app/api/ynab/categories/route.ts
  • src/app/api/ynab/setup/route.ts
  • src/app/api/ynab/transactions/route.ts
  • src/app/embed/[id]/page.tsx
  • src/app/lib/unifiedDataService.ts
  • src/app/map/[id]/page.tsx
📝 Walkthrough

Walkthrough

This PR hardens security and safety across multiple layers: it enforces no-store caching for admin-sensitive routes, validates external post URLs before rendering links, enforces input limits on YNAB transaction categories, and simplifies logging messages.

Changes

Security & Safety Hardening

Layer / File(s) Summary
Cache Control for Host-Sensitive Routes
AGENTS.md, next.config.js, src/app/__tests__/unit/nextConfigCache.test.ts
Host-sensitive map and calendar routes now use Cache-Control: no-store to prevent shared CDN caching of admin planning data. Configuration is documented, implemented in Next.js headers, and validated by cache-control tests.
URL Validation for External Post Links
src/app/embed/[id]/page.tsx, src/app/map/[id]/page.tsx
External post URLs (Instagram, TikTok, Blog) are validated before rendering. Safe URLs render as clickable links; unsafe URLs render as non-clickable text with the same visual labels and icons.
YNAB Transaction Category Input Validation
src/app/api/ynab/transactions/route.ts, src/app/__tests__/api/ynab-token-boundary.test.ts
YNAB category ID mapping is validated, deduplicated, and limited to MAX_TRANSACTION_CATEGORY_IDS. Requests exceeding the limit return a 400 error with PRIVATE_JSON_HEADERS. Tests cover limit enforcement and deduplication behavior.
Logging Simplification
src/app/lib/unifiedDataService.ts
Temp-location cleanup logs are simplified to remove accommodation and location name interpolation, reducing log verbosity while maintaining the same control flow.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • bdamokos/travel-tracker#161: Both PRs add/adjust rendering of social post hyperlinks with strict HTTP(S) URL validation (main PR gates map/embed external post links; retrieved PR extends TripUpdate links and validates URLs when rendering them).

Suggested labels

codex

Poem

🐰 Four safety shields raised in one swift bound,
Cache headers locked, URLs sound,
Input limits guard the YNAB gate,
Logs cleaned up—the system's great! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.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 'Resolve remaining security scan comments' accurately reflects the main focus of the changeset, which addresses security concerns across multiple areas (caching, URL validation, input bounds, logging).
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 codex/resolve-security-comments-2026-05-23

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.

@greptile-apps

greptile-apps Bot commented May 24, 2026

Copy link
Copy Markdown
Contributor

Confidence Score: 5/5

Safe to merge — all changes are targeted security hardening with no logic regressions.

Every changed path has direct test coverage: cache header tests exercise the next.config rules, the YNAB boundary tests verify the cap, dedup, and no-store header on error responses, and the URL validation utility is straightforward with no side effects. The normalization logic in the transactions route correctly trims and deduplicates category IDs before the YNAB call, and the lookup map keys match what YNAB returns. No regressions are introduced.

No files require special attention.

Important Files Changed

Filename Overview
next.config.js Correctly changes /map/:id* and /calendars/:tripId* from CDN-cacheable to no-store; /embed/:id*, /maps, and /calendars list remain publicly cacheable.
src/app/api/ynab/transactions/route.ts Adds normalizeMappedCategory helper, deduplication via Set, and a 25-category cap before any YNAB API call; all error paths now include PRIVATE_JSON_HEADERS.
src/app/lib/publicUrlValidation.ts New utility; isSafePublicHttpUrl correctly allows only http:/https: protocols using URL parser, blocking javascript:/data:/blob: injection vectors.
src/app/map/[id]/page.tsx All three post-link render sites (blog, Instagram, TikTok) are now guarded with isSafePublicHttpUrl; unsafe URLs fall back to a styled span without href.
src/app/embed/[id]/page.tsx Same URL guard applied to Instagram, TikTok, and blog post links in the embeddable map page.
src/app/tests/api/ynab-token-boundary.test.ts Adds four new test cases covering the 25-category cap, category ID deduplication/trimming, setup validation error cache header, and YNAB upstream error cache header.
src/app/tests/unit/nextConfigCache.test.ts New test file verifying that map/calendar routes emit no-store and that embed routes remain publicly cacheable.

Reviews (2): Last reviewed commit: "Resolve remaining security scan comments" | Re-trigger Greptile

@bdamokos bdamokos force-pushed the codex/resolve-security-comments-2026-05-23 branch from f19c7e1 to a5b59f3 Compare May 24, 2026 09:55

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
src/app/__tests__/api/ynab-token-boundary.test.ts (1)

248-280: ⚡ Quick win

Add one regression case for whitespace-normalized category IDs.

This test verifies de-duplication, but not trim normalization. Add one mapping like ' cat-1 ' and assert getTransactionsByCategories receives 'cat-1' to lock in normalization behavior.

🤖 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/app/__tests__/api/ynab-token-boundary.test.ts` around lines 248 - 280,
Add a regression case to ensure whitespace-normalized category IDs are deduped:
in the test for ynabTransactionsPOST add a categoryMappings entry with a padded
ID like ' cat-1 ' (alongside the existing 'cat-1') and keep the other mappings;
then assert mockGetTransactionsByCategories is called with the trimmed ID array
['cat-1','cat-3'] so the test verifies trimming + dedup behavior for
categoryMappings before calling getTransactionsByCategories.
🤖 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 `@src/app/api/ynab/transactions/route.ts`:
- Around line 61-62: The POST route's error responses are inconsistent: include
PRIVATE_JSON_HEADERS on every error NextResponse.json call in the POST handler
(not just the two 400 returns). Update the error paths that currently return
401, 404, 429, 500 (and the earlier 79-83 error returns) to pass
PRIVATE_JSON_HEADERS in the response options so all admin-sensitive error
responses use the same private/no-store headers; look for NextResponse.json(...)
calls inside the POST handler in route.ts and add the headers argument ({
headers: PRIVATE_JSON_HEADERS }) to each error response.
- Around line 66-77: The category normalization is done into mappedCategoryIds
but the later categoryMappingLookup still reads raw mapping.ynabCategoryId and
mappingType, which breaks lookups for whitespace-padded IDs and allows invalid
mappingType values; update the code that builds categoryMappingLookup to first
validate and normalize each CategoryMapping (check typeof mapping === 'object',
typeof mapping.ynabCategoryId === 'string' and typeof mapping.mappingType ===
'string' and mapping.mappingType !== 'none'), trim and reject empty
ynabCategoryId, then use the trimmed ID as the key when constructing
categoryMappingLookup so lookups match mappedCategoryIds and malformed mappings
are excluded.

---

Nitpick comments:
In `@src/app/__tests__/api/ynab-token-boundary.test.ts`:
- Around line 248-280: Add a regression case to ensure whitespace-normalized
category IDs are deduped: in the test for ynabTransactionsPOST add a
categoryMappings entry with a padded ID like ' cat-1 ' (alongside the existing
'cat-1') and keep the other mappings; then assert
mockGetTransactionsByCategories is called with the trimmed ID array
['cat-1','cat-3'] so the test verifies trimming + dedup behavior for
categoryMappings before calling getTransactionsByCategories.
🪄 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: c5703c9b-434d-4564-ba00-090d8b8d8534

📥 Commits

Reviewing files that changed from the base of the PR and between 004f96a and f19c7e1.

📒 Files selected for processing (8)
  • AGENTS.md
  • next.config.js
  • src/app/__tests__/api/ynab-token-boundary.test.ts
  • src/app/__tests__/unit/nextConfigCache.test.ts
  • src/app/api/ynab/transactions/route.ts
  • src/app/embed/[id]/page.tsx
  • src/app/lib/unifiedDataService.ts
  • src/app/map/[id]/page.tsx

Comment thread src/app/api/ynab/transactions/route.ts
Comment thread src/app/api/ynab/transactions/route.ts
@bdamokos bdamokos force-pushed the codex/resolve-security-comments-2026-05-23 branch from a5b59f3 to fc5984c Compare May 24, 2026 09:59
@bdamokos bdamokos merged commit 53eee9b into main May 24, 2026
5 checks passed
@bdamokos bdamokos deleted the codex/resolve-security-comments-2026-05-23 branch May 24, 2026 10:01
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