Automated Threat Modeling

Technical Overview: Apache Fineract CVE-2026-64618 SQL Injection in the Advanced Search API

A brief summary of CVE-2026-64618, a CVSS 9.8 SQL injection in the Apache Fineract advanced search API. It covers the root cause in operator concatenation, the allowlist fix in PR 6153, and the affected versions.

CVE Analysis

9 min read

Gaurav Sarraf
Gaurav Sarraf

2026-11-03

Technical Overview: Apache Fineract CVE-2026-64618 SQL Injection in the Advanced Search API
Experimental AI-Generated Content

This CVE analysis is an experimental publication that is completely AI-generated. The content may contain errors or inaccuracies and is subject to change as more information becomes available. We are continuously refining our process.

If you have feedback, questions, or notice any errors, please reach out to us.

[email protected]

Introduction

Apache Fineract sits underneath loan books, savings accounts, and general ledgers for microfinance and core banking deployments. That means an SQL injection in its search layer reaches directly into the data store behind financial records. In CVE-2026-64618, which NVD scores 9.8 Critical, the comparison operator in an advanced search request flows straight into the SQL text that Fineract builds for loan outstanding amount filters.

Apache Fineract is an open-source core banking platform governed by the Apache Software Foundation. It provides client data management, loan and savings portfolio management, accounting, and reporting, with cloud and on-premises deployment options. It graduated to an ASF Top-Level Project on April 24, 2017.

The ASF announcement cited Musoni using Fineract as a core component of a cloud banking platform serving more than 90 microfinance institutions across Africa. Fineract is also the backend of the Mifos X distribution, which places it at the center of a wider financial inclusion ecosystem.

Technical information

Summary

AttributeValue
ProductApache Fineract
WeaknessCWE-89, SQL injection
Vulnerable inputoutStandingAmountPercentageCondition
Endpoint/fineract-provider/api/v1/search/advance
NVD scoreCVSS 3.1 9.8 Critical
VectorCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
Apache severity labelimportant
Affected1.15.0 and earlier
Fixed1.16.1

Root cause: an operator cannot be a bind parameter

The advanced search endpoint lets a caller filter loans by outstanding percentage or outstanding amount. To do that, it combines a comparison operator such as <= with a numeric value.

The value is handled safely as a named bind parameter, :outStandingAmountPercentage. The operator cannot be bound, because SQL bind parameters only carry values, not syntax. Fineract therefore concatenates the operator string into the query text, producing fragments like this:

a.percentOut <= :outStandingAmountPercentage

Before the patch, convertToSearchConditions() in SearchReadServiceImpl.java only screened these operator strings through the general-purpose SqlValidator:

if (request.getOutStandingAmountPercentageCondition() != null) { sqlValidator.validate(request.getOutStandingAmountPercentageCondition()); } if (request.getOutstandingAmountCondition() != null) { sqlValidator.validate(request.getOutstandingAmountCondition()); }

After that check, the code passed the raw request value to the query builder. A pattern-based validator tries to spot bad input. When the input is concatenated directly into SQL, any gap in that detection becomes injection. The validator was the only barrier between attacker-controlled text and the SQL statement.

Two neighboring inputs reached the same query through the same weak path:

  • outstandingAmountCondition, the sibling of the named parameter, used the same pattern.
  • loanDateOption was also only run through SqlValidator.

Attack flow

Based on the advisory and the published fix, exploitation follows this shape:

  1. The attacker locates a Fineract instance at 1.15.0 or earlier that exposes the advanced search API at /api/v1/search/advance.
  2. The attacker submits a search request that enables outstanding amount percentage filtering. The outStandingAmountPercentageCondition value starts with a valid operator and continues with additional SQL syntax. Fineract's own regression test uses the shape <= 0 union select as a rejected example.
  3. If SqlValidator does not flag the string, the raw value is placed into AdHocQuerySearchConditions. It is then concatenated next to a.percentOut in the query text.
  4. The database executes a statement whose structure is now partly defined by the attacker. The same approach applies to outstandingAmountCondition, which the tests probe with >= 0 or 1 = 1.

The CVSS vector models high confidentiality, integrity, and availability impact. That is a scoring model. It does not demonstrate data extraction or transaction manipulation in a specific deployment.

The advisory does not publish a complete malicious HTTP request. The reviewed patch material also does not establish the HTTP verb or the concrete authorization checks in front of the endpoint. Treat NVD's PR:N rating as NVD's assessment rather than as source-level proof that every deployment allows unauthenticated access to this path.

Threat context

Public reporting describes a serious weakness with no observed campaign:

  • SecurityOnline reports that maintainers have not seen active exploitation and that no public proof of concept has been released.
  • TheHackerWire reports no confirmed public exploit code and no known ransomware linkage.
  • NotCVE and TheHackerWire report that the CVE is not listed in CISA KEV.
  • NotCVE puts EPSS below 1%, while TheHackerWire lists scoring as in progress.

Apache credits thiscodecc of MoyunSec Vlab and Bing as the finders, and Adam Saghy as the remediation developer.

Disclosure timeline

EventDate
Report received by ApacheApril 10, 2026
Fix merged (PR 6153)July 23, 2026
Fineract 1.16.1 release announcementOctober 29, 2026
NVD publicationOctober 30, 2026
NVD last modificationNovember 2, 2026

Patch information

Apache fixed CVE-2026-64618 in Apache Fineract 1.16.1.

  • Change: PR 6153, titled FINERACT-2684: Enhance Search API, written by Ádám Sághy.
  • Merge: Merged into develop on July 23, 2026, as merge commit 355fd6fcb67f7255726ddbd94f10c66ed190b7db.
  • Advisory: The Apache advisory on oss security lists this PR as the reference fix.

The PR is small. It has one commit, with 149 additions and 19 deletions across three files:

  • SearchReadServiceImpl.java (search service): the actual fix.
  • SearchConfiguration.java (search starter): wiring cleanup.
  • SearchReadServiceImplTest.java: new regression tests.

From detection to an allowlist

The patch removes SqlValidator from the search service entirely and adds a strict allowlist for the operator:

private static final String VALID_SEARCH_CONDITIONS = "=, >, >=, <, <=, between"; ... private static String validateSearchCondition(final String condition, final String parameterName, final boolean required) { if (StringUtils.isBlank(condition)) { if (required) { throw invalidSearchParameter(parameterName, condition, VALID_SEARCH_CONDITIONS); } return condition; } final String trimmedCondition = condition.trim(); if (CONDITION_BETWEEN.equalsIgnoreCase(trimmedCondition)) { return CONDITION_BETWEEN; } ...

The method finishes with a switch expression. It returns trimmedCondition only when the value is exactly =, >, >=, <, or <=, and it throws invalidSearchParameter for anything else.

The method has three properties:

  1. After trimming, the input must equal one of six tokens. Any extra character fails the switch, including a trailing 0 union select. Before the patch, the only question was whether the validator noticed something bad.
  2. The method returns either a trimmed exact match or the constant between, never the original string. convertToSearchConditions() now builds AdHocQuerySearchConditions from these validated values instead of from request.get...(). The SQL builder therefore only ever sees an allowed operator.
  3. The check fails closed. If includeOutStandingAmountPercentage or includeOutstandingAmount is true but the matching condition is blank, the request is rejected. Rejected input raises PlatformApiDataValidationException with the error key validation.msg.search.parameter.is.not.one.of.expected.enumerations. The API returns a validation error and no query runs.

Neighboring inputs

The same PR hardens the two related inputs:

  • outstandingAmountCondition goes through the same allowlist.
  • loanDateOption must now be blank or one of the values from SearchConstants.SearchLoanDate.getAllValues():
private static void validateLoanDateOption(final String loanDateOption) { if (StringUtils.isBlank(loanDateOption) || SearchConstants.SearchLoanDate.getAllValues().contains(loanDateOption)) { return; }

Because the service no longer needs SqlValidator, the SearchConfiguration bean factory drops it from the SearchReadServiceImpl constructor. This is cleanup only, with no behavior change.

Regression tests

The new SearchReadServiceImplTest covers both sides of the fix:

  • A valid <= condition produces SQL containing a.percentOut <= :outStandingAmountPercentage.
  • An injected outStandingAmountPercentageCondition of <= 0 union select throws PlatformApiDataValidationException.
  • An injected outstandingAmountCondition of >= 0 or 1 = 1 is rejected the same way.

In both rejection tests, Mockito verifies that NamedParameterJdbcTemplate.query(...) is never() called. Validation stops bad input before any SQL is built or run.

Backports and hardening

The fix ships in the 1.16.1 release line. Since January 2025, Fineract's stated policy has been to decide backports case by case, and older releases become end of life by default when a new one ships. The advisories name no backported patch for 1.15.x or earlier.

The advisory provides no CVE-specific workaround. Fineract's SECURITY.md lists general production controls that complement the upgrade but do not fix the input handling:

  • Keep Fineract behind a reverse proxy, WAF, or API gateway rather than exposing it directly to the internet.
  • Drop migration-only database privileges after startup.
  • Use OAuth2 through a trusted identity provider instead of Basic Auth.
  • Enable two-factor authentication for administrators.

Affected systems and versions

  • Affected: Apache Fineract 1.15.0 and earlier, per the Apache advisory and the Fineract security page.
  • Fixed: Apache Fineract 1.16.1. The Fineract security page lists CVE-2026-64618 under "Fixed in 1.16.1".
  • Vulnerable component: The outStandingAmountPercentageCondition parameter of /api/v1/search/advance. The sibling outstandingAmountCondition and loanDateOption inputs were hardened in the same change.
  • Version nuance: The NVD machine-readable configuration marks versions before 1.16.0 as vulnerable, while Apache's prose names 1.15.0 and earlier. Neither source confirms 1.16.0 as vulnerable, but Apache's explicit upgrade target is 1.16.1.
  • Backports: None named for 1.15.x or earlier.

Vendor security history

Fineract has published several SQL injection advisories affecting different API paths:

CVEMechanismAffected releases and fix
CVE-2024-23538Blind SQL injection through sqlSearch under certain configurations1.8.4 and earlier. Fix recorded December 6, 2023.
CVE-2024-23539SQL injection through sqlSearch on specific endpoints under certain configurations1.8.4 and earlier. Fix recorded December 6, 2023.
CVE-2026-64618Advanced Search API injection through outStandingAmountPercentageCondition1.15.0 and earlier. Fix recorded July 23, 2026, listed under 1.16.1.
CVE-2026-65874Time-based blind injection through ORDER BY inputs in Center and datatable endpoints. Regex validation can be bypassed.1.15.0 and earlier. Fix recorded August 18, 2026.

CVE-2026-65874 involved regex validation that could be bypassed. The CVE-2026-64618 fix abandons detection in favor of an exact-match allowlist. These are separate defects in separate inputs, so do not assume a fix for one covers the other.

Apache publishes resolved issues on its security page and accepts reports at [email protected].

References

Detect & fix
what others miss

Works with
  • GitHub
  • GitLab
  • Bitbucket
  • Azure DevOps Services
  • Gerrit
  • CVS
  • Jira
  • Linear
  • Slack
  • Security Compass
Explore integrations
Security magnifying glass visualization