airajena opened a new pull request, #63:
URL: https://github.com/apache/fineract-business-intelligence/pull/63

   ## Audit Fixes
   
   ### 🔴 Critical
   
   | Finding | Status |
   |---|---|
   | RLS fails open to `'admin'` when `current_username()` is empty | ✅ Fixed: 
empty/None now yields zero rows (fail-closed), not admin access |
   | RLS injectable via unescaped username interpolation | ✅ Fixed: quotes are 
escaped (`replace("'", "''")`) before interpolation |
   | Test suite concealed the RLS bug (stripped the vulnerable line before 
testing) | ✅ Fixed: tests now render through real Jinja, exercising the actual 
line |
   | No database-level RLS (`CREATE POLICY`), only app-layer SQL text | ❌ Not 
done: deliberately deferred, see below |
   | Historical portfolio figures wrong (current balance replicated across all 
history) | ✅ Fixed: rebuilt via point-in-time reconstruction from the 
transaction ledger |
   | `loan_status_id = 300` filter made closed loans vanish from history 
retroactively | ✅ Fixed: filter removed, closed loans now stay in historical 
snapshots |
   | PAR bands based on bucket config (`min_age_days`), not real DPD | ✅ Fixed: 
DPD now computed from `m_loan_repayment_schedule`, not bucket config |
   | Per-batch commits break run atomicity (`WatermarkManager.update()` 
committing mid-run) | ✅ Fixed: commit removed, atomicity owned solely by 
`run()` |
   
   ### 🟡 Smaller Items
   
   | Finding | Status |
   |---|---|
   | NULL cursor columns silently skipped, causing hard failures on NOT NULL 
columns | ✅ Fixed: coalesced to epoch sentinel |
   | COB gate too loose (any completed job, not specifically Close-of-Business) 
| ✅ Fixed: scoped to `job_name` |
   | Bind-parameter ceiling risk (~51k params against 65535 limit) | ✅ Fixed: 
chunked inserts |
   | No TLS on database connections | ✅ Fixed: configurable `ssl_mode` per 
connection |
   | Deletes never propagate (upsert-only, orphans persist forever) | ✅ Fixed: 
new reconcile mode, verified live |
   
   ---
   
   ## What's Not Done & Why: Native Postgres Row-Level Security
   
   ### Context
   
   All audit items are resolved **except one**: native database-level RLS via 
Postgres `CREATE POLICY`.
   
   ### Why it wasn't implemented
   
   All Superset users share a **single database login** 
(`WAREHOUSE_READER_USER`) from a shared connection pool. Postgres RLS works by 
checking *"who is the current user?"* but since everyone uses the same login, 
Postgres cannot distinguish between users on its own.
   
   To make this work, you'd need to identify the real human user per-query by 
running:
   ```sql
   SET app.username = 'actual_user'
   ```
   before every query, and the only place in Superset to inject this is the 
`DB_CONNECTION_MUTATOR` hook.
   
   **The risk:** If Superset reuses a pooled connection without re-running that 
hook (which we could not reliably verify), **User A's session variable could 
leak onto User B's connection**, silently bypassing office-level data 
isolation. That is a worse outcome than the current state.
   
   Given this risk and no safe way to verify Superset's exact connection 
checkout/reuse behavior within the project scope, this was deliberately left as 
a documented gap.
   
   ### What was done instead
   
   The existing Jinja-templated application-layer RLS (in each Superset 
dataset's SQL) was hardened:
   
   - **Fail-closed**: empty or missing username yields zero rows returned, not 
full admin access
   - **Injection-safe**: usernames are escaped before interpolation into SQL
   - **Fully tested**: unit + integration tests covering both fail-closed and 
injection cases
   
   ### Current risk posture
   
   | Layer | Status |
   |---|---|
   | Application-layer RLS (Superset dataset SQL) | ✅ Hardened: fail-closed + 
injection-safe |
   | Database-layer RLS (Postgres `CREATE POLICY`) | ❌ Not implemented: known 
gap |
   
   > ⚠️ The application-layer RLS depends on every dataset's SQL being written 
correctly. It is safe and tested, but not database-enforced.
   
   Fixes: 
[62](https://github.com/apache/fineract-business-intelligence/issues/62)


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to