Skip to content

fix: normalize referer before redirect#5640

Merged
fengmk2 merged 4 commits into
nextfrom
koa-fix-1908
Oct 23, 2025
Merged

fix: normalize referer before redirect#5640
fengmk2 merged 4 commits into
nextfrom
koa-fix-1908

Conversation

@fengmk2

@fengmk2 fengmk2 commented Oct 23, 2025

Copy link
Copy Markdown
Member

pick from koajs/koa#1908

Summary by CodeRabbit

  • Bug Fixes

    • Redirect "back" now only honors same-origin absolute referrers and falls back safely for protocol-relative or unsafe referrers.
  • Tests

    • Expanded redirect-back test coverage (origin validation, referer variations, host-context cases).
    • Marked flaky cluster tests to skip on Windows.

@fengmk2 fengmk2 requested a review from Copilot October 23, 2025 13:54
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello @fengmk2, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request implements a critical security enhancement by normalizing and validating the Referer header before performing a ctx.redirect('back'). This prevents potential open redirect vulnerabilities where a malicious Referer header could lead users to external, untrusted sites. The change ensures that all back redirects remain within the application's origin, and it is accompanied by new test cases to verify the fix, particularly for protocol-relative URLs that could be exploited.

Highlights

  • Security Fix: Addresses a potential open redirect vulnerability by strictly normalizing and validating the Referer header before performing a back redirect.
  • Referer Normalization: All Referer values, whether relative or absolute, are now processed through URL object construction and checked against the current host to ensure same-origin redirection.
  • Improved Test Coverage: New test cases have been added to cover same-origin absolute URLs and specifically to validate the fix for the 'Trailing Double-Slash security issue' in referer handling.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@coderabbitai

coderabbitai Bot commented Oct 23, 2025

Copy link
Copy Markdown
Contributor

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

The response back-referrer logic now accepts only same-origin absolute Referrer URLs; relative referrers are ignored. Tests were updated to assert origin checks, relative-path fallbacks, and handling of protocol-relative or unsafe referrers. One test suite is skipped on Windows due to flakiness.

Changes

Cohort / File(s) Summary
Referrer validation logic
packages/koa/src/response.ts
_getBackReferrer changed to parse and validate only absolute Referrer URLs and ensure same-origin; it no longer returns relative paths starting with /.
Redirect back tests
packages/koa/test/response/redirect.test.ts
Tests updated to create contexts with explicit URL/Host, added same-origin full-URL redirect tests, relative-path fallback scenarios, protocol-relative/trailing-slash safety checks, and Referer/Referrer variations.
Platform-gated tests
plugins/schedule/test/dynamic.test.ts
Wrapping cluster test suite with describe.skipIf(process.platform === 'win32') to skip flaky tests on Windows (no logic changes to tests themselves).

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Client
  participant ServerResponse as Response._getBackReferrer
  participant URLParser as URL(parse)
  Note over ServerResponse,URLParser #DDEEFF: New flow validates origin & absolute URL

  Client->>ServerResponse: requests redirect('back')
  ServerResponse->>URLParser: parse ctx.get('Referrer') / ctx.get('Referer')
  alt Referrer absent or parse fails
    URLParser-->>ServerResponse: error / invalid
    ServerResponse-->>Client: fallback redirect (e.g., '/')
  else Absolute URL parsed
    URLParser-->>ServerResponse: { origin, pathname, ... }
    alt same-origin
      ServerResponse-->>Client: redirect to parsed full URL
    else different-origin
      ServerResponse-->>Client: fallback redirect (e.g., '/')
    end
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰
I hopped through headers, nose to the byte,
I sniffed for origins in the moonlight.
No stray slashes may lead us wrong—
Back only when hosts belong.
A tidy hop, secure and light.

Pre-merge checks and finishing touches

❌ 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%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The pull request title "fix: normalize referer before redirect" directly corresponds to the primary change in the changeset. The main modification is in packages/koa/src/response.ts, where the _getBackReferrer method is updated to normalize referer handling by only accepting same-origin absolute URLs instead of allowing relative paths. The title accurately reflects this core change—normalizing the referer before redirect operations. The supporting changes in test files validate this referer normalization behavior. The title is concise, specific, and clearly communicates the essential change without unnecessary details.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch koa-fix-1908

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f621138 and e137037.

📒 Files selected for processing (2)
  • packages/koa/test/response/redirect.test.ts (2 hunks)
  • plugins/schedule/test/dynamic.test.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

**/*.ts: Prefer TypeScript and ESM: write sources and exports in .ts (ESM-first) rather than CommonJS
Use two-space indentation, trailing commas, and semicolons (Prettier/oxlint defaults)
Name files in lowercase with hyphens (e.g., loader-context.ts)
Name classes in PascalCase
Name functions and variables in camelCase
Re-export types thoughtfully to keep the public API stable

Files:

  • plugins/schedule/test/dynamic.test.ts
  • packages/koa/test/response/redirect.test.ts
**/test/**/*.test.ts

📄 CodeRabbit inference engine (AGENTS.md)

**/test/**/*.test.ts: Place test suites following Vitest discovery: /test//*.test.ts
Mirror the repository test pattern when adding new suites

Files:

  • plugins/schedule/test/dynamic.test.ts
  • packages/koa/test/response/redirect.test.ts
{packages/**,plugins/**,tools/!(egg-bin)/**}/**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

{packages/**,plugins/**,tools/!(egg-bin)/**}/**/*.ts: For isolatedDeclarations support, all exported functions/methods/getters must have explicit return type annotations
Avoid computed property names with symbols in class declarations (no get SYM)
Add explicit type annotations for class properties when needed (no inferred exported property types)
Exported symbols must use unique symbol type (e.g., export const X: unique symbol = Symbol('x'))

Files:

  • plugins/schedule/test/dynamic.test.ts
  • packages/koa/test/response/redirect.test.ts
{packages/!(cookies)/**/test/**/*.test.ts,plugins/**/test/**/*.test.ts}

📄 CodeRabbit inference engine (CLAUDE.md)

Vitest test files must follow the naming pattern test/**/*.test.ts

Files:

  • plugins/schedule/test/dynamic.test.ts
  • packages/koa/test/response/redirect.test.ts
{packages/**/test/**,plugins/**/test/**}

📄 CodeRabbit inference engine (CLAUDE.md)

Use Node.js assert for assertions in Vitest tests

Files:

  • plugins/schedule/test/dynamic.test.ts
  • packages/koa/test/response/redirect.test.ts
packages/**/test/**/*.test.ts

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

packages/**/test/**/*.test.ts: Name test files as test/**/*.test.ts and run them with Vitest
Use import { describe, it } from 'vitest' in tests
Use Node.js built-in assert module for test assertions

Files:

  • packages/koa/test/response/redirect.test.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
  • GitHub Check: Test (ubuntu-latest, 24, 3/5)
  • GitHub Check: Test (ubuntu-latest, 24, 2/5)
  • GitHub Check: Test bin (ubuntu-latest, 22, 0/3)
  • GitHub Check: Test bin (ubuntu-latest, 22, 1/3)
  • GitHub Check: typecheck
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: Analyze (actions)
🔇 Additional comments (3)
plugins/schedule/test/dynamic.test.ts (1)

8-9: Skipping tests on Windows is a temporary workaround.

While describe.skipIf is appropriate for handling flaky tests, this leaves the underlying timeout issue unresolved. Consider investigating whether the 20-second hook timeout is caused by:

  • Platform-specific timing differences in cluster initialization
  • Resource cleanup delays on Windows
  • Race conditions that manifest more frequently on Windows
packages/koa/test/response/redirect.test.ts (2)

41-41: LGTM! Context initialization enables proper origin handling.

Adding explicit url and host to the context initialization allows the redirect logic to properly validate same-origin referrers. This aligns with the security improvements in this PR.

Also applies to: 47-52


88-96: Excellent security test coverage.

This test properly verifies that protocol-relative URLs (e.g., //evil.com/login/) in the referrer header are treated as unsafe and trigger the fallback behavior instead of being followed. This prevents potential open redirect vulnerabilities.

The test covers both fallback scenarios:

  • Default fallback to / when no alt is provided
  • Fallback to the alt parameter (/home) when explicitly provided

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.

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Oct 23, 2025

Copy link
Copy Markdown

Deploying egg with  Cloudflare Pages  Cloudflare Pages

Latest commit: e137037
Status: ✅  Deploy successful!
Preview URL: https://85cbdb3f.egg-cci.pages.dev
Branch Preview URL: https://koa-fix-1908.egg-cci.pages.dev

View logs

Copilot AI 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.

Pull Request Overview

This PR addresses a security vulnerability in the redirect functionality by normalizing referer values before processing redirects. The change prevents the "Trailing Double-Slash" security issue where URLs like //evil.com could be exploited for open redirects.

Key Changes:

  • Removed special handling for relative path referers (starting with /)
  • Added test coverage for same-origin URL redirects
  • Added security test case demonstrating the fix for double-slash URLs

Reviewed Changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
packages/koa/src/response.ts Removed conditional check that treated paths starting with / as safe, now all referers go through URL parsing and origin validation
packages/koa/test/response/redirect.test.ts Added test cases for same-origin redirects and the double-slash security vulnerability fix

Comment thread packages/koa/test/response/redirect.test.ts Outdated
Comment thread packages/koa/test/response/redirect.test.ts Outdated
@codecov

codecov Bot commented Oct 23, 2025

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 87.52%. Comparing base (97372fd) to head (e137037).
⚠️ Report is 3 commits behind head on next.

Additional details and impacted files
@@            Coverage Diff             @@
##             next    #5640      +/-   ##
==========================================
- Coverage   87.52%   87.52%   -0.01%     
==========================================
  Files         565      565              
  Lines       11007    11006       -1     
  Branches     1243     1243              
==========================================
- Hits         9634     9633       -1     
  Misses       1291     1291              
  Partials       82       82              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@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 addresses a potential open redirect vulnerability by normalizing the Referer header before using it for a 'back' redirect. The change in packages/koa/src/response.ts removes special handling for relative paths and now consistently uses the URL constructor to parse and validate the referrer against the request's host. This ensures that only same-origin referrers are used for redirection, preventing redirects to malicious external sites. The accompanying changes in packages/koa/test/response/redirect.test.ts are excellent, adding a specific test case for the vulnerability and improving the robustness of existing tests by providing a proper request context. The changes are correct, well-tested, and improve the security of the application.

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Oct 23, 2025

Copy link
Copy Markdown

Deploying egg-v3 with  Cloudflare Pages  Cloudflare Pages

Latest commit: e137037
Status: ✅  Deploy successful!
Preview URL: https://fbdbc4c9.egg-v3.pages.dev
Branch Preview URL: https://koa-fix-1908.egg-v3.pages.dev

View logs

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

🧹 Nitpick comments (1)
packages/koa/test/response/redirect.test.ts (1)

77-77: Inconsistent assertion method usage.

Lines 77 and 85 use assert.strictEqual, while other tests in this file use assert.equal. Since the file imports from node:assert/strict, both methods behave identically (strict equality). For consistency, consider using only assert.equal throughout the file.

Apply this diff to make assertions consistent:

-    assert.strictEqual(ctx.response.header.location, 'https://example.com/login');
+    assert.equal(ctx.response.header.location, 'https://example.com/login');

And:

-    assert.strictEqual(ctx.response.header.location, '/');
+    assert.equal(ctx.response.header.location, '/');

Also applies to: 85-85

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 97372fd and f621138.

📒 Files selected for processing (2)
  • packages/koa/src/response.ts (0 hunks)
  • packages/koa/test/response/redirect.test.ts (2 hunks)
💤 Files with no reviewable changes (1)
  • packages/koa/src/response.ts
🧰 Additional context used
📓 Path-based instructions (6)
packages/**/test/**/*.test.ts

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

packages/**/test/**/*.test.ts: Name test files as test/**/*.test.ts and run them with Vitest
Use import { describe, it } from 'vitest' in tests
Use Node.js built-in assert module for test assertions

Files:

  • packages/koa/test/response/redirect.test.ts
**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

**/*.ts: Prefer TypeScript and ESM: write sources and exports in .ts (ESM-first) rather than CommonJS
Use two-space indentation, trailing commas, and semicolons (Prettier/oxlint defaults)
Name files in lowercase with hyphens (e.g., loader-context.ts)
Name classes in PascalCase
Name functions and variables in camelCase
Re-export types thoughtfully to keep the public API stable

Files:

  • packages/koa/test/response/redirect.test.ts
**/test/**/*.test.ts

📄 CodeRabbit inference engine (AGENTS.md)

**/test/**/*.test.ts: Place test suites following Vitest discovery: /test//*.test.ts
Mirror the repository test pattern when adding new suites

Files:

  • packages/koa/test/response/redirect.test.ts
{packages/**,plugins/**,tools/!(egg-bin)/**}/**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

{packages/**,plugins/**,tools/!(egg-bin)/**}/**/*.ts: For isolatedDeclarations support, all exported functions/methods/getters must have explicit return type annotations
Avoid computed property names with symbols in class declarations (no get SYM)
Add explicit type annotations for class properties when needed (no inferred exported property types)
Exported symbols must use unique symbol type (e.g., export const X: unique symbol = Symbol('x'))

Files:

  • packages/koa/test/response/redirect.test.ts
{packages/!(cookies)/**/test/**/*.test.ts,plugins/**/test/**/*.test.ts}

📄 CodeRabbit inference engine (CLAUDE.md)

Vitest test files must follow the naming pattern test/**/*.test.ts

Files:

  • packages/koa/test/response/redirect.test.ts
{packages/**/test/**,plugins/**/test/**}

📄 CodeRabbit inference engine (CLAUDE.md)

Use Node.js assert for assertions in Vitest tests

Files:

  • packages/koa/test/response/redirect.test.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (20)
  • GitHub Check: Test (windows-latest, 22, 2/5)
  • GitHub Check: Test (macos-latest, 22, 2/5)
  • GitHub Check: Test (ubuntu-latest, 24, 5/5)
  • GitHub Check: Test (macos-latest, 24, 4/5)
  • GitHub Check: Test (macos-latest, 22, 1/5)
  • GitHub Check: Test (ubuntu-latest, 24, 3/5)
  • GitHub Check: Test (macos-latest, 22, 5/5)
  • GitHub Check: Test (macos-latest, 22, 4/5)
  • GitHub Check: Test (ubuntu-latest, 24, 1/5)
  • GitHub Check: Test (windows-latest, 24, 4/5)
  • GitHub Check: Test (ubuntu-latest, 22, 1/5)
  • GitHub Check: Test (windows-latest, 24, 5/5)
  • GitHub Check: Test (windows-latest, 24, 1/5)
  • GitHub Check: Test bin (windows-latest, 22, 0/3)
  • GitHub Check: Test bin (ubuntu-latest, 22, 1/3)
  • GitHub Check: Test bin (ubuntu-latest, 22, 0/3)
  • GitHub Check: Test bin (windows-latest, 22, 2/3)
  • GitHub Check: Test bin (windows-latest, 22, 1/3)
  • GitHub Check: typecheck
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (2)
packages/koa/test/response/redirect.test.ts (2)

40-52: LGTM: Proper context initialization for origin-aware redirects.

The explicit context initialization with url and host is necessary for the updated redirect logic to perform origin checks. Testing both referrer and referer headers is correct since HTTP allows both spellings.


88-96: LGTM: Critical security fix properly tested.

This test correctly validates the Trailing Double-Slash security fix, ensuring protocol-relative URLs (e.g., //evil.com/login/) are not followed during back redirects. The test verifies:

  1. Protocol-relative referrer falls back to /
  2. Explicit fallback path (e.g., /home) works as expected

This prevents potential open redirect vulnerabilities.

Comment thread packages/koa/test/response/redirect.test.ts Outdated
fengmk2 and others added 3 commits October 23, 2025 22:53
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@fengmk2 fengmk2 merged commit 03f66dc into next Oct 23, 2025
50 of 52 checks passed
@fengmk2 fengmk2 deleted the koa-fix-1908 branch October 23, 2025 17:38
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.

2 participants