diff --git a/pkgs/by-name/zi/zitadel/2.42.x-CVE-2024-41953.patch b/pkgs/by-name/zi/zitadel/2.42.x-CVE-2024-41953.patch
new file mode 100644
index 0000000000000..9616355b78bd7
--- /dev/null
+++ b/pkgs/by-name/zi/zitadel/2.42.x-CVE-2024-41953.patch
@@ -0,0 +1,282 @@
+Based on upstream 4b59cac67bb89c1f3f84a2041dd273d11151d29f, adjusted to
+apply to 2.42.x
+
+diff --git a/console/src/app/modules/top-view/top-view.component.html b/console/src/app/modules/top-view/top-view.component.html
+index 65e68dec7..7ef4c27e1 100644
+--- a/console/src/app/modules/top-view/top-view.component.html
++++ b/console/src/app/modules/top-view/top-view.component.html
+@@ -16,7 +16,7 @@
+ >
+
+
+-
++
{{ sub }}
+
+ info_outline
+
+diff --git a/console/src/app/pages/projects/granted-projects/granted-project-detail/granted-project-detail.component.html b/console/src/app/pages/projects/granted-projects/granted-project-detail/granted-project-detail.component.html
+index c04e428d0..17a41cce9 100644
+--- a/console/src/app/pages/projects/granted-projects/granted-project-detail/granted-project-detail.component.html
++++ b/console/src/app/pages/projects/granted-projects/granted-project-detail/granted-project-detail.component.html
+@@ -2,9 +2,7 @@
+ title="{{ project?.projectName }}"
+ [hasActions]="false"
+ docLink="https://zitadel.com/docs/guides/manage/console/projects#what-is-a-granted-project"
+- sub="{{ 'PROJECT.PAGES.TYPE.GRANTED_SINGULAR' | translate }} {{ 'ACTIONS.OF' | translate }}
{{
+- project?.projectOwnerName
+- }}"
++ sub="{{ 'PROJECT.PAGES.TYPE.GRANTED_SINGULAR' | translate: { name: project?.projectOwnerName } }}"
+ [isActive]="project?.state === ProjectGrantState.PROJECT_GRANT_STATE_ACTIVE"
+ [isInactive]="project?.state === ProjectGrantState.PROJECT_GRANT_STATE_INACTIVE"
+ stateTooltip="{{ 'ORG.STATE.' + project?.state | translate }}"
+diff --git a/console/src/assets/i18n/bg.json b/console/src/assets/i18n/bg.json
+index e2821f14c..734d137d3 100644
+--- a/console/src/assets/i18n/bg.json
++++ b/console/src/assets/i18n/bg.json
+@@ -1456,7 +1456,7 @@
+ "OWNED": "Притежавани проекти",
+ "GRANTED": "Предоставени проекти",
+ "OWNED_SINGULAR": "Собствен проект",
+- "GRANTED_SINGULAR": "Приет проект"
++ "GRANTED_SINGULAR": "Отпуснат проект на {{name}}"
+ },
+ "PRIVATELABEL": {
+ "0": {
+diff --git a/console/src/assets/i18n/cs.json b/console/src/assets/i18n/cs.json
+index b734a58f6..6ac6a7db8 100644
+--- a/console/src/assets/i18n/cs.json
++++ b/console/src/assets/i18n/cs.json
+@@ -1463,7 +1463,7 @@
+ "OWNED": "Vlastní projekty",
+ "GRANTED": "Přidělené projekty",
+ "OWNED_SINGULAR": "Vlastní projekt",
+- "GRANTED_SINGULAR": "Přidělený projekt"
++ "GRANTED_SINGULAR": "Projekt přidělený {{name}}"
+ },
+ "PRIVATELABEL": {
+ "TITLE": "Nastavení brandingu",
+diff --git a/console/src/assets/i18n/de.json b/console/src/assets/i18n/de.json
+index 8685ee4bb..aa377a819 100644
+--- a/console/src/assets/i18n/de.json
++++ b/console/src/assets/i18n/de.json
+@@ -1462,7 +1462,7 @@
+ "OWNED": "Eigene Projekte",
+ "GRANTED": "Berechtigte Projekte",
+ "OWNED_SINGULAR": "Eigenes Projekt",
+- "GRANTED_SINGULAR": "Berechtigtes Projekt"
++ "GRANTED_SINGULAR": "Berechtigtes Projekt von {{name}}"
+ },
+ "PRIVATELABEL": {
+ "TITLE": "Branding Verhalten",
+diff --git a/console/src/assets/i18n/en.json b/console/src/assets/i18n/en.json
+index 0af6455fe..87a945bb9 100644
+--- a/console/src/assets/i18n/en.json
++++ b/console/src/assets/i18n/en.json
+@@ -1463,7 +1463,7 @@
+ "OWNED": "Owned Projects",
+ "GRANTED": "Granted Projects",
+ "OWNED_SINGULAR": "Owned Project",
+- "GRANTED_SINGULAR": "Granted Project"
++ "GRANTED_SINGULAR": "Granted Project of {{name}}"
+ },
+ "PRIVATELABEL": {
+ "TITLE": "Branding Setting",
+diff --git a/console/src/assets/i18n/es.json b/console/src/assets/i18n/es.json
+index 7b4a338a0..e1aa7a75c 100644
+--- a/console/src/assets/i18n/es.json
++++ b/console/src/assets/i18n/es.json
+@@ -1463,7 +1463,7 @@
+ "OWNED": "Proyectos propios",
+ "GRANTED": "Proyectos concedidos",
+ "OWNED_SINGULAR": "Proyecto propio",
+- "GRANTED_SINGULAR": "Proyecto concedido"
++ "GRANTED_SINGULAR": "Proyecto asignado {{name}}"
+ },
+ "PRIVATELABEL": {
+ "TITLE": "Ajustes de imagen de marca",
+diff --git a/console/src/assets/i18n/fr.json b/console/src/assets/i18n/fr.json
+index aa293ba4b..00671f6ec 100644
+--- a/console/src/assets/i18n/fr.json
++++ b/console/src/assets/i18n/fr.json
+@@ -1462,7 +1462,7 @@
+ "OWNED": "Projets possédés",
+ "GRANTED": "Projets accordés",
+ "OWNED_SINGULAR": "Projet propre",
+- "GRANTED_SINGULAR": "Projet concédé"
++ "GRANTED_SINGULAR": "Projet attribué à {{name}}"
+ },
+ "PRIVATELABEL": {
+ "TITLE": "Image de marque",
+diff --git a/console/src/assets/i18n/it.json b/console/src/assets/i18n/it.json
+index caca5f6fc..38423509c 100644
+--- a/console/src/assets/i18n/it.json
++++ b/console/src/assets/i18n/it.json
+@@ -1462,7 +1462,7 @@
+ "OWNED": "Progetti proprietari",
+ "GRANTED": "Progetti delegati",
+ "OWNED_SINGULAR": "Progetto proprietario",
+- "GRANTED_SINGULAR": "Progetto delegato"
++ "GRANTED_SINGULAR": "Progetto concesso di {{name}}"
+ },
+ "PRIVATELABEL": {
+ "TITLE": "Impostazione branding",
+diff --git a/console/src/assets/i18n/ja.json b/console/src/assets/i18n/ja.json
+index 527bf018f..bdba247cb 100644
+--- a/console/src/assets/i18n/ja.json
++++ b/console/src/assets/i18n/ja.json
+@@ -1458,7 +1458,7 @@
+ "OWNED": "所有プロジェクト",
+ "GRANTED": "グラントされたプロジェクト",
+ "OWNED_SINGULAR": "所有プロジェクト",
+- "GRANTED_SINGULAR": "グラントされたプロジェクト"
++ "GRANTED_SINGULAR": "{{name}}に付与されたプロジェクト"
+ },
+ "PRIVATELABEL": {
+ "TITLE": "ブランディング設定",
+diff --git a/console/src/assets/i18n/mk.json b/console/src/assets/i18n/mk.json
+index 4f6df0710..62c536f34 100644
+--- a/console/src/assets/i18n/mk.json
++++ b/console/src/assets/i18n/mk.json
+@@ -1464,7 +1464,7 @@
+ "OWNED": "Сопствени проекти",
+ "GRANTED": "Доделени проекти",
+ "OWNED_SINGULAR": "Сопствен проект",
+- "GRANTED_SINGULAR": "Доделен проект"
++ "GRANTED_SINGULAR": "Проект доделен на {{name}}"
+ },
+ "PRIVATELABEL": {
+ "TITLE": "Подесувања за брендирање",
+diff --git a/console/src/assets/i18n/nl.json b/console/src/assets/i18n/nl.json
+index db071c2f4..70bd9acb0 100644
+--- a/console/src/assets/i18n/nl.json
++++ b/console/src/assets/i18n/nl.json
+@@ -1463,7 +1463,7 @@
+ "OWNED": "Eigen Projecten",
+ "GRANTED": "Verleende Projecten",
+ "OWNED_SINGULAR": "Eigen Project",
+- "GRANTED_SINGULAR": "Verleend Project"
++ "GRANTED_SINGULAR": "Project toegewezen {{name}}"
+ },
+ "PRIVATELABEL": {
+ "TITLE": "Branding Instelling",
+diff --git a/console/src/assets/i18n/pl.json b/console/src/assets/i18n/pl.json
+index 39068f248..57fbdc714 100644
+--- a/console/src/assets/i18n/pl.json
++++ b/console/src/assets/i18n/pl.json
+@@ -1462,7 +1462,7 @@
+ "OWNED": "Własne Projekty",
+ "GRANTED": "Udzielone Projekty ",
+ "OWNED_SINGULAR": "Własny Projekt",
+- "GRANTED_SINGULAR": "Udzielony Projekt"
++ "GRANTED_SINGULAR": "Projekt przydzielony {{name}}"
+ },
+ "PRIVATELABEL": {
+ "TITLE": "Ustawienia marka",
+diff --git a/console/src/assets/i18n/pt.json b/console/src/assets/i18n/pt.json
+index 21e4c67a3..39324f3f4 100644
+--- a/console/src/assets/i18n/pt.json
++++ b/console/src/assets/i18n/pt.json
+@@ -1462,7 +1462,7 @@
+ "OWNED": "Projetos Próprios",
+ "GRANTED": "Projetos Concedidos",
+ "OWNED_SINGULAR": "Projeto Próprio",
+- "GRANTED_SINGULAR": "Projeto Concedido"
++ "GRANTED_SINGULAR": "Projeto atribuído a {{name}}"
+ },
+ "PRIVATELABEL": {
+ "TITLE": "Configuração de Marca",
+diff --git a/console/src/assets/i18n/ru.json b/console/src/assets/i18n/ru.json
+index e4f826021..0fefe992a 100644
+--- a/console/src/assets/i18n/ru.json
++++ b/console/src/assets/i18n/ru.json
+@@ -1446,9 +1446,8 @@
+ "ZITADELPROJECT": "Этот проект является системным. Будьте осторожны: если вы внесете изменения, ZITADEL может вести себя не так, как задумано.",
+ "TYPE": {
+ "OWNED": "Собственные проекты",
+- "GRANTED": "Предоставленные проекты",
+ "OWNED_SINGULAR": "Собственный проект",
+- "GRANTED_SINGULAR": "Предоставленный проект"
++ "GRANTED_SINGULAR": "Проект, предоставленный {{name}}"
+ },
+ "PRIVATELABEL": {
+ "0": {
+diff --git a/console/src/assets/i18n/zh.json b/console/src/assets/i18n/zh.json
+index 9697037c1..201dc60cb 100644
+--- a/console/src/assets/i18n/zh.json
++++ b/console/src/assets/i18n/zh.json
+@@ -1461,7 +1461,7 @@
+ "OWNED": "拥有的项目",
+ "GRANTED": "被授权的项目",
+ "OWNED_SINGULAR": "拥有项目",
+- "GRANTED_SINGULAR": "被授予的项目"
++ "GRANTED_SINGULAR": "授予{{name}}的项目"
+ },
+ "PRIVATELABEL": {
+ "TITLE": "品牌标识设置",
+diff --git a/internal/notification/templates/templateData.go b/internal/notification/templates/templateData.go
+index f9572a4c5..8ff750da5 100644
+--- a/internal/notification/templates/templateData.go
++++ b/internal/notification/templates/templateData.go
+@@ -2,7 +2,6 @@ package templates
+
+ import (
+ "fmt"
+- "html"
+
+ "github.com/zitadel/zitadel/internal/domain"
+ "github.com/zitadel/zitadel/internal/i18n"
+@@ -40,7 +39,7 @@ func (data *TemplateData) Translate(translator *i18n.Translator, msgType string,
+ data.PreHeader = translator.Localize(fmt.Sprintf("%s.%s", msgType, domain.MessagePreHeader), args, langs...)
+ data.Subject = translator.Localize(fmt.Sprintf("%s.%s", msgType, domain.MessageSubject), args, langs...)
+ data.Greeting = translator.Localize(fmt.Sprintf("%s.%s", msgType, domain.MessageGreeting), args, langs...)
+- data.Text = html.UnescapeString(translator.Localize(fmt.Sprintf("%s.%s", msgType, domain.MessageText), args, langs...))
++ data.Text = translator.Localize(fmt.Sprintf("%s.%s", msgType, domain.MessageText), args, langs...)
+ data.ButtonText = translator.Localize(fmt.Sprintf("%s.%s", msgType, domain.MessageButtonText), args, langs...)
+ // Footer text is neither included in i18n files nor defaults.yaml
+ footerText := fmt.Sprintf("%s.%s", msgType, domain.MessageFooterText)
+diff --git a/internal/notification/types/notification.go b/internal/notification/types/notification.go
+index 1a5ccebb2..9bbfb66c8 100644
+--- a/internal/notification/types/notification.go
++++ b/internal/notification/types/notification.go
+@@ -2,7 +2,9 @@ package types
+
+ import (
+ "context"
++ "html"
+
++ "github.com/zitadel/zitadel/internal/database"
+ "github.com/zitadel/zitadel/internal/eventstore"
+ "github.com/zitadel/zitadel/internal/i18n"
+ "github.com/zitadel/zitadel/internal/notification/channels/smtp"
+@@ -42,6 +44,7 @@ func SendEmail(
+ allowUnverifiedNotificationChannel bool,
+ ) error {
+ args = mapNotifyUserToArgs(user, args)
++ sanitizeArgsForHTML(args)
+ data := GetTemplateData(ctx, translator, args, url, messageType, user.PreferredLanguage.String(), colors)
+ template, err := templates.GetParsedTemplate(mailhtml, data)
+ if err != nil {
+@@ -59,6 +62,23 @@ func SendEmail(
+ }
+ }
+
++func sanitizeArgsForHTML(args map[string]any) {
++ for key, arg := range args {
++ switch a := arg.(type) {
++ case string:
++ args[key] = html.EscapeString(a)
++ case []string:
++ for i, s := range a {
++ a[i] = html.EscapeString(s)
++ }
++ case database.TextArray[string]:
++ for i, s := range a {
++ a[i] = html.EscapeString(s)
++ }
++ }
++ }
++}
++
+ func SendSMSTwilio(
+ ctx context.Context,
+ channels ChannelChains,
diff --git a/pkgs/by-name/zi/zitadel/package.nix b/pkgs/by-name/zi/zitadel/package.nix
index 14c9ff1a3ad81..a706133094155 100644
--- a/pkgs/by-name/zi/zitadel/package.nix
+++ b/pkgs/by-name/zi/zitadel/package.nix
@@ -99,6 +99,10 @@ buildGoModule rec {
name = "zitadel";
inherit version;
+ patches = [
+ ./2.42.x-CVE-2024-41953.patch
+ ];
+
src = zitadelRepo;
nativeBuildInputs = [ sass statik ];
@@ -149,5 +153,8 @@ buildGoModule rec {
license = licenses.asl20;
sourceProvenance = [ sourceTypes.fromSource ];
maintainers = with maintainers; [ Sorixelle ];
+ knownVulnerabilities = [
+ "CVE-2024-41952"
+ ];
};
}