Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@sixcolors
Copy link
Member

Description

This PR fixes a bug in the session middleware's fresh flag logic that caused incorrect Fresh() values when getSession() was called multiple times for the same session within a single request.

Problem

The bug was on line 130 of middleware/session/store.go:

fresh := ok  // ❌ WRONG: inverted logic

This inverted logic meant that:

  • When session ID was found in locals (cached), fresh was set to true (incorrectly indicating new session)
  • When session ID was not found in locals, fresh was set to false (incorrectly indicating existing session)

Impact

The bug affected scenarios where:

  1. Multiple getSession() calls happened in the same request (e.g., middleware chain + CSRF validation)
  2. Applications relying on Fresh() to detect truly new sessions
  3. Session expiration detection logic

Solution

Changed line 130 to:

fresh := false  // ✅ CORRECT: only true when actually generating new ID

Now the fresh flag is only set to true in two legitimate cases:

  1. acquireSession() - when creating a brand new session (line 61 in session.go)
  2. refresh() - when regenerating an expired session (line 280 in session.go)

Tests Added

Added 3 comprehensive tests to verify the fix:

  1. Test_Session_Fresh_Flag_Bug - Verifies multiple getSession calls return consistent fresh=false for existing sessions
  2. Test_Session_CSRF_Scenario - Simulates the user-reported CSRF issue with session regeneration
  3. Test_Session_Multiple_GetSession_Calls - Ensures session ID consistency across multiple retrievals

Updated 1 existing test:

  • Test_Session_Cookie_In_Middleware_Chain - Corrected expectation to match fixed behavior

Test Results

All 48 session middleware tests passing:

$ make test
PASS
coverage: 89.4% of statements
ok      github.com/gofiber/fiber/v3/middleware/session  2.345s

Backwards Compatibility

This is a bug fix, not a breaking change. Applications relying on the buggy behavior (which was incorrect) will now receive the correct fresh flag values.

Related Issues

Discovered during investigation of user-reported CSRF + session behavior.

Fixed a bug where the `fresh` flag was incorrectly set to `true` when
a session ID was found in context locals during subsequent calls to
`getSession()` in the same request.

The previous logic was:
```go
fresh := ok // Assume the session is fresh if the ID is found in locals
```

This was backwards. When the session ID is found in locals (ok == true),
it means the session was already initialized in this request, so it
should NOT be marked as fresh.

The correct logic is:
```go
fresh := false // Session is not fresh initially; only set to true if we generate a new ID
```

**Impact:**
- The `Fresh()` method now correctly returns `false` for existing sessions
- Fixes potential issues with absolute timeout calculations
- Prevents confusion in middleware that checks if a session is new

**Tests added:**
- `Test_Session_Fresh_Flag_Bug`: Verifies fresh flag is correct across multiple getSession() calls
- `Test_Session_CSRF_Scenario`: Simulates the user-reported CSRF + session scenario
- `Test_Session_Multiple_GetSession_Calls`: Ensures consistency across multiple calls

**Tests updated:**
- `Test_Session_Cookie_In_Middleware_Chain`: Fixed to expect correct fresh flag behavior

**Related to user-reported issue:**
While investigating a user report about getting new session IDs on failed CSRF
validation, we discovered this bug. The user's issue is actually expected behavior
(sessions regenerate when data expires), but this bug needed fixing regardless.
Copilot AI review requested due to automatic review settings October 28, 2025 20:24
@sixcolors sixcolors requested a review from a team as a code owner October 28, 2025 20:24
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 28, 2025

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 session middleware's fresh-flag initialization was changed so sessions are only marked fresh when a new ID is generated; previously an ID found in locals marked the session fresh. One existing test expectation was updated and three new tests were added to cover fresh-flag, CSRF, and repeated getSession call scenarios.

Changes

Cohort / File(s) Change Summary
Session Store Logic
middleware/session/store.go
Initialize fresh as false instead of fresh := ok (stop treating a locals-provided ID as fresh); keep existing data retrieval, ID generation, and expiration handling.
Session Tests
middleware/session/session_test.go
Updated Test_Session_Cookie_In_Middleware_Chain to expect sess.Fresh() == false; added Test_Session_Fresh_Flag_Bug, Test_Session_CSRF_Scenario, and Test_Session_Multiple_GetSession_Calls to validate fresh-flag behavior, CSRF/session edge cases, and multiple getSession() calls within one request.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Handler as Request Handler
    participant SessionMW as Session Middleware
    participant Store as Session Store

    Note over SessionMW,Store: Fresh flag now only true when Store generates a new ID

    rect rgb(240,248,255)
    Note over Client,Store: Existing session flow
    Client->>Handler: Request with session cookie
    Handler->>SessionMW: getSession(ctx)
    SessionMW->>Store: check locals for ID
    Store->>Store: ID found in locals
    Store->>Store: set fresh := false
    Store->>Store: load session data (if present & not expired)
    Store-->>SessionMW: return session (fresh=false)
    end

    rect rgb(240,255,240)
    Note over Client,Store: New session flow
    Client->>Handler: Request without session
    Handler->>SessionMW: getSession(ctx)
    SessionMW->>Store: check locals for ID
    Store->>Store: no ID -> generate new ID
    Store->>Store: set fresh := true
    Store-->>SessionMW: return session (fresh=true)
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Single-line semantic change in middleware/session/store.go.
  • Multiple new tests added in middleware/session/session_test.go; run tests and inspect CSRF/expiry scenarios.
  • Pay attention to:
    • middleware/session/store.go — fresh flag logic, ID generation, locals handling.
    • middleware/session/session_test.go — test correctness around repeated getSession() and expiry.

Possibly related PRs

Suggested labels

SessionMW

Suggested reviewers

  • gaby
  • ReneWerner87
  • efectn

Poem

🐰 I hop through code with whiskers bright,
IDs appear only when none are in sight,
Freshness saved for newborn sessions' cheer,
Tests munch carrots to keep behavior clear,
Hooray for stable IDs — hop, hop, hooray! 🥕

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Description Check ⚠️ Warning The PR description provides comprehensive technical detail about the bug, impact, solution, and test coverage, demonstrating good content quality. However, it significantly deviates from the required template structure by omitting critical sections including the "Fixes #" issue reference, the "Changes introduced" section with required subsections, the explicit "Type of change" checkbox selection, and the formal "Checklist" verification items. While the author provides valuable information about backwards compatibility and test results, the response does not follow the template's required organization and structure for PR descriptions in this repository. Please restructure the description to follow the repository template by adding: (1) a "Fixes #" reference to the related issue, (2) a "Changes introduced" section (even if only to indicate which subsections apply), (3) a "Type of change" section with the appropriate checkbox selected (likely "Code consistency" or similar for this bug fix), and (4) the formal "Checklist" section with completed verification items. The existing technical content can be incorporated into these template sections to maintain the quality of the explanation.
✅ Passed checks (2 passed)
Check name Status Explanation
Title Check ✅ Passed The pull request title "fix(session): correct fresh flag logic in getSession" is specific, clear, and directly related to the main change in the changeset. It concisely summarizes the bug fix for inverted logic in the fresh flag initialization without vague phrasing. A teammate scanning the repository history would immediately understand that this addresses a session middleware bug related to the fresh flag logic in the getSession function.
Docstring Coverage ✅ Passed Docstring coverage is 80.00% which is sufficient. The required threshold is 80.00%.
✨ 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 fix/session-fresh-flag-bug

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
Copy link
Contributor

Summary of Changes

Hello @sixcolors, 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 addresses a critical bug in the session middleware's fresh flag logic that caused Fresh() to return an incorrect value under specific conditions. Previously, an existing session could be mistakenly identified as 'fresh' if its ID was found in the request's local context, particularly when getSession() was invoked multiple times. The fix ensures that the fresh flag accurately reflects whether a session is truly new or has been regenerated, thereby restoring correct session state detection and preventing issues in scenarios such as CSRF validation.

Highlights

  • Bug Fix: Incorrect Fresh Flag Logic: Resolved a bug in the session middleware where the fresh flag was incorrectly set to true when a session ID was found in context locals, leading to Fresh() returning an incorrect value for existing sessions, especially when getSession() was called multiple times within a single request.
  • Corrected Fresh Flag Assignment: The fresh flag initialization in getSession() was changed from fresh := ok to fresh := false. This ensures fresh is only set to true when a new session is genuinely created (via acquireSession()) or regenerated (via refresh()), aligning with expected behavior.
  • New Comprehensive Tests Added: Three new tests (Test_Session_Fresh_Flag_Bug, Test_Session_CSRF_Scenario, Test_Session_Multiple_GetSession_Calls) were introduced to thoroughly verify the fix, covering scenarios like multiple getSession() calls, CSRF validation, and expired sessions.
  • Existing Test Updated: The Test_Session_Cookie_In_Middleware_Chain test was updated to reflect the correct fresh flag expectation for an existing session, changing require.True(t, sess.Fresh()) to require.False(t, sess.Fresh()).
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.

Copy link
Contributor

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

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 effectively addresses a logic bug in the fresh flag of the session middleware. The fix is straightforward and correct, ensuring that sessions are only marked as 'fresh' when a new session ID is generated. The addition of comprehensive tests is commendable, as they thoroughly verify the corrected behavior and cover various scenarios, including the user-reported CSRF issue. I have one minor suggestion to improve one of the new tests by removing an unnecessary delay.

Comment on lines +1633 to +1634
// Small delay to ensure save completes
time.Sleep(10 * time.Millisecond)
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The memory.New() storage provider used in these tests operates synchronously. The Set operation completes before returning, so this time.Sleep is not necessary to ensure the save operation has finished. Removing it will make the test slightly faster and avoid potential confusion about the storage provider's behavior.

@codecov
Copy link

codecov bot commented Oct 28, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 92.18%. Comparing base (83cc132) to head (919fd56).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3825      +/-   ##
==========================================
- Coverage   92.20%   92.18%   -0.03%     
==========================================
  Files         115      115              
  Lines        9671     9671              
==========================================
- Hits         8917     8915       -2     
- Misses        482      483       +1     
- Partials      272      273       +1     
Flag Coverage Δ
unittests 92.18% <100.00%> (-0.03%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ 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.

Copy link
Contributor

Copilot AI left a comment

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 fixes a bug in the session middleware where the fresh flag was incorrectly set to true when getSession() was called multiple times within the same request. The bug occurred because the session ID stored in context locals was interpreted as a fresh session.

  • Changed the fresh flag initialization from fresh := ok to fresh := false in the getSession() method
  • Updated an existing test assertion to reflect the correct behavior (session should not be fresh when it has existing data)
  • Added three comprehensive test cases to verify the fix and prevent regression

Reviewed Changes

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

File Description
middleware/session/store.go Fixed the fresh flag logic to only set it to true when a new session ID is generated
middleware/session/session_test.go Updated one test assertion and added three new test cases to verify the fix

Copy link
Contributor

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

♻️ Duplicate comments (1)
middleware/session/session_test.go (1)

1633-1634: Remove unnecessary sleep.

The memory.New() storage provider operates synchronously - the Save() operation completes before returning. This sleep is unnecessary and can be removed.

Apply this diff:

-	// Small delay to ensure save completes
-	time.Sleep(10 * time.Millisecond)
-
 	// Simulate: POST request with valid session (before expiration)
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 432d56f and 96fb215.

📒 Files selected for processing (1)
  • middleware/session/session_test.go (2 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.go

📄 CodeRabbit inference engine (AGENTS.md)

**/*.go: Apply formatting using gofumpt (Make target: format)
Optimize struct field alignment using betteralign (Make target: betteralign)
Modernize code using gopls modernize (Make target: modernize)

Files:

  • middleware/session/session_test.go
🧠 Learnings (1)
📚 Learning: 2024-06-30T00:38:06.580Z
Learnt from: sixcolors
PR: gofiber/fiber#3051
File: middleware/session/session.go:215-216
Timestamp: 2024-06-30T00:38:06.580Z
Learning: Parallel tests for `Session.Save` already exist in the `middleware/session/session_test.go` file, specifically in the `Test_Session_Save` and `Test_Session_Save_Expiration` functions.

Applied to files:

  • middleware/session/session_test.go
🧬 Code graph analysis (1)
middleware/session/session_test.go (3)
middleware/session/store.go (1)
  • NewStore (46-64)
middleware/csrf/csrf.go (1)
  • New (47-214)
middleware/session/config.go (1)
  • Config (13-90)
🪛 GitHub Actions: golangci-lint
middleware/session/session_test.go

[error] 1071-1071: golangci-lint: File is not properly formatted (gofmt).

🪛 GitHub Check: lint
middleware/session/session_test.go

[failure] 1071-1071:
File is not properly formatted (gofmt)

⏰ 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). (3)
  • GitHub Check: unit (1.25.x, windows-latest)
  • GitHub Check: repeated
  • GitHub Check: Compare
🔇 Additional comments (2)
middleware/session/session_test.go (2)

1557-1607: Excellent test coverage for the fresh flag bug.

This test comprehensively validates the fix by covering all relevant scenarios: initial fresh session, existing non-fresh session, the critical bug case (multiple getSession calls in same request), and the expired session edge case.


1668-1718: Excellent targeted test for the bug scenario.

This test precisely validates the fix by simulating the exact conditions that triggered the bug: multiple getSession() calls within the same request where the session ID gets stored in context locals. The progressive verification across three calls ensures the fix is robust.

Copy link
Contributor

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

🧹 Nitpick comments (1)
middleware/session/session_test.go (1)

1633-1634: Consider removing unnecessary sleep.

The memory.New() storage provider operates synchronously - the Set operation completes before Save() returns. This sleep is not needed to ensure data persistence.

Apply this diff to remove the unnecessary delay:

 	sess1.Release()
 	app.ReleaseCtx(ctx1)
 
-	// Small delay to ensure save completes
-	time.Sleep(10 * time.Millisecond)
-
 	// Simulate: POST request with valid session (before expiration)
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 96fb215 and 919fd56.

📒 Files selected for processing (1)
  • middleware/session/session_test.go (2 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.go

📄 CodeRabbit inference engine (AGENTS.md)

**/*.go: Apply formatting using gofumpt (Make target: format)
Optimize struct field alignment using betteralign (Make target: betteralign)
Modernize code using gopls modernize (Make target: modernize)

Files:

  • middleware/session/session_test.go
🧠 Learnings (1)
📚 Learning: 2024-06-30T00:38:06.580Z
Learnt from: sixcolors
PR: gofiber/fiber#3051
File: middleware/session/session.go:215-216
Timestamp: 2024-06-30T00:38:06.580Z
Learning: Parallel tests for `Session.Save` already exist in the `middleware/session/session_test.go` file, specifically in the `Test_Session_Save` and `Test_Session_Save_Expiration` functions.

Applied to files:

  • middleware/session/session_test.go
🧬 Code graph analysis (1)
middleware/session/session_test.go (2)
middleware/session/store.go (1)
  • NewStore (46-64)
middleware/session/config.go (1)
  • Config (13-90)
⏰ 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). (3)
  • GitHub Check: Compare
  • GitHub Check: unit (1.25.x, windows-latest)
  • GitHub Check: repeated
🔇 Additional comments (4)
middleware/session/session_test.go (4)

1071-1071: LGTM - Correct expectation after bug fix.

The assertion correctly expects Fresh() to return false when the second Get() call reuses the session ID from context locals. This aligns with the PR's fix that ensures fresh is only true when a session is newly created via ID generation.


1557-1607: Well-structured test covering the fresh flag bug scenarios.

This test thoroughly validates the fresh flag behavior across multiple scenarios:

  • Fresh sessions on initial creation
  • Non-fresh sessions when loading existing data
  • Critical bug scenario: repeated getSession() calls maintaining non-fresh state
  • Fresh sessions after expiration/missing data

The test properly manages context and session lifecycles with appropriate cleanup.


1609-1666: Solid CSRF scenario test with one minor optimization opportunity.

The test effectively simulates the user-reported CSRF + session interaction, validating that sessions remain non-fresh when valid and become fresh after expiration with a new ID.


1668-1718: Excellent test for the core bug scenario.

This test directly validates the fix for the fresh flag bug by calling getSession() multiple times within the same request context. It ensures the session remains non-fresh across calls when the ID is found in context locals - the exact scenario that was broken before the fix.

The test properly:

  • Verifies session state persistence across calls
  • Validates ID consistency
  • Ensures data integrity
  • Manages session and context lifecycle correctly

@gaby
Copy link
Member

gaby commented Oct 29, 2025

@codex review

@gaby gaby added the v3 label Oct 29, 2025
@gaby gaby added this to v3 Oct 29, 2025
@gaby gaby added this to the v3 milestone Oct 29, 2025
@gaby gaby moved this to In Progress in v3 Oct 29, 2025
@chatgpt-codex-connector
Copy link

Codex Review: Didn't find any major issues. Hooray!

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ReneWerner87 ReneWerner87 merged commit cbf8efd into main Oct 29, 2025
15 checks passed
@ReneWerner87 ReneWerner87 deleted the fix/session-fresh-flag-bug branch October 29, 2025 13:57
@github-project-automation github-project-automation bot moved this from In Progress to Done in v3 Oct 29, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

4 participants