This document is for human security researchers finding and submitting security reports, AI-assisted human security researchers doing same, and Fineract PMC members handling these reports.
This is not a standalone document; it lives alongside the code it supports.
See our top-level readme for an introduction to Fineract.
Source code repository: https://github.com/apache/fineract.
Signed releases: https://fineract.apache.org/#downloads.
- Back-office core banking: Loan officers, tellers, and administrators manage clients, loans, savings, deposits, and accounting via REST APIs.
- Batch end-of-day processing: Close-of-Business (COB) jobs run via Spring Batch, optionally partitioned across worker nodes.
- External business events: Publishing events (e.g., ClientCreated) to downstream systems via Kafka or ActiveMQ.
- Server / daemon: Executable JAR (recommended), or WAR deployed to external Tomcat (not recommended).
- Containerized: Docker image run as a container with an OCI-compliant engine.
- Multi-instance topology: Read-only instances, write-enabled instances, batch-manager instances, and batch-worker instances can be segregated.
Fineract is is not designed to be embedded as a library inside another JVM application.
| Role | Trust level | Description |
|---|---|---|
| Operator / deployer | root access | Sysadmin who configures and deploys the application. |
| Back-office user | Authenticated, authorized | Loan officers, branch managers, system admins. Hold tenant-scoped credentials. |
| Self-service | N/A | Direct access from bank customers to Fineract is out of model per §3. |
All scripts/configs used in build/dev/test, GitHub actions, and the project website.
- Direct internet-facing deployment without a reverse proxy / WAF: The project documentation explicitly recommends running behind NGINX or a cloud-native load balancer with SSL termination.
- Cryptocurrency or blockchain ledger integration: Fineract is a traditional double-entry accounting system; it does not provide blockchain primitives.
- Real-time payment rails (RTGS, SWIFT): Fineract manages internal accounts; integration with external payment networks is a downstream responsibility.
- Web UI: Fineract only provides an API. The "Community App" is a separate repository (https://github.com/openMF/web-app) and is not part of this model.
- Self-service: Fineract is used by back-office users, not bank customers. The "Self-service Plugin" is a separate repository (https://github.com/openMF/selfservice-plugin) and is not part of this model.
- Physical access to the database server: If an attacker has OS-level access to the PostgreSQL/MariaDB host, the project assumes the game is already lost.
- Network-level DDoS: The embedded Tomcat has configurable connection limits, but volumetric DDoS mitigation is explicitly left to the reverse proxy / cloud provider.
The API surface (HTTP/S) is the primary trust boundary. Once a request has passed authentication and tenant resolution, data inside the application is treated as trusted.
The filesystem is a secondary trust boundary: The application assumes all disk read and write operations are safe.
The database connection pool is a secondary trust boundary: SQL queries generated by the application are trusted by the database.
[Untrusted Internet] --(TLS)--> [Reverse Proxy/WAF] ----> [Fineract API (Tomcat)]
|
| (JDBC, authenticated pool)
v
[Database (PostgreSQL)]
|
| (tenant-scoped schema)
v
[Tenant Data Schema]
Trust transitions:
- Internet → Reverse Proxy: TLS-encrypted; certificate validation required. The project ships a self-signed cert for localhost only; production requires a CA-trusted cert or managed proxy.
- Reverse Proxy → Fineract API: TLS-encrypted; X-Forwarded-For and X-Forwarded-Proto respected if proxy is present.
- Fineract API → Database: JDBC over TCP; credentials from application.properties / env vars; connection pool authenticated per-tenant.
- Java VM: Azul Zulu recommended.
- Database: PostgreSQL recommended.
Should run on any OS with a compatible JVM. See top-level readme for appropriate version(s).
Multi-tenancy is implemented via schema-per-tenant or database-per-tenant; tenant resolution happens at request entry via Fineract-Platform-TenantId header.
- The JVM provides standard memory safety and garbage collection.
- Fineract relies on the JVM system clock for business-date logic, COB scheduling, and audit timestamps.
- If the system clock is manipulated, loan interest accrual and COB batch behavior may be incorrect. This is treated as an environmental issue, not a Fineract bug.
Fineract can be deployed in many ways. It configured at runtime via environment variables and Java properties.
See Deployment and Security sections in the official documentation for steps operators must follow as they work towards deploying to production.
- HTTP API requests (headers, request body, path, query string)
- database
- filesystem
- HTTP request size: May be enforced by Fineract. Should also be enforced by reverse proxy / WAF.
- Rate limiting: Not enforced by Fineract itself. Left to reverse proxy / WAF.
| Adversary | Capability | What they are trying to do |
|---|---|---|
| Network-based attacker (unauthenticated) | Can send HTTP requests to the API; can observe TLS-encrypted traffic but not decrypt it without cert compromise. | Gain authentication, extract data via injection, cause DoS via resource exhaustion. |
| Authenticated back-office user (low-privilege) | Has valid tenant credentials with limited permissions (e.g., loan officer). | Escalate privileges, access other tenants' data, modify loans/disbursements they do not own. |
| Authenticated back-office user (high-privilege) | Has admin / super-user role. | Arbitrary data modification, user management, configuration changes. |
- Physical attacker with datacenter access: If the attacker has root on the DB server or the Fineract host, the model assumes they have already won.
- JVM / OS / database / dependency supply-chain attacker: The model assumes all infrastructure and dependencies are not compromised.
- Side-channel observer: Timing attacks and cache attacks are not modeled.
- Reverse proxy / WAF bypass attacker: If the reverse proxy is compromised, the attacker is out of scope for Fineract's model; that is infrastructure-layer.
- Tenant isolation — users and data of tenant A are inaccessible from tenant B
- Role-based access control (RBAC) enforcement — low-privilege users cannot perform admin actions
- Password strength enforcement
- Support for external identity provider (e.g. Keycloak)
- HTTPS encryption (with operator-provided valid certificate)
- Rate limiting / brute-force protection
- Audit log tamper-resistance - Audit logs are written to the database and filesystem; no append-only or cryptographic integrity guarantee
- Encryption at rest
- SQL injection in custom reports / ad-hoc queries: Fineract allows administrators to define custom reports with SQL. If an attacker gains admin access, they can execute arbitrary SQL through the reporting module. This is by design (admin capability) and not a vulnerability.
What the operator / deployer must do for the assumptions in §5–§7 to hold:
- Replace the embedded SSL keystore with a CA-trusted certificate or terminate TLS at a reverse proxy before exposing the service to any network.
- Deploy a reverse proxy / WAF / API gateway in front of Fineract to enforce rate limiting, IP filtering, and DDoS mitigation. The project explicitly recommends not running directly on the internet.
- Run database migrations (Liquibase) separately from the application server in production, or ensure the app server has migration-only privileges that are dropped after startup.
- Enable and configure OAuth2 (instead of Basic Auth) - use a separate trusted identity provider such as Keycloak.
- Enable 2FA (
FINERACT_SECURITY_2FA_ENABLED=true) and configure a secure SMS/email gateway for production admin accounts. - Segregate instance types in large deployments: run batch managers and workers on separate nodes from API-serving nodes; use read-only instances for reporting.
- Encrypt data at rest at the storage layer.
- Exposing the API directly to the internet without a reverse proxy. The embedded Tomcat is not hardened for direct internet exposure; the self-signed cert is not trusted; and there is no built-in rate limiting.
- Using the embedded SSL keystore in production. The
keystore.jksis self-signed and the private key is public (shipped in the JAR). This leaves users vulnerable to MITM attacks.
The following changes should trigger a revision of this threat model:
- New public API surface (e.g., a new
/api/v2/...major version, GraphQL endpoint, or gRPC service). - New input format accepted (e.g., XML batch imports, protobuf, Avro).
- New network surface (e.g., native Kafka consumer instead of just producer, WebSocket support, gRPC).
- New deployment context (e.g., serverless/FaaS, edge computing, mobile SDK embedding).
- New authentication scheme (e.g., mTLS for clients, SAML, LDAP integration).
- Promotion of a 3rd party component into core (e.g., if the self-service plugin moves from openMF/ into apache/fineract proper).
- Change in default for a §5a build knob that changes the security envelope (e.g., OAuth2 becoming the default instead of Basic Auth).
- New CVE that cannot be cleanly routed to one of the §13 dispositions — this indicates a
MODEL-GAPand requires model revision, not an ad-hoc call.
| Disposition | Meaning | Licensed by |
|---|---|---|
VALID |
Violates a property the project claims, via an in-scope adversary and input. | §8, §6, §7 |
VALID-HARDENING |
No §8 property is violated, but the API makes a §11 misuse easy enough that the project elects to harden it. Reported privately; fixed at maintainer discretion; typically no CVE. | §11 |
OUT-OF-MODEL: trusted-input |
Requires attacker control of a parameter the model marks trusted (operator-entered value). | §6 |
OUT-OF-MODEL: adversary-not-in-scope |
Requires an attacker capability the model excludes (e.g., physical datacenter access, JVM compromise). | §7 |
OUT-OF-MODEL: unsupported-component |
Unrelated code/logic path or non-shipped component. | §3 |
OUT-OF-MODEL: non-default-build |
Only manifests under a discouraged or non-default §5a flag (e.g., disabled HTTPS or test profile used in production). | §5a |
BY-DESIGN: property-disclaimed |
Concerns a property the project explicitly does not provide (e.g., rate limiting, encryption at rest). | §9 |
KNOWN-NON-FINDING |
Matches a known misuse pattern or non-finding documented under §11. | §11 |
MODEL-GAP |
Cannot be cleanly routed to any of the above. Triggers §12 revision. | §12 |
Don't add any here. Bring them up in private if they are sensitive, otherwise in chat, on the mailing list, or in the issue tracker.
A sidecar threat-model.yaml is recommended for automated triage pipelines. The prose document remains canonical; the sidecar is a derived index.