CVE-2022-46166 (Java, published 2022-12-09T21:15Z)
Description: value: Spring boot admins is an open source administrative user interface for management of spring boot applications. All users who run Spring Boot Admin Server, having enabled Notifiers (e.g. Teams-Notifier) and write access to environment variables via UI are affected. Users are advised to upgrade to the most recent releases of Spring Boot Admin 2.6.10 and 2.7.8 to resolve this issue. Users unable to upgrade may disable any notifier or disable write access (POST request) on `/env` actuator endpoint.


Severity: nan (CVSS v3 base score: 9.8)
Weakness: CWE-94 \u2014 Improper Control of Generation of Code ('Code Injection')
The product constructs all or part of a code segment using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the syntax or behavior of the intended code segment.
Repository: https://github.com/codecentric/spring-boot-admin
Files changed:
spring-boot-admin-server/src/main/java/de/codecentric/boot/admin/server/notify/DingTalkNotifier.java
spring-boot-admin-server/src/main/java/de/codecentric/boot/admin/server/notify/DiscordNotifier.java
spring-boot-admin-server/src/main/java/de/codecentric/boot/admin/server/notify/HipchatNotifier.java
spring-boot-admin-server/src/main/java/de/codecentric/boot/admin/server/notify/LetsChatNotifier.java
spring-boot-admin-server/src/main/java/de/codecentric/boot/admin/server/notify/MicrosoftTeamsNotifier.java
spring-boot-admin-server/src/main/java/de/codecentric/boot/admin/server/notify/OpsGenieNotifier.java
spring-boot-admin-server/src/main/java/de/codecentric/boot/admin/server/notify/PagerdutyNotifier.java
spring-boot-admin-server/src/main/java/de/codecentric/boot/admin/server/notify/SlackNotifier.java
spring-boot-admin-server/src/main/java/de/codecentric/boot/admin/server/notify/TelegramNotifier.java
Commit message: feat: improve notifiers


Vulnerable code:
import org.springframework.expression.spel.support.StandardEvaluationContext;
		StandardEvaluationContext context = new StandardEvaluationContext(root);
		context.addPropertyAccessor(new MapAccessor());
			mac.init(new SecretKeySpec(secret.getBytes("UTF-8"), "HmacSHA256"));
			byte[] signData = mac.doFinal(stringToSign.getBytes("UTF-8"));
import org.springframework.expression.spel.support.StandardEvaluationContext;
		StandardEvaluationContext context = new StandardEvaluationContext(root);
		context.addPropertyAccessor(new MapAccessor());
import org.springframework.expression.spel.support.StandardEvaluationContext;
		return String.format("%s/room/%s/notification?auth_token=%s", url.toString(), roomId, authToken);
		StandardEvaluationContext context = new StandardEvaluationContext(root);
		context.addPropertyAccessor(new MapAccessor());
	public void setUrl(@Nullable URI url) {
		this.url = url;
	}

	public void setAuthToken(@Nullable String authToken) {
		this.authToken = authToken;
	public void setRoomId(@Nullable String roomId) {
		this.roomId = roomId;
	public void setNotify(boolean notify) {
		this.notify = notify;
	public void setDescription(String description) {
		this.description = parser.parseExpression(description, ParserContext.TEMPLATE_EXPRESSION);
import org.springframework.expression.spel.support.StandardEvaluationContext;
		StandardEvaluationContext context = new StandardEvaluationContext(root);
		context.addPropertyAccessor(new MapAccessor());
	public void setUrl(@Nullable URI url) {
		this.url = url;
	}

	public void setUsername(String username) {
		this.username = username;
	public void setRoom(@Nullable String room) {
		this.room = room;
	public void setToken(@Nullable String token) {
		this.token = token;
	public void setMessage(String message) {
		this.message = parser.parseExpression(message, ParserContext.TEMPLATE_EXPRESSION);
import org.springframework.expression.spel.support.StandardEvaluationContext;
		StandardEvaluationContext context = createEvaluationContext(event, instance);
	protected Message getDeregisteredMessage(Instance instance, StandardEvaluationContext context) {
	protected Message getRegisteredMessage(Instance instance, StandardEvaluationContext context) {
	protected Message getStatusChangedMessage(Instance instance, StandardEvaluationContext context) {
			StandardEvaluationContext context) {
	protected String evaluateExpression(StandardEvaluationContext context, Expression expression) {
	protected StandardEvaluationContext createEvaluationContext(InstanceEvent event, Instance instance) {
		StandardEvaluationContext context = new StandardEvaluationContext(root);
		context.addPropertyAccessor(new MapAccessor());
		return context;
import org.springframework.expression.spel.support.StandardEvaluationContext;
			return String.format("%s/%s/close", url.toString(), generateAlias(instance));
		StandardEvaluationContext context = new StandardEvaluationContext(root);
		context.addPropertyAccessor(new MapAccessor());
	public void setApiKey(@Nullable String apiKey) {
		this.apiKey = apiKey;
	}

import org.springframework.expression.spel.support.StandardEvaluationContext;
		StandardEvaluationContext context = new StandardEvaluationContext(root);
		context.addPropertyAccessor(new MapAccessor());

	public void setUrl(URI url) {
		this.url = url;
	}

	public void setClient(@Nullable String client) {
		this.client = client;
	public void setClientUrl(@Nullable URI clientUrl) {
		this.clientUrl = clientUrl;
	public void setServiceKey(@Nullable String serviceKey) {
		this.serviceKey = serviceKey;
	public void setDescription(String description) {
		this.description = parser.parseExpression(description, ParserContext.TEMPLATE_EXPRESSION);
import org.springframework.expression.spel.support.StandardEvaluationContext;
		StandardEvaluationContext context = new StandardEvaluationContext(root);
		context.addPropertyAccessor(new MapAccessor());
import org.springframework.expression.spel.support.StandardEvaluationContext;
		StandardEvaluationContext context = new StandardEvaluationContext(root);
		context.addPropertyAccessor(new MapAccessor());

Fixed code:
import java.nio.charset.StandardCharsets;
import org.springframework.expression.spel.support.DataBindingPropertyAccessor;
import org.springframework.expression.spel.support.SimpleEvaluationContext;
		SimpleEvaluationContext context = SimpleEvaluationContext
				.forPropertyAccessors(DataBindingPropertyAccessor.forReadOnlyAccess(), new MapAccessor())
				.withRootObject(root).build();
			mac.init(new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
			byte[] signData = mac.doFinal(stringToSign.getBytes(StandardCharsets.UTF_8));
import org.springframework.expression.spel.support.DataBindingPropertyAccessor;
import org.springframework.expression.spel.support.SimpleEvaluationContext;
		SimpleEvaluationContext context = SimpleEvaluationContext
				.forPropertyAccessors(DataBindingPropertyAccessor.forReadOnlyAccess(), new MapAccessor())
				.withRootObject(root).build();
import org.springframework.expression.spel.support.DataBindingPropertyAccessor;
import org.springframework.expression.spel.support.SimpleEvaluationContext;
		return String.format("%s/room/%s/notification?auth_token=%s", url, roomId, authToken);
		SimpleEvaluationContext context = SimpleEvaluationContext
				.forPropertyAccessors(DataBindingPropertyAccessor.forReadOnlyAccess(), new MapAccessor())
				.withRootObject(root).build();
	public void setUrl(@Nullable URI url) {
		this.url = url;
	public void setAuthToken(@Nullable String authToken) {
		this.authToken = authToken;
	public void setRoomId(@Nullable String roomId) {
		this.roomId = roomId;
	public void setNotify(boolean notify) {
		this.notify = notify;
	public void setDescription(String description) {
		this.description = parser.parseExpression(description, ParserContext.TEMPLATE_EXPRESSION);
	}

import org.springframework.expression.spel.support.DataBindingPropertyAccessor;
import org.springframework.expression.spel.support.SimpleEvaluationContext;
		SimpleEvaluationContext context = SimpleEvaluationContext
				.forPropertyAccessors(DataBindingPropertyAccessor.forReadOnlyAccess(), new MapAccessor())
				.withRootObject(root).build();
	public void setUrl(@Nullable URI url) {
		this.url = url;
	public void setUsername(String username) {
		this.username = username;
	public void setRoom(@Nullable String room) {
		this.room = room;
	public void setToken(@Nullable String token) {
		this.token = token;
	public void setMessage(String message) {
		this.message = parser.parseExpression(message, ParserContext.TEMPLATE_EXPRESSION);
	}

import org.springframework.expression.EvaluationContext;
import org.springframework.expression.spel.support.DataBindingPropertyAccessor;
import org.springframework.expression.spel.support.SimpleEvaluationContext;
		EvaluationContext context = createEvaluationContext(event, instance);
	protected Message getDeregisteredMessage(Instance instance, EvaluationContext context) {
	protected Message getRegisteredMessage(Instance instance, EvaluationContext context) {
	protected Message getStatusChangedMessage(Instance instance, EvaluationContext context) {
			EvaluationContext context) {
	protected String evaluateExpression(EvaluationContext context, Expression expression) {
	protected EvaluationContext createEvaluationContext(InstanceEvent event, Instance instance) {
		return SimpleEvaluationContext
				.forPropertyAccessors(DataBindingPropertyAccessor.forReadOnlyAccess(), new MapAccessor())
				.withRootObject(root).build();
import org.springframework.expression.spel.support.DataBindingPropertyAccessor;
import org.springframework.expression.spel.support.SimpleEvaluationContext;
			return String.format("%s/%s/close", url, generateAlias(instance));
		SimpleEvaluationContext context = SimpleEvaluationContext
				.forPropertyAccessors(DataBindingPropertyAccessor.forReadOnlyAccess(), new MapAccessor())
				.withRootObject(root).build();
	public void setApiKey(@Nullable String apiKey) {
		this.apiKey = apiKey;
	}

import org.springframework.expression.spel.support.DataBindingPropertyAccessor;
import org.springframework.expression.spel.support.SimpleEvaluationContext;
		SimpleEvaluationContext context = SimpleEvaluationContext
				.forPropertyAccessors(DataBindingPropertyAccessor.forReadOnlyAccess(), new MapAccessor())
				.withRootObject(root).build();
	public void setUrl(URI url) {
		this.url = url;
	public void setClient(@Nullable String client) {
		this.client = client;
	public void setClientUrl(@Nullable URI clientUrl) {
		this.clientUrl = clientUrl;
	public void setServiceKey(@Nullable String serviceKey) {
		this.serviceKey = serviceKey;
	public void setDescription(String description) {
		this.description = parser.parseExpression(description, ParserContext.TEMPLATE_EXPRESSION);
	}

import org.springframework.expression.spel.support.DataBindingPropertyAccessor;
import org.springframework.expression.spel.support.SimpleEvaluationContext;
		SimpleEvaluationContext context = SimpleEvaluationContext
				.forPropertyAccessors(DataBindingPropertyAccessor.forReadOnlyAccess(), new MapAccessor())
				.withRootObject(root).build();

import org.springframework.expression.spel.support.DataBindingPropertyAccessor;
import org.springframework.expression.spel.support.SimpleEvaluationContext;
		SimpleEvaluationContext context = SimpleEvaluationContext
				.forPropertyAccessors(DataBindingPropertyAccessor.forReadOnlyAccess(), new MapAccessor())
				.withRootObject(root).build();