Skip to content

Update dependency iron-session to v9 - #122

Open
renovate[bot] wants to merge 1 commit into
mainfrom
renovate/iron-session-9.x
Open

renovate[bot] wants to merge 1 commit into
mainfrom
renovate/iron-session-9.x

Conversation

@renovate

@renovate renovate Bot commented Aug 30, 2026

Copy link
Copy Markdown
Contributor

This PR contains the following updates:

Package Change Age Confidence
iron-session ^8.0.4^9.0.0 age confidence

Release Notes

vvo/iron-session (iron-session)

v9.0.1

Compare Source

No code changes. dist/index.js and dist/index.d.ts are byte-for-byte
identical to 9.0.0; only the version number differs.

9.0.0 was published from a laptop because CI could not authenticate with npm,
so its tarball carries no provenance attestation and cannot be verified against a
commit. That is not fixable after the fact: npm versions are immutable. 9.0.1
is the same code published from CI with
provenance, so you can
check it was built from this repository at a known commit:

npm audit signatures

If you are on 9.0.0 and do not care about provenance, there is no reason to
upgrade.

v9.0.0

Compare Source

Install
pnpm add iron-session
pnpm add iron-session@8   # if you are still on Node 20 or need CommonJS
How to upgrade

Requires Node 22.13+, and the package is ESM-only (require() works on Node
22.13+). Two code changes cover most apps:

- session.lastSeen = new Date();   // v8 sealed it as a string
+ session.lastSeen = Date.now();

- const userId = session.user.id;  // empty on a first visit
+ const userId = session.user?.id;

Nothing else is required. getIronSession(req, res, options) and
getIronSession(await cookies(), options) both still work, and v9 reads v8
cookies while v8 reads v9 cookies, so a deploy rolls back without signing
everyone out. Delete any as any you had on await cookies().

Full guide, including removed APIs: MIGRATION.md.

⚠ BREAKING CHANGES
  • Node 22.13 or later is required. Node 20 reached end of life in April 2026.
  • The package is ESM-only. require() still works on Node 22.13+, which
    supports require() of an ES module.
  • Date values can no longer be stored in a session. v8 turned them into an
    ISO string when sealing and returned a string when reading, so the type you
    wrote was not the type you got back. Store Date.now() instead.
  • IronSession<T> properties are optional on read. A session that does not
    exist yet is an empty object, so the old type let session.user.id compile
    and then throw (#​661).
  • Writing to a session after destroy() and then saving throws. A bare
    save() after destroy() is ignored, so logout handlers that call both keep
    working. Before, that save re-sealed the session and the browser kept the last
    Set-Cookie, so the logout silently did not happen.
  • updateConfig() validates and applies a new password. Passing one used to
    be ignored: it kept sealing with the old password and skipped the 32-character
    check.
  • cookieOptions.expires in the past is rejected when saving. A Date built
    once at module scope drifts into the past, and the browser then discards every
    cookie. Reading a session never sets a cookie, so reads are unaffected.
  • Pre-v8 cookies are no longer read, so those users sign in once more. The
    format was chosen by a version marker outside the seal's signature, which made
    it attacker-controlled.
  • createSealData, createUnsealData and createGetIronSession are removed.
    They existed to inject a crypto implementation. Import sealData,
    unsealData and getIronSession directly.
  • uncrypto is no longer a dependency.
Features
  • cookie adapters: nodeCookies, webCookies and nextProxyCookies. The last
    one makes sessions work in Next.js proxy.ts / middleware.ts, including
    rotation visible to the same request
    (#​887,
    #​938,
    #​709,
    #​684)
  • chunk: true splits a session that does not fit in one cookie across several,
    capped at 4 because the Cookie request header is the real limit. Based on the
    approach in #​937 by
    @​sefasenturk95
  • onUnsealError(reason, error) reports why a cookie was rejected, as
    "expired", "invalid" or "unknown-password". A broken password rotation
    used to be completely silent
  • cookie 2 and iron-webcrypto 2
  • CI runs the suite on Node 22/24/26, Bun and Deno. Runtime-specific reports were
    previously impossible for us to reproduce
  • SECURITY.md
Bug Fixes
  • getIronSession(await cookies(), options) typechecks without a cast. Our
    CookieStore.set was an overload pair while Next declares a single signature
    over a tuple union, so as any on the session that guards your
    app was the only thing that worked (#​840)
  • a ttl shorter than the 60s clock skew keeps its full Max-Age. It used to
    produce Max-Age=0 or a negative value, so the browser dropped the cookie on
    arrival while save() reported success
  • the "not JSON serializable" error names the value it choked on, for example
    (session.user.lastSeen is a Date), instead of leaving you to find it
  • an unreadable cookie always starts a fresh session. Two reachable
    iron-webcrypto messages, Wrong mac prefix and Invalid expiration, escaped
    the old error allowlist and threw a 500 on every request from a browser
    holding that cookie, which is HttpOnly so the app could not clear it
  • getRandomValues is not a function under Turbopack. The runtime always had
    WebCrypto, the bundler resolved the wrong uncrypto export condition
    (#​898)
  • a ttl between 1 and 60 produced Max-Age=0 or a negative value, so the
    browser dropped the cookie on arrival while save() reported success
  • both calling conventions measure the cookie size the same way, in UTF-8 bytes
    on the real Set-Cookie header. One of them used to add up
    name.length + seal.length + JSON.stringify(options).length
  • the version marker on a seal can no longer select a code path. Flipping ~2 to
    ~1 on a genuine cookie used to reshape the session without the password
  • an empty or non-integer-keyed password map fails with a message that says what
    to do, instead of an opaque error from the crypto layer
Internal
  • one session implementation behind a CookieJar, replacing two copies of the
    read/save/destroy logic that had drifted apart
  • oxlint and oxfmt replace eslint, 6 plugins and prettier. Lint goes from
    seconds to ~0.2s and 12 devDependencies are removed
  • typescript 7, tsdown, node's built-in test coverage. turbo and c8 are gone
  • CI has permissions: contents: read, actions pinned by commit SHA,
    --frozen-lockfile, and renovate no longer automerges
  • type-tests/ typechecks against the real next/headers and next/server
    types, so a Next release breaks our CI instead of a user's build
  • coverage on core.ts is 97.4%, up from 85.9%. The cookie-store path had no
    tests at all

Configuration

📅 Schedule: (UTC)

  • Branch creation
    • At any time (no schedule defined)
  • Automerge
    • At any time (no schedule defined)

🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.

Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 Ignore: Close this PR and you won't be reminded about this update again.


  • If you want to rebase/retry this PR, check this box

This PR was generated by Mend Renovate. View the repository job log.

Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
@renovate
renovate Bot force-pushed the renovate/iron-session-9.x branch from 5959832 to 454b2fa Compare September 2, 2026 22:51
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.

0 participants