Skip to content

🔒 Fix fallback of allowedOrigin to localhost in production#381

Open
is0692vs wants to merge 1 commit into
mainfrom
jules-9766932802489647517-7e5e2205
Open

🔒 Fix fallback of allowedOrigin to localhost in production#381
is0692vs wants to merge 1 commit into
mainfrom
jules-9766932802489647517-7e5e2205

Conversation

@is0692vs

@is0692vs is0692vs commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

🎯 What: The vulnerability fixed
In src/app/api/card/[username]/route.ts, if the APP_URL environment variable is not explicitly set, the allowedOrigin falls back to http://localhost:3000.

⚠️ Risk: The potential impact if left unfixed
This insecure fallback might cause fonts or other internal fetch requests to hit a local developer endpoint instead of the intended service in production environments. Crucially, this variable is used via renderCardResponse as the trusted allowedOrigin in isTrustedFontUrl (in validators.ts), potentially meaning that the production environment would implicitly trust localhost:3000 URLs when it shouldn't.

🛡️ Solution: How the fix addresses the vulnerability
The code now properly verifies the presence of the APP_URL environment variable. If APP_URL is empty and the environment is production, the server now explicitly returns a 500 Server configuration error. In non-production environments, it safely falls back to http://localhost:3000.


PR created automatically by Jules for task 9766932802489647517 started by @is0692vs

Greptile Summary

本番環境で APP_URL 環境変数が未設定の場合に localhost:3000 へフォールバックしていた問題を修正するPRです。NODE_ENV === \"production\" のときは明示的に 500 を返し、それ以外の環境では従来通り localhost:3000 にフォールバックします。

  • 環境変数チェックの追加: APP_URL が未設定かつ本番環境の場合、500 エラーを即時返却するよう変更。
  • 開発環境の挙動は維持: 非本番環境では引き続き http://localhost:3000 へのフォールバックを許容。

Confidence Score: 4/5

変更は1ファイル・数行のみで、本番環境での設定ミスを早期に検出するための防御的なガードです。マージ自体のリスクは低い。

修正は意図通りに機能しており、ロジックも明確です。ただし 500 レスポンスのボディが内部環境変数名を公開している点と、他のエラーレスポンスと形式が異なる点(プレーンテキスト vs SVG カード)が残っています。

src/app/api/card/[username]/route.ts — 500 エラーのレスポンス形式とメッセージ内容を確認してください。

Security Review

  • 情報漏洩 (route.ts L23): 500 エラーのボディに内部環境変数名 APP_URL がそのまま含まれており、設定ミスの詳細をクライアントに公開しています。汎用的なメッセージ(例: "Server configuration error")に変更することを推奨します。
  • 既存の緩和策: isTrustedFontUrl は HTTPS のみを許可し、getTrustedFontOrigins も HTTPS オリジンのみをホワイトリストに追加するため、旧来の http://localhost:3000 フォールバックは実際には信頼済みオリジンとして機能しなかった点に注意してください。今回の修正は防御的に正しい方向ですが、実際の悪用経路は限定的でした。

Important Files Changed

Filename Overview
src/app/api/card/[username]/route.ts 本番環境で APP_URL 未設定時に 500 を返すよう修正。エラーメッセージに内部環境変数名が含まれる点と、他エラーと異なるプレーンテキスト形式の点が気になる。

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[GET /api/card/:username] --> B[process.env.APP_URL 取得]
    B --> C{APP_URL は設定済み?}
    C -- はい --> G[allowedOrigin = APP_URL]
    C -- いいえ --> D{NODE_ENV === production?}
    D -- はい --> E[500 Server configuration error を返す]
    D -- いいえ 開発環境 --> F[allowedOrigin = http://localhost:3000]
    F --> G
    G --> H[fontUrl 組み立て]
    H --> I{レートリミット超過?}
    I -- はい --> J[renderErrorCardResponse 429]
    I -- いいえ --> K[fetchCardData]
    K --> L{data あり?}
    L -- いいえ --> M[renderErrorCardResponse 404]
    L -- はい --> N[renderCardResponse 200]
    K -- 例外 --> O[renderErrorCardResponse 503]
Loading
Prompt To Fix All With AI
Fix the following 2 code review issues. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 2
src/app/api/card/[username]/route.ts:23
エラーレスポンスのボディに内部の環境変数名 (`APP_URL`) がそのまま含まれており、クライアントに不要な実装詳細を公開しています。攻撃者が設定ミスをスキャンする際のヒントになり得るため、汎用的なメッセージに留めることを推奨します。

```suggestion
            return new Response("Server configuration error", { status: 500 });
```

### Issue 2 of 2
src/app/api/card/[username]/route.ts:23
**レスポンス形式の不整合**

このエンドポイントの他のすべてのエラーパス(429・404・503)は `renderErrorCardResponse` を通じて SVG カードを返しますが、この 500 レスポンスのみプレーンテキストを返します。クライアント(`<img>` タグ等)が常に SVG を期待している場合、`APP_URL` が未設定の本番環境でデプロイされたとき破損した表示になります。`renderErrorCardResponse` で統一するか、`Content-Type: image/svg+xml` を明示することを検討してください。

Reviews (1): Last reviewed commit: "Fix APP_URL environment variable fallbac..." | Re-trigger Greptile

Greptile also left 2 inline comments on this PR.

Co-authored-by: is0692vs <135803462+is0692vs@users.noreply.github.com>
@google-labs-jules

Copy link
Copy Markdown
Contributor

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

@vercel

vercel Bot commented Jun 12, 2026

Copy link
Copy Markdown

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

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
github-user-summary Ignored Ignored Jun 12, 2026 7:28am

@qodo-code-review

Copy link
Copy Markdown

Qodo reviews are paused for this user.

Troubleshooting steps vary by plan Learn more →

On a Teams plan?
Reviews resume once this user has a paid seat and their Git account is linked in Qodo.
Link Git account →

Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center?
These require an Enterprise plan - Contact us
Contact us →

@dosubot dosubot Bot added the bug Something isn't working label Jun 12, 2026
@coderabbitai

coderabbitai Bot commented Jun 12, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@is0692vs, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 10 minutes and 13 seconds. Learn how PR review limits work.

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

⌛ How to resolve this issue?

After more reviews become available, 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 include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: d1aa1355-69c5-4e3b-adf5-2b1ab2f30e19

📥 Commits

Reviewing files that changed from the base of the PR and between a475ecb and 6eb0c3e.

📒 Files selected for processing (1)
  • src/app/api/card/[username]/route.ts
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch jules-9766932802489647517-7e5e2205

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.

@gemini-code-assist gemini-code-assist 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.

Code Review

This pull request improves environment variable validation in the card API route by returning a 500 error in production if the APP_URL environment variable is not configured. The reviewer suggested trimming APP_URL to prevent issues with accidental leading or trailing whitespace.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

const url = new URL(request.url);
const options = parseCardQueryParams(url.searchParams);
const allowedOrigin = process.env.APP_URL || "http://localhost:3000";
let allowedOrigin = process.env.APP_URL;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

Trimming the APP_URL environment variable prevents potential issues caused by accidental leading or trailing whitespace in configuration files, which could otherwise result in malformed font URLs or failed origin validation checks.

Suggested change
let allowedOrigin = process.env.APP_URL;
let allowedOrigin = process.env.APP_URL?.trim();

@codecov

codecov Bot commented Jun 12, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

let allowedOrigin = process.env.APP_URL;
if (!allowedOrigin) {
if (process.env.NODE_ENV === "production") {
return new Response("Server configuration error: APP_URL environment variable is not set", { status: 500 });

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.

P2 security エラーレスポンスのボディに内部の環境変数名 (APP_URL) がそのまま含まれており、クライアントに不要な実装詳細を公開しています。攻撃者が設定ミスをスキャンする際のヒントになり得るため、汎用的なメッセージに留めることを推奨します。

Suggested change
return new Response("Server configuration error: APP_URL environment variable is not set", { status: 500 });
return new Response("Server configuration error", { status: 500 });
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/app/api/card/[username]/route.ts
Line: 23

Comment:
エラーレスポンスのボディに内部の環境変数名 (`APP_URL`) がそのまま含まれており、クライアントに不要な実装詳細を公開しています。攻撃者が設定ミスをスキャンする際のヒントになり得るため、汎用的なメッセージに留めることを推奨します。

```suggestion
            return new Response("Server configuration error", { status: 500 });
```

How can I resolve this? If you propose a fix, please make it concise.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

let allowedOrigin = process.env.APP_URL;
if (!allowedOrigin) {
if (process.env.NODE_ENV === "production") {
return new Response("Server configuration error: APP_URL environment variable is not set", { status: 500 });

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.

P2 レスポンス形式の不整合

このエンドポイントの他のすべてのエラーパス(429・404・503)は renderErrorCardResponse を通じて SVG カードを返しますが、この 500 レスポンスのみプレーンテキストを返します。クライアント(<img> タグ等)が常に SVG を期待している場合、APP_URL が未設定の本番環境でデプロイされたとき破損した表示になります。renderErrorCardResponse で統一するか、Content-Type: image/svg+xml を明示することを検討してください。

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/app/api/card/[username]/route.ts
Line: 23

Comment:
**レスポンス形式の不整合**

このエンドポイントの他のすべてのエラーパス(429・404・503)は `renderErrorCardResponse` を通じて SVG カードを返しますが、この 500 レスポンスのみプレーンテキストを返します。クライアント(`<img>` タグ等)が常に SVG を期待している場合、`APP_URL` が未設定の本番環境でデプロイされたとき破損した表示になります。`renderErrorCardResponse` で統一するか、`Content-Type: image/svg+xml` を明示することを検討してください。

How can I resolve this? If you propose a fix, please make it concise.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working size/XS

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant