One scan, shown whole.

5,288 files of Apache Fineract, read in one pass on 2026-08-20. Every figure below is that scan’s own output, including what it could not resolve.

github.com/Nirvahana/fineract · scan 3f8508a6
5,288files read
545,138lines
1,559,015entities checked
70findings
23personal-data elements
18unencrypted sinks

Java 5,270 files · SQL 14 · Kubernetes manifests 4. Run 2026-08-20, one pass, no configuration beyond the repository URL.

01 · Findings12 TRACED · DPDPA

Seventy findings, and which twelve are proven.

A rule matching a line is a candidate. A value the engine followed from the place it entered to the place it landed is a finding you can act on today. Both are shown, and they are never presented as the same thing.

8critical
21high
37medium
4low
proof · what the engine actually followed

A rule matching a line is a candidate. A value the engine followed from where it entered to where it landed is something you can act on today. The page never presents the two as the same thing.

by rule · top 6
LOG-00113
STORE-0019
RETENTION-0018
INPUT-0015
IAC-K8S-RO-FS-0013
CONSENT-0013

22 unique findings across 70 occurrences.

findings · sorted by severity
RuleSeverityFileLineEvidence
INPUT-001CRITICAL…ueries/service/GenericDataServiceImpl.java228pattern
INPUT-001CRITICAL…sAccountTransactionsSearchServiceImpl.java269pattern
INPUT-001CRITICAL…sAccountTransactionsSearchServiceImpl.java117pattern
INPUT-001CRITICAL…ies/service/DatatableWriteServiceImpl.java536pattern
INPUT-001CRITICAL…ries/service/DatatableReadServiceImpl.java202pattern
PCI-4.1.1CRITICAL…lient/feign/FineractFeignClientConfig.java177pattern
PCI-4.1.1CRITICAL…lient/feign/FineractFeignClientConfig.java193pattern
PCI-4.1.1CRITICAL…e/fineract/client/util/FineractClient.java514pattern
AUTH-001HIGH…ganisation/staff/api/StaffApiResource.java102pattern
DPDPA-SVC-001HIGH…AcmeExternalEventSourceProviderConfig.java29pattern
IAC-K8S-NETPOL-001HIGH…tes/fineract-mifoscommunity-deployment.yml1pattern
IAC-K8S-RUN-ROOT-001HIGHkubernetes/fineractmysql-deployment.yml68pattern
IAC-K8S-RUN-ROOT-001HIGHkubernetes/fineract-server-deployment.yml37pattern
IAC-K8S-RUN-ROOT-001HIGH…tes/fineract-mifoscommunity-deployment.yml76pattern
NOTICE-001HIGH…s/0002-mifosx-base-reference-data-utf8.sql291pattern
PII-001HIGH…vice/OidcAppUserResolutionServiceImpl.java71traced
02 · The data flow

Where the personal data in this repository ends up.

One graph over the whole codebase: 119 nodes, 39 edges, and 12 complete source-to-sink traces. 18 of the sinks carry no evidence of encryption.

119nodes
39edges
12complete traces
18unencrypted sinks
data flow · 119 nodes over one graph
47Entry points33Processing19Storage20Logging

18 of the 39 sinks carry no evidence of encryption. Every ribbon above is drawn in proportion to the node counts beside it.

traces · 12 followed end to end
accountNumberUnencrypted storageunencrypted
accountNumberData sinkunknown
accountNumberFormatUnencrypted storageunencrypted
emailApplication logunknown
cannot_change_password, email, firstname…Unencrypted storageunencrypted
cannot_change_password, email, firstname…Unencrypted storageunencrypted
cannot_change_password, email, firstname…Unencrypted storageunencrypted
account_no, date_of_birth, display_name…Unencrypted storageunencrypted
account_no, date_of_birth, display_name…Unencrypted storageunencrypted
accountNumberUnencrypted storageunencrypted
cannot_change_password, email, firstname…Unencrypted storageunencrypted
emailApplication logunknown
03 · Every element23 ELEMENTS

What counts as personal data here, and under which law.

Discovered from the schema and the code, not from a questionnaire. Each carries its category, its sensitivity, and the regimes that reach it, which is what turns a field name into an obligation.

contact6
cityLow
emailMedium
phoneMedium
postal_addressMedium
postal_codeLow
state_provinceLow
name4
first_nameLow
full_nameMedium
last_nameLow
middle_nameLow
demographic3
ageMedium
date_of_birthHigh
genderMedium
government id3
aadhaarCritical
identity_documentHigh
national_idHigh
credential2
api_keyCritical
passwordCritical
online identifier2
account_identifierMedium
ip_addressMedium
employment1
employee_idLow
financial1
salaryHigh
location1
geolocationHigh
04 · Blast radiusREACHABILITY, NOT SCORE

Four of ten advisories can touch regulated data.

Dependency advisories re-ranked by whether the vulnerable package is imported by a file that handles personal data. This is an import-level reachability proxy, not proof of exploitability, and it is labelled that way in the product too.

79components
7advisories
4can reach personal data
0critical and reachable
reachability · 4 vulnerable packages
Regulated data31 files · 22 categoriescommons-lang3jackson-databindactivemq-clientpostgresql

imported by a file that handles personal data no path to personal data

the upgrade that clears each package
PackageCVEsSeverityUpgrade to
commons-lang3
3.17.0
1MEDIUM3.18.0
jackson-databind
2.21.4
3MEDIUM2.21.5
activemq-client
6.1.8
2HIGHno single version
postgresql
42.7.11
1HIGH42.7.12

One row per package, not per CVE. jackson-databind carries three separate advisories against 2.21.4 and each publishes its own fix list; 2.21.5 is the lowest version that appears in all three. activemq-client has no version that clears both of its advisories, which is why it says so.

05 · The evidence

What you hand to whoever asked.

An SBOM, the egress inventory, and the erasure surfaces, each with its own gaps stated. A report that claims complete coverage of a codebase this size would be the least credible thing in the bundle.

SBOM · CycloneDX
52of 79 components checked

27 could not be resolved against an advisory database. They are reported as not analysed, never as clean. Of the 7 findings, 7 have a published fix and 0 are known to be exploited.

egress · who receives it
41of 313 calls carry personal data

Named recipients: Pinecone, Segment, Sentry, Weaviate. 13 destinations could not be named and are listed as unresolved rather than dropped.

erasure and access
21of 23 elements have a path

24 surfaces in code, covering access and erasure. 2 elements have no erasure or access path at all, so the answer to “can you delete me” for those is no.

06 · In the product

The same scan, on screen.

Findings group by the obligation they touch rather than by file, so the queue reads as a plan instead of a backlog. Every row opens into why it matters, the path the data took, and the line to change.

scrutora · findings
Findings grouped by framework, with severity and status filters.

And the data dictionary, where a decision about what counts as personal data is made once and flows into the map, the RoPA, the blast radius and the findings together.

scrutora · data dictionary
The data dictionary: confirmed, rejected and undecided fields, with erasure coverage.