From b6d8baebc1ae99f06ea31a75e99c4a0f0008fd60 Mon Sep 17 00:00:00 2001 From: Mikael Finstad Date: Fri, 13 Mar 2026 21:18:31 +0800 Subject: [PATCH 1/6] Update Dockerfile for node:22-alpine and dependencies Updated base image version to node:22-alpine and modified build dependencies handling. --- Dockerfile | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/Dockerfile b/Dockerfile index 5ce604c25..eab832cfe 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM node:22.18.0-alpine AS build +FROM node:22-alpine AS build # Create link to node on amd64 so that corepack can find it RUN if [ "$(uname -m)" == "aarch64" ]; then mkdir -p /usr/local/sbin/ && ln -s /usr/local/bin/node /usr/local/sbin/node; fi @@ -7,17 +7,19 @@ WORKDIR /app COPY . /app/ -RUN apk --update add --virtual native-dep \ - make gcc g++ python3 libgcc libstdc++ git && \ +# Ensure corepack is enabled (available in official Node images) and +# install only build-time dependencies using a named virtual package. +RUN corepack enable && \ + apk add --no-cache --virtual .build-deps build-base python3 libgcc libstdc++ git && \ (cd /app && corepack yarn workspaces focus @uppy/companion) && \ - apk del native-dep + apk del .build-deps RUN cd /app && corepack yarn workspace @uppy/companion build # Now remove all non-prod dependencies for a leaner image RUN cd /app && corepack yarn workspaces focus @uppy/companion --production -FROM node:22.18.0-alpine +FROM node:22-alpine WORKDIR /app From 635106e0d428f80d0666b3ea027075b218692ffe Mon Sep 17 00:00:00 2001 From: Mikael Finstad Date: Fri, 13 Mar 2026 22:52:07 +0800 Subject: [PATCH 2/6] Change Node.js version to 22.22.1-alpine Updated Node.js base image version in Dockerfile. --- Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index eab832cfe..0845d4987 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM node:22-alpine AS build +FROM node:22.22.1-alpine AS build # Create link to node on amd64 so that corepack can find it RUN if [ "$(uname -m)" == "aarch64" ]; then mkdir -p /usr/local/sbin/ && ln -s /usr/local/bin/node /usr/local/sbin/node; fi @@ -19,7 +19,7 @@ RUN cd /app && corepack yarn workspace @uppy/companion build # Now remove all non-prod dependencies for a leaner image RUN cd /app && corepack yarn workspaces focus @uppy/companion --production -FROM node:22-alpine +FROM node:22.22.1-alpine WORKDIR /app From 2606237064c210f014c9d6e525538fc387d801c0 Mon Sep 17 00:00:00 2001 From: Mikael Finstad Date: Tue, 23 Jun 2026 13:40:00 +0200 Subject: [PATCH 3/6] reduce companion redis key timeouts to 10 min https://github.com/transloadit/api2/pull/8345#pullrequestreview-4552806932 --- packages/@uppy/companion/src/server/Uploader.ts | 5 ++++- packages/@uppy/companion/src/server/helpers/jwt.ts | 2 +- packages/@uppy/companion/src/server/middlewares.ts | 3 ++- packages/@uppy/companion/src/standalone/index.ts | 7 ++++++- 4 files changed, 13 insertions(+), 4 deletions(-) diff --git a/packages/@uppy/companion/src/server/Uploader.ts b/packages/@uppy/companion/src/server/Uploader.ts index fb4e3cea7..d611475a6 100644 --- a/packages/@uppy/companion/src/server/Uploader.ts +++ b/packages/@uppy/companion/src/server/Uploader.ts @@ -602,8 +602,11 @@ export default class Uploader { saveState(state: { action: string; payload: unknown }): void { if (!this.storage) return // make sure the keys get cleaned up. + // We don't need more than 10 minutes because progress events should make sure that it doesn't expire before the upload is done. + // assume that after the upload is done, we don't need it around for long // https://github.com/transloadit/uppy/issues/3748 - const keyExpirySec = 60 * 60 * 24 + // https://github.com/transloadit/api2/pull/8345#pullrequestreview-4552806932 + const keyExpirySec = 60 * 10 const redisKey = `${Uploader.STORAGE_PREFIX}:${this.token}` this.storage.set(redisKey, jsonStringify(state), 'EX', keyExpirySec) } diff --git a/packages/@uppy/companion/src/server/helpers/jwt.ts b/packages/@uppy/companion/src/server/helpers/jwt.ts index 18b30c892..c6540a53c 100644 --- a/packages/@uppy/companion/src/server/helpers/jwt.ts +++ b/packages/@uppy/companion/src/server/helpers/jwt.ts @@ -108,7 +108,7 @@ function getCommonCookieOptions({ return cookieOptions } -const getCookieName = (oauthProvider: string): string => +export const getCookieName = (oauthProvider: string): string => `uppyAuthToken--${oauthProvider}` const addToCookies = ({ diff --git a/packages/@uppy/companion/src/server/middlewares.ts b/packages/@uppy/companion/src/server/middlewares.ts index 92def8aee..3e0a0fb26 100644 --- a/packages/@uppy/companion/src/server/middlewares.ts +++ b/packages/@uppy/companion/src/server/middlewares.ts @@ -6,6 +6,7 @@ import packageJson from '../../package.json' with { type: 'json' } import type { CompanionRuntimeOptions } from '../types/companion-options.js' import type { ProviderUserSession } from '../types/express.js' import * as tokenService from './helpers/jwt.js' +import { getCookieName } from './helpers/jwt.js' import { getURLBuilder } from './helpers/utils.js' import * as logger from './logger.js' import { isOAuthProvider } from './provider/Provider.js' @@ -175,7 +176,7 @@ export const cookieAuthToken: RequestHandler = (req, res, next) => { if (oauthProvider == null || oauthProvider.length === 0) { return next() } - req.companion.authToken = req.cookies[`uppyAuthToken--${oauthProvider}`] + req.companion.authToken = req.cookies[getCookieName(oauthProvider)] return next() } diff --git a/packages/@uppy/companion/src/standalone/index.ts b/packages/@uppy/companion/src/standalone/index.ts index 488fb90a8..7abd45816 100644 --- a/packages/@uppy/companion/src/standalone/index.ts +++ b/packages/@uppy/companion/src/standalone/index.ts @@ -139,7 +139,12 @@ export default function server(inputCompanionOptions?: CompanionInitOptions) { if (process.env['COMPANION_COOKIE_DOMAIN']) { sessionOptions.cookie = { domain: process.env['COMPANION_COOKIE_DOMAIN'], - maxAge: 24 * 60 * 60 * 1000, // 1 day + // AFAIK sessions are only used for the initial oauth2 dance, and not after that. + // Therefore 10 minutes should be plenty of time for the user to complete the oauth2 dance. + // we might want to see if we can make grant work without sessions, so we can remove sessions: + // https://github.com/transloadit/uppy/issues/4394 + // https://github.com/transloadit/api2/pull/8345#pullrequestreview-4552806932 + maxAge: 10 * 60 * 1000, } } From 3b0837463bba7836d72dd456eb726b7ec8142459 Mon Sep 17 00:00:00 2001 From: Mikael Finstad Date: Tue, 23 Jun 2026 13:59:21 +0200 Subject: [PATCH 4/6] Update redis key timeouts to 10 minutes In theory this shouldn't affect users --- .changeset/purple-vans-act.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/purple-vans-act.md diff --git a/.changeset/purple-vans-act.md b/.changeset/purple-vans-act.md new file mode 100644 index 000000000..405236751 --- /dev/null +++ b/.changeset/purple-vans-act.md @@ -0,0 +1,5 @@ +--- +"@uppy/companion": patch +--- + +Reduce companion redis key timeouts to 10 min - In theory this shouldn't affect users From 260623fe3e9a0230a0c89ee8c34ecec729625ee8 Mon Sep 17 00:00:00 2001 From: Mikael Finstad Date: Tue, 23 Jun 2026 15:26:55 +0200 Subject: [PATCH 5/6] fix cookie options bug --- .../@uppy/companion/src/standalone/index.ts | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/packages/@uppy/companion/src/standalone/index.ts b/packages/@uppy/companion/src/standalone/index.ts index 7abd45816..d1466abc6 100644 --- a/packages/@uppy/companion/src/standalone/index.ts +++ b/packages/@uppy/companion/src/standalone/index.ts @@ -136,18 +136,21 @@ export default function server(inputCompanionOptions?: CompanionInitOptions) { }) } - if (process.env['COMPANION_COOKIE_DOMAIN']) { - sessionOptions.cookie = { - domain: process.env['COMPANION_COOKIE_DOMAIN'], - // AFAIK sessions are only used for the initial oauth2 dance, and not after that. - // Therefore 10 minutes should be plenty of time for the user to complete the oauth2 dance. - // we might want to see if we can make grant work without sessions, so we can remove sessions: - // https://github.com/transloadit/uppy/issues/4394 - // https://github.com/transloadit/api2/pull/8345#pullrequestreview-4552806932 - maxAge: 10 * 60 * 1000, - } + const cookieOptions: SessionOptions['cookie'] = { + // AFAIK sessions are only used for the initial oauth2 dance, and not after that. + // Therefore 10 minutes should be plenty of time for the user to complete the oauth2 dance. + // we might want to see if we can make grant work without sessions, so we can remove sessions: + // https://github.com/transloadit/uppy/issues/4394 + // https://github.com/transloadit/api2/pull/8345#pullrequestreview-4552806932 + maxAge: 10 * 60 * 1000, } + if (process.env['COMPANION_COOKIE_DOMAIN']) { + cookieOptions.domain = process.env['COMPANION_COOKIE_DOMAIN']; + } + + sessionOptions.cookie = cookieOptions + // Session is used for grant redirects, so that we don't need to expose secret tokens in URLs // See https://github.com/transloadit/uppy/pull/1668 // https://github.com/transloadit/uppy/issues/3538#issuecomment-1069232909 From a6617feda1f7c2d0fb252961b2f7852e35f3bbb5 Mon Sep 17 00:00:00 2001 From: Mikael Finstad Date: Sun, 28 Jun 2026 01:37:44 +0200 Subject: [PATCH 6/6] Fix cookieOptions domain assignment syntax --- packages/@uppy/companion/src/standalone/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@uppy/companion/src/standalone/index.ts b/packages/@uppy/companion/src/standalone/index.ts index d1466abc6..efaadf036 100644 --- a/packages/@uppy/companion/src/standalone/index.ts +++ b/packages/@uppy/companion/src/standalone/index.ts @@ -146,7 +146,7 @@ export default function server(inputCompanionOptions?: CompanionInitOptions) { } if (process.env['COMPANION_COOKIE_DOMAIN']) { - cookieOptions.domain = process.env['COMPANION_COOKIE_DOMAIN']; + cookieOptions.domain = process.env['COMPANION_COOKIE_DOMAIN'] } sessionOptions.cookie = cookieOptions