Compare commits

..

2 Commits

Author SHA1 Message Date
lebaudantoine 80dfaf43dc 🔒️(frontend) upgrade base image to 1.30.4-alpine3.24
Bump the frontend base image to `1.30.4-alpine3.24`, which picks up
fixes for the CVEs listed below and lets us drop the individual
dependency pins that were only there to address earlier known CVEs.

Address the following HIGH severity CVEs in libuuid / util-linux,
reported by Trivy. Bumping to 2.41.6-r1 (bundled in the new base
image) covers all of them:

* CVE-2026-53612 — TOCTOU in mount post-mount ownership/mode
  changes.
* CVE-2026-53613 — TOCTOU in mount via ancestor directory swap.
* CVE-2026-53614 — SUID mount(8) nosuid/noexec bypass via
  LIBMOUNT_FORCE_MOUNT2.
* CVE-2026-76642 — failed external mount helper still runs
  privileged X-mount post-hooks.
* CVE-2026-78408 — nsenter --join-cgroup leaks root cgroup
  migration authority (fixed in 2.41.6-r1).
* CVE-2026-78410 — restricted bind mounts do not pin the source,
  allowing X-mount.owner/group/mode escalation.
2026-09-07 16:07:42 +02:00
lebaudantoine 2a59b55128 🐛(frontend) keep feedback buttons on one line for fr/es/en
A minor layout regression appeared when switching to the Marianne
font: the feedback buttons wrapped onto two lines instead of
staying on one.

Adjust the layout so the buttons stay on a single line regardless
of the font in use.
2026-09-07 16:07:34 +02:00
6 changed files with 8 additions and 125 deletions
+2 -1
View File
@@ -17,6 +17,7 @@ and this project adheres to
### Changed ### Changed
- ⬆️(dev) pin LiveKit server to v1.13.6 - ⬆️(dev) pin LiveKit server to v1.13.6
- 🔒(frontend) upgrade base image to 1.30.4-alpine3.24
### Fixed ### Fixed
@@ -24,7 +25,7 @@ and this project adheres to
- 🐛(frontend) keep the sending resolution picked while the camera is off #1667 - 🐛(frontend) keep the sending resolution picked while the camera is off #1667
- 🐛(frontend) restore automatic lower-hand on speaking - 🐛(frontend) restore automatic lower-hand on speaking
- 🐛(frontend) center Avatar initials with a font-aware cap-height ratio - 🐛(frontend) center Avatar initials with a font-aware cap-height ratio
- 🔒️(backend) reject inactive users in resource server backend - 🐛(frontend) keep feedback buttons on one line for fr/es/en
## [1.30.0] - 2026-09-01 ## [1.30.0] - 2026-09-01
+3 -11
View File
@@ -54,19 +54,11 @@ RUN npx webpack --mode production
# ---- Front-end image ---- # ---- Front-end image ----
FROM nginxinc/nginx-unprivileged:1.30.3-alpine3.23 AS frontend-production FROM nginxinc/nginx-unprivileged:1.30.4-alpine3.24 AS frontend-production
USER root USER root
RUN apk del curl
# Security patches for known CVEs USER nginx
RUN apk update && apk upgrade \
libcrypto3>=3.5.7-r0 \
libssl3>=3.5.7-r0 \
musl \
musl-utils \
zlib>=1.3.2-r0 \
libexpat>=2.8.4-r0 \
&& apk del curl
USER nginx USER nginx
@@ -286,10 +286,6 @@ class ResourceServerBackend(LaSuiteBackend):
if user is None and settings.OIDC_CREATE_USER: if user is None and settings.OIDC_CREATE_USER:
user = self.create_user(sub) user = self.create_user(sub)
if user is not None and not user.is_active:
logger.warning("Inactive user attempted authentication: %s", user.pk)
raise SuspiciousOperation("User account is disabled.")
return user return user
def create_user(self, sub): def create_user(self, sub):
@@ -1,96 +0,0 @@
"""Tests for the external API ResourceServerBackend."""
from django.core.exceptions import SuspiciousOperation
import pytest
import responses
from rest_framework.test import APIClient
from core.external_api.authentication import ResourceServerBackend
from core.factories import UserFactory
from core.models import User
pytestmark = pytest.mark.django_db
def _payload(sub):
return {"sub": sub, "active": True, "scope": "lasuite_meet", "client_id": "app"}
def test_resource_server_backend_get_or_create_user_active():
"""An existing active user matching the sub should be returned."""
user = UserFactory()
result = ResourceServerBackend().get_or_create_user(
access_token="token", id_token=None, payload=_payload(user.sub)
)
assert result == user
def test_resource_server_backend_get_or_create_user_inactive():
"""An inactive user should be rejected even with a valid token."""
user = UserFactory(is_active=False)
with pytest.raises(SuspiciousOperation, match="User account is disabled."):
ResourceServerBackend().get_or_create_user(
access_token="token", id_token=None, payload=_payload(user.sub)
)
def test_resource_server_backend_get_or_create_user_creates(settings):
"""An unknown sub should create an active user when OIDC_CREATE_USER is set."""
settings.OIDC_CREATE_USER = True
result = ResourceServerBackend().get_or_create_user(
access_token="token", id_token=None, payload=_payload("new-sub")
)
assert result.sub == "new-sub"
assert result.is_active is True
assert User.objects.filter(sub="new-sub").exists()
def test_resource_server_backend_get_or_create_user_no_creation(settings):
"""An unknown sub should return None when OIDC_CREATE_USER is unset."""
settings.OIDC_CREATE_USER = False
result = ResourceServerBackend().get_or_create_user(
access_token="token", id_token=None, payload=_payload("new-sub")
)
assert result is None
assert not User.objects.filter(sub="new-sub").exists()
@responses.activate
def test_api_rooms_list_resource_server_inactive_user(settings):
"""End to end: a valid introspected token for an inactive user should get 401."""
settings.OIDC_OP_INTROSPECTION_ENDPOINT = "https://oidc.example.com/introspect"
settings.OIDC_OP_URL = "https://oidc.example.com"
user = UserFactory(is_active=False)
responses.add(
responses.POST,
"https://oidc.example.com/introspect",
json={
"iss": "https://oidc.example.com",
"active": True,
"sub": user.sub,
"scope": "lasuite_meet",
"client_id": "app",
},
)
client = APIClient()
client.credentials(HTTP_AUTHORIZATION="Bearer rs-token")
response = client.get("/external-api/v1.0/rooms/")
assert response.status_code == 401
assert "login failed" in str(response.data).lower()
+2 -12
View File
@@ -42,20 +42,10 @@ ENV VITE_APP_TITLE=${VITE_APP_TITLE}
RUN npm run build RUN npm run build
# ---- Front-end image ---- # ---- Front-end image ----
FROM nginxinc/nginx-unprivileged:1.30.3-alpine3.23 AS frontend-production FROM nginxinc/nginx-unprivileged:1.30.4-alpine3.24 AS frontend-production
USER root USER root
RUN apk del curl
# Security patches for known CVEs
RUN apk update && apk upgrade \
libcrypto3>=3.5.7-r0 \
libssl3>=3.5.7-r0 \
musl \
musl-utils \
zlib>=1.3.2-r0 \
libexpat>=2.8.4-r0 \
&& apk del curl
USER nginx USER nginx
# Un-privileged user running the application # Un-privileged user running the application
@@ -65,7 +65,7 @@ const FeedbackRoute = () => {
<Stack <Stack
direction={{ base: 'column', xsm: 'row' }} direction={{ base: 'column', xsm: 'row' }}
width={{ base: '100%', xsm: 'auto' }} width={{ base: '100%', xsm: 'auto' }}
maxWidth="380px" maxWidth="410px"
> >
{showBackButton && ( {showBackButton && (
<Button <Button