Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/bump-patch-1771425547745.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@rocket.chat/meteor': patch
---

Bump @rocket.chat/meteor version.
5 changes: 5 additions & 0 deletions .changeset/nice-glasses-love.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@rocket.chat/meteor': patch
---

Security Hotfix (https://docs.rocket.chat/docs/security-fixes-and-updates)
3 changes: 2 additions & 1 deletion apps/meteor/app/api/server/helpers/parseJsonQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,8 @@ export async function parseJsonQuery(api: GenericRouteExecutionContext): Promise
}
}

if (queryFields && !isValidQuery(query, queryFields || ['*'], queryOperations ?? pathAllowConf.def)) {
const containsQueryFields = queryFields.length > 0;
if (containsQueryFields && !isValidQuery(query, queryFields, queryOperations ?? pathAllowConf.def)) {
throw new Meteor.Error('error-invalid-query', isValidQuery.errors.join('\n'));
}

Expand Down
11 changes: 7 additions & 4 deletions apps/meteor/app/api/server/lib/isValidQuery.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { isRecord } from '@rocket.chat/tools';

import { removeDangerousProps } from './cleanQuery';

type Query = { [k: string]: any };
Expand All @@ -8,7 +10,8 @@ export const isValidQuery: {
} = Object.assign(
(query: Query, allowedAttributes: string[], allowedOperations: string[]): boolean => {
isValidQuery.errors = [];
if (!(query instanceof Object)) {
// query is an object with null prototype, so it wont be instance of Object
if (!isRecord(query)) {
throw new Error('query must be an object');
}

Expand All @@ -21,7 +24,7 @@ export const isValidQuery: {
);

const verifyQuery = (query: Query, allowedAttributes: string[], allowedOperations: string[], parent = ''): boolean => {
return Object.entries(removeDangerousProps(query)).every(([key, value]) => {
return Object.entries(removeDangerousProps({ ...query })).every(([key, value]) => {
const path = parent ? `${parent}.${key}` : key;
if (key.startsWith('$')) {
if (!allowedOperations.includes(key)) {
Expand All @@ -33,7 +36,7 @@ const verifyQuery = (query: Query, allowedAttributes: string[], allowedOperation
return value.every((v) => verifyQuery(v, allowedAttributes, allowedOperations));
}

if (value instanceof Object) {
if (isRecord(value)) {
return verifyQuery(value, allowedAttributes, allowedOperations, path);
}

Expand All @@ -56,7 +59,7 @@ const verifyQuery = (query: Query, allowedAttributes: string[], allowedOperation
return false;
}

if (value instanceof Object) {
if (isRecord(value)) {
return verifyQuery(value, allowedAttributes, allowedOperations, path);
}
return true;
Expand Down
6 changes: 3 additions & 3 deletions apps/meteor/app/api/server/v1/users.ts
Original file line number Diff line number Diff line change
Expand Up @@ -511,8 +511,6 @@ API.v1.addRoute(

const inclusiveFieldsKeys = Object.keys(inclusiveFields);

const hasUserQuery = query && Object.keys(query).length > 0;

const nonEmptyQuery = getNonEmptyQuery(query, await hasPermissionAsync(this.userId, 'view-full-other-user-info'));

// if user provided a query, validate it with their allowed operators
Expand All @@ -528,7 +526,9 @@ API.v1.addRoute(
inclusiveFieldsKeys.includes('type') && 'type.*',
inclusiveFieldsKeys.includes('customFields') && 'customFields.*',
].filter(Boolean) as string[],
hasUserQuery ? this.queryOperations : [...this.queryOperations, '$regex', '$options'],
// At this point, we have already validated the user query not containing malicious fields
// On here we are using our own query so we can allow some extra fields
[...this.queryOperations, '$regex', '$options'],
)
) {
throw new Meteor.Error('error-invalid-query', isValidQuery.errors.join('\n'));
Expand Down
10 changes: 6 additions & 4 deletions apps/meteor/app/file/server/file.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import { NpmModuleMongodb } from 'meteor/npm-mongo';
import mime from 'mime-type/with-db';
import mkdirp from 'mkdirp';

import { sanitizeFileName } from './functions/sanitizeFileName';

const { db } = MongoInternals.defaultRemoteCollectionDriver().mongo;

type IFile = {
Expand Down Expand Up @@ -141,23 +143,23 @@ class FileSystem implements IRocketChatFileStore {
}

createWriteStream(fileName: string) {
const ws = fs.createWriteStream(path.join(this.absolutePath, fileName));
const ws = fs.createWriteStream(path.join(this.absolutePath, sanitizeFileName(fileName)));
ws.on('close', () => {
return ws.emit('end');
});
return ws;
}

createReadStream(fileName: string) {
return fs.createReadStream(path.join(this.absolutePath, fileName));
return fs.createReadStream(path.join(this.absolutePath, sanitizeFileName(fileName)));
}

stat(fileName: string) {
return fsp.stat(path.join(this.absolutePath, fileName));
return fsp.stat(path.join(this.absolutePath, sanitizeFileName(fileName)));
}

async remove(fileName: string) {
return fsp.unlink(path.join(this.absolutePath, fileName));
return fsp.unlink(path.join(this.absolutePath, sanitizeFileName(fileName)));
}

async getFileWithReadStream(fileName: string) {
Expand Down
55 changes: 55 additions & 0 deletions apps/meteor/app/file/server/functions/sanitizeFileName.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { expect } from 'chai';
import { describe, it } from 'mocha';

import { sanitizeFileName } from './sanitizeFileName';

describe('sanitizeFileName', () => {
describe('valid filenames', () => {
it('should allow simple filenames', () => {
const result = sanitizeFileName('sound.mp3');
expect(result).to.equal('sound.mp3');
});

it('should allow filenames with dashes, underscores and dots', () => {
const result = sanitizeFileName('alert_test-01.wav');
expect(result).to.equal('alert_test-01.wav');
});

it('should allow filenames without extension', () => {
const result = sanitizeFileName('beep');
expect(result).to.equal('beep');
});
});

describe('invalid paths', () => {
it('should reject path traversal using ../', () => {
expect(() => sanitizeFileName('../etc/passwd')).to.throw();
});

it('should reject path traversal using ./', () => {
expect(() => sanitizeFileName('./folder/sounds')).to.throw();
});

it('should reject nested paths', () => {
expect(() => sanitizeFileName('sounds/alert.mp3')).to.throw();
});

it('should reject absolute paths', () => {
expect(() => sanitizeFileName('/etc/passwd')).to.throw();
});
});

describe('invalid characters', () => {
it('should reject filenames with spaces', () => {
expect(() => sanitizeFileName('my sound.mp3')).to.throw();
});

it('should reject filenames with special characters', () => {
expect(() => sanitizeFileName('sound$.mp3')).to.throw();
});

it('should reject filenames with backslashes', () => {
expect(() => sanitizeFileName('..\\passwd')).to.throw();
});
});
Comment on lines +6 to +54
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Missing edge-case coverage and weak error-type assertions.

Two gaps worth addressing:

  1. Missing tests for '', '.', and '..' — all currently throw 'error-invalid-file-name' but are not exercised. A test for a valid hidden-style filename like '.hidden' (which does pass today) would also document the intended boundary.

  2. Weak throw assertion.to.throw() passes for any exception including an unexpected TypeError. Scoping to the expected error string removes false-positive risk.

🛡️ Suggested additions
+	describe('edge cases', () => {
+		it('should reject empty string', () => {
+			expect(() => sanitizeFileName('')).to.throw(Error, 'error-invalid-file-name');
+		});
+
+		it('should reject single dot', () => {
+			expect(() => sanitizeFileName('.')).to.throw(Error, 'error-invalid-file-name');
+		});
+
+		it('should reject double dot', () => {
+			expect(() => sanitizeFileName('..')).to.throw(Error, 'error-invalid-file-name');
+		});
+	});

And tighten existing assertions, e.g.:

-		expect(() => sanitizeFileName('../etc/passwd')).to.throw();
+		expect(() => sanitizeFileName('../etc/passwd')).to.throw(Error, 'error-invalid-file-name');
-		expect(() => sanitizeFileName('my sound.mp3')).to.throw();
+		expect(() => sanitizeFileName('my sound.mp3')).to.throw(Error, 'error-invalid-characters-in-file-name');
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/meteor/app/file/server/functions/sanitizeFileName.spec.ts` around lines
6 - 54, Add missing edge-case tests and tighten throw assertions in the
sanitizeFileName spec: add tests that call sanitizeFileName(''),
sanitizeFileName('.'), sanitizeFileName('..') and a positive test for
sanitizeFileName('.hidden'), and update all existing expects that use
.to.throw() to assert the specific error message (e.g.
.to.throw('error-invalid-file-name') or a regex) so failures only pass when the
expected error from sanitizeFileName is thrown; locate and modify the tests in
the sanitizeFileName spec (functions referenced: sanitizeFileName and the
existing it() blocks) to include these cases and replace bare .to.throw() checks
with the scoped error string.

});
19 changes: 19 additions & 0 deletions apps/meteor/app/file/server/functions/sanitizeFileName.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import path from 'path';

export function sanitizeFileName(fileName: string) {
const base = path.basename(fileName);

if (base !== fileName) {
throw new Error('error-invalid-file-name');
}

if (base === '.' || base.startsWith('..')) {
throw new Error('error-invalid-file-name');
}

if (!/^[a-zA-Z0-9._-]+$/.test(base)) {
throw new Error('error-invalid-characters-in-file-name');
}
Comment on lines +14 to +16
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Find all callers that instantiate FileSystem or invoke its IO methods

# 1. Where is RocketChatFile.FileSystem used and what is passed as fileName?
echo "=== RocketChatFile.FileSystem usage ==="
rg -n --type=ts -C 4 'RocketChatFile\.FileSystem\b' --glob '!*.spec.ts' | head -100

# 2. Where are createWriteStream / createReadStream called on FileSystem instances?
echo -e "\n=== FileSystem method calls in apps/meteor/app/file/ ==="
rg -n --type=ts -C 3 'createWriteStream|createReadStream|\.remove\b|\.deleteFile\b' apps/meteor/app/file/ --glob '!*.spec.ts' | head -150

Repository: RocketChat/Rocket.Chat

Length of output: 4907


🏁 Script executed:

#!/bin/bash
# Find who calls createWriteStream and createReadStream on fileStore instances

echo "=== Callers of createWriteStream ==="
rg -n --type=ts 'fileStore\s*\.\s*createWriteStream\(' --glob '!*.spec.ts' -A 2 -B 2 | head -80

echo -e "\n=== Callers of createReadStream ==="
rg -n --type=ts 'fileStore\s*\.\s*createReadStream\(' --glob '!*.spec.ts' -A 2 -B 2 | head -80

echo -e "\n=== Callers of getFileWithReadStream ==="
rg -n --type=ts '\.getFileWithReadStream\(' --glob '!*.spec.ts' -A 2 -B 2 | head -80

Repository: RocketChat/Rocket.Chat

Length of output: 1522


🏁 Script executed:

#!/bin/bash
# Find all usages of createWriteStream across the codebase
echo "=== All createWriteStream callers ==="
rg -n --type=ts 'createWriteStream' apps/meteor --glob '!*.spec.ts' -B 3 -A 1 | head -150

# Find encodeURIComponent usage with file operations
echo -e "\n=== encodeURIComponent with file operations ==="
rg -n --type=ts 'encodeURIComponent.*\.' apps/meteor --glob '!*.spec.ts' -B 2 -A 2

# Check the emoji custom file store usage more broadly
echo -e "\n=== RocketChatFileEmojiCustomInstance usage ==="
rg -n --type=ts 'RocketChatFileEmojiCustomInstance' apps/meteor --glob '!*.spec.ts' -B 2 -A 3

Repository: RocketChat/Rocket.Chat

Length of output: 29005


🏁 Script executed:

#!/bin/bash
# Check what the asset filenames look like and understand the actual impact

echo "=== Asset filenames usage ==="
rg -n --type=ts 'RocketChatAssetsInstance\.' apps/meteor/app/assets/server -B 3 -A 3 | head -100

echo -e "\n=== Importer filenames ==="
rg -n --type=ts 'RocketChatImportFileInstance\.' apps/meteor/app/importer/server -B 2 -A 2 | head -100

# Check if there are any database records of emoji or other files that might have encoded names
echo -e "\n=== Check emoji-custom startup/init ==="
cat apps/meteor/app/emoji-custom/server/startup/emoji-custom.ts 2>/dev/null | head -50

Repository: RocketChat/Rocket.Chat

Length of output: 3404


🏁 Script executed:

#!/bin/bash
# Check what asset keys are used
echo "=== Asset keys/names ==="
rg -n --type=ts 'Assets_' apps/meteor/app/assets/server/assets.ts | head -20

# Check what newFileName is in importer
echo -e "\n=== Importer newFileName source ==="
rg -n --type=ts 'newFileName.*=' apps/meteor/app/importer/server/methods/ -B 3 -A 1 | head -80

# Check emoji-custom initialization
echo -e "\n=== RocketChatFileEmojiCustomInstance type ==="
rg -n --type=ts 'RocketChatFileEmojiCustomInstance\s*=' apps/meteor/app/emoji-custom/ -A 5 | head -30

Repository: RocketChat/Rocket.Chat

Length of output: 1631


🏁 Script executed:

#!/bin/bash
# Verify the actual emoji-custom instance and understand the real scope
echo "=== Emoji custom FileStore type ==="
rg -n --type=ts 'new RocketChatFile' apps/meteor/app/emoji-custom/server/startup/ -B 5 -A 5

# Understand what happens with existing emoji in database
echo -e "\n=== Check emoji-custom schema/model ==="
fd -t f 'emoji.*\.ts' apps/meteor/app/emoji-custom/server/ --type f -exec head -30 {} \;

# Check if sanitizeFileName is called before encodeURIComponent anywhere
echo -e "\n=== Check sanitizeFileName calls ==="
rg -n --type=ts 'sanitizeFileName\(' apps/meteor --glob '!*.spec.ts' -B 2 -A 2 | head -100

Repository: RocketChat/Rocket.Chat

Length of output: 2238


🏁 Script executed:

#!/bin/bash
# Find what RocketChatFileEmojiCustomInstance actually is
echo "=== Find emoji-custom instance definition ==="
rg -n --type=ts 'RocketChatFileEmojiCustomInstance' apps/meteor/app/emoji-custom/server/startup/emoji-custom.ts -A 10 -B 5

# Check all FileSystem instances to understand the storage backends
echo -e "\n=== FileSystem instances ==="
rg -n --type=ts 'new RocketChatFileSystem\|new RocketChatFileMongoDB' apps/meteor/app/file/server/ -B 3 -A 5

# Check where custom sounds FileStore is initialized
echo -e "\n=== Custom sounds FileStore ==="
rg -n --type=ts 'RocketChatFileCustomSoundsInstance\|FileStore' apps/meteor/app/custom-sounds/server/ -B 2 -A 3

Repository: RocketChat/Rocket.Chat

Length of output: 291


🏁 Script executed:

#!/bin/bash
# Find the actual emoji-custom startup file
echo "=== Find emoji-custom startup files ==="
find apps/meteor/app/emoji-custom -name '*.ts' -type f | grep -i startup

# Find RocketChatFileEmojiCustomInstance definition
echo -e "\n=== Find RocketChatFileEmojiCustomInstance ==="
rg -n --type=ts 'RocketChatFileEmojiCustomInstance' apps/meteor/app/emoji-custom --glob '!*.spec.ts' -B 5 -A 5 | head -100

# Find all FileStore definitions
echo -e "\n=== All FileStore definitions ==="
rg -n --type=ts 'const.*FileStore.*=.*new' apps/meteor --glob '!*.spec.ts' -B 2 -A 2 | head -150

Repository: RocketChat/Rocket.Chat

Length of output: 9577


🏁 Script executed:

#!/bin/bash
# Find where RocketChatFileEmojiCustomInstance is exported from
echo "=== Find emoji-custom export ==="
rg -n --type=ts 'export.*RocketChatFileEmojiCustomInstance' apps/meteor/app/emoji-custom -A 5 -B 5

# Find the startup directory
echo -e "\n=== Find emoji-custom server files ==="
find apps/meteor/app/emoji-custom/server -type f -name '*.ts' | head -30

# Search in the entire app for where these instances are created
echo -e "\n=== Search for RocketChatFile instance creation ==="
rg -n --type=ts 'new RocketChatFile' apps/meteor --glob '!*.spec.ts' -B 3 -A 3 | head -150

Repository: RocketChat/Rocket.Chat

Length of output: 1052


🏁 Script executed:

#!/bin/bash
# Check the emoji-custom index.ts
echo "=== emoji-custom index.ts ==="
cat apps/meteor/app/emoji-custom/server/index.ts

# Search for RocketChatFileEmojiCustomInstance initialization across entire codebase
echo -e "\n=== Search for RocketChatFileEmojiCustomInstance initialization ==="
rg -n --type=ts 'RocketChatFileEmojiCustomInstance\s*=' apps/meteor --glob '!*.spec.ts' -B 3 -A 5

# Check imports from 'startup/emoji-custom' module
echo -e "\n=== Files that import from emoji-custom startup ==="
rg -n --type=ts "from.*'.*emoji-custom'" apps/meteor/app/emoji-custom --glob '!*.spec.ts' | grep -i startup

Repository: RocketChat/Rocket.Chat

Length of output: 793


🏁 Script executed:

#!/bin/bash
# The startup file must exist since it's being imported. Let's find it with a broader search
echo "=== Search for emoji-custom.ts files ==="
find apps/meteor/app/emoji-custom -name '*emoji-custom*' -type f

# Also try with git ls-files
echo -e "\n=== git ls-files for emoji-custom ==="
git ls-files apps/meteor/app/emoji-custom | grep -i startup

# If file exists, read it
echo -e "\n=== Read the startup file ==="
if [ -f apps/meteor/app/emoji-custom/server/startup/emoji-custom.ts ]; then
  cat apps/meteor/app/emoji-custom/server/startup/emoji-custom.ts
else
  echo "File not found at expected path"
  # Try to find all .ts files in emoji-custom
  find apps/meteor/app/emoji-custom -type f -name '*.ts'
fi

Repository: RocketChat/Rocket.Chat

Length of output: 694


🏁 Script executed:

#!/bin/bash
# Read the .js startup file
echo "=== Read emoji-custom.js startup ==="
cat apps/meteor/app/emoji-custom/server/startup/emoji-custom.js

# Also check assets startup for comparison
echo -e "\n=== Check assets startup ==="
find apps/meteor/app/assets/server -name '*startup*' -o -name '*assets*' | grep -v node_modules
cat apps/meteor/app/assets/server/assets.ts | head -50

Repository: RocketChat/Rocket.Chat

Length of output: 5248


The strict allowlist regex breaks backward compatibility with encodeURIComponent-encoded filenames.

The regex ^[a-zA-Z0-9._-]+$ rejects the % character, but the codebase passes encoded filenames to FileSystem methods:

  • uploadEmojiCustom.ts:70 calls createWriteStream(encodeURIComponent(...))
  • insertOrUpdateEmoji.ts:114-117 calls deleteFile(encodeURIComponent(...))
  • uploadZipFile.ts:24 uses encodeURIComponent(...) on data export filenames
  • emoji-custom.js:56 calls getFileWithReadStream(encodeURIComponent(...))

Any emoji with non-ASCII or space characters (e.g., "smile 😊", "my sound") will be encoded as smile%20%F0%9F%98%8A, which fails the regex validation. This renders existing files inaccessible and breaks deletion/updates.

The regex should either allow % or callers should sanitize before encoding, not after.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/meteor/app/file/server/functions/sanitizeFileName.ts` around lines 14 -
16, The validation in sanitizeFileName.ts currently rejects percent-encoded
names because the allowlist regex tested against the variable base disallows '%'
— update the validation so percent signs are accepted (i.e., include '%' in the
allowed characters in the regex used in sanitizeFileName) to preserve
compatibility with encodeURIComponent-based callers (functions like
createWriteStream in uploadEmojiCustom.ts, deleteFile callers in
insertOrUpdateEmoji.ts, uploadZipFile.ts, and getFileWithReadStream usage in
emoji-custom.js); alternatively, if you prefer not to change the regex,
decodeURIComponent(base) before running the existing validation, but prefer the
regex change to avoid breaking existing encoded filenames.


return base;
}
2 changes: 1 addition & 1 deletion docker-compose-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ services:
image: kong/httpbin

traefik:
image: traefik:v3.1
image: traefik:v3.6.6
command:
- --providers.docker=true
- '--serverstransport.maxidleconnsperhost=-1'
Expand Down
34 changes: 3 additions & 31 deletions docker-compose-local.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
version: '3.8'

services:
rocketchat:
platform: linux/amd64
build:
dockerfile: apps/meteor/.docker/Dockerfile.alpine
context: /tmp/build
image: ghcr.io/${LOWERCASE_REPOSITORY}/rocket.chat:${DOCKER_TAG}
environment:
- TEST_MODE=true
Expand All @@ -29,10 +24,6 @@ services:

authorization-service:
platform: linux/amd64
build:
dockerfile: ee/apps/authorization-service/Dockerfile
args:
SERVICE: authorization-service
image: ghcr.io/${LOWERCASE_REPOSITORY}/authorization-service:${DOCKER_TAG}
environment:
- 'MONGO_URL=${MONGO_URL}'
Expand All @@ -45,10 +36,6 @@ services:

account-service:
platform: linux/amd64
build:
dockerfile: ee/apps/account-service/Dockerfile
args:
SERVICE: account-service
image: ghcr.io/${LOWERCASE_REPOSITORY}/account-service:${DOCKER_TAG}
environment:
- MONGO_URL=${MONGO_URL}
Expand All @@ -61,10 +48,6 @@ services:

presence-service:
platform: linux/amd64
build:
dockerfile: ee/apps/presence-service/Dockerfile
args:
SERVICE: presence-service
image: ghcr.io/${LOWERCASE_REPOSITORY}/presence-service:${DOCKER_TAG}
environment:
- MONGO_URL=${MONGO_URL}
Expand All @@ -77,10 +60,6 @@ services:

ddp-streamer-service:
platform: linux/amd64
build:
dockerfile: ee/apps/ddp-streamer/Dockerfile
args:
SERVICE: ddp-streamer
image: ghcr.io/${LOWERCASE_REPOSITORY}/ddp-streamer-service:${DOCKER_TAG}
environment:
- MONGO_URL=${MONGO_URL}
Expand All @@ -99,10 +78,6 @@ services:

queue-worker-service:
platform: linux/amd64
build:
dockerfile: ee/apps/queue-worker/Dockerfile
args:
SERVICE: queue-worker
image: ghcr.io/${LOWERCASE_REPOSITORY}/queue-worker-service:${DOCKER_TAG}
environment:
- MONGO_URL=${MONGO_URL}
Expand All @@ -115,10 +90,6 @@ services:

omnichannel-transcript-service:
platform: linux/amd64
build:
dockerfile: ee/apps/omnichannel-transcript/Dockerfile
args:
SERVICE: omnichannel-transcript
image: ghcr.io/${LOWERCASE_REPOSITORY}/omnichannel-transcript-service:${DOCKER_TAG}
environment:
- MONGO_URL=${MONGO_URL}
Expand All @@ -142,7 +113,7 @@ services:
bash -c
"mongod --replSet $$MONGODB_REPLICA_SET_NAME --bind_ip_all &
sleep 2;
until mongosh --eval \"db.adminCommand('ping')\"; do
until mongosh --eval \"db.adminCommand('ping')\"; do
echo '=====> Waiting for Mongo...';
sleep 1;
done;
Expand All @@ -155,9 +126,10 @@ services:
image: nats:2.6-alpine

traefik:
image: traefik:v2.8
image: traefik:v3.6.6
command:
- --providers.docker=true
- '--serverstransport.maxidleconnsperhost=-1'
ports:
- 3000:80
volumes:
Expand Down
Loading
Loading