@@ -23,7 +23,7 @@ If you discover a security vulnerability in MyFans, please report it responsibly
2323| Component | Last Tested | Status | Critical Issues | High Issues | Medium Issues |
2424| -----------| -------------| --------| -----------------| -------------| ---------------|
2525| Frontend | - | Pending | 0 | 0 | 0 |
26- | Backend | - | Pending | 0 | 0 | 0 |
26+ | Backend | 2026-07-25 | Reviewed | 0 | 0 | 3 |
2727| Contracts | - | Pending | 0 | 0 | 0 |
2828
2929### Findings Log
@@ -45,13 +45,117 @@ If you discover a security vulnerability in MyFans, please report it responsibly
4545
4646### Active Findings
4747
48- * No active findings at this time*
48+ ```
49+ ### Finding #6 - Low - 2026-07-25
50+ **Component**: Backend
51+ **Category**: Dead Code / Attack Surface
52+ **Description**: Deprecated duplicate auth stacks (`src/auth`, `src/refresh-module`,
53+ `src/users-module`) remain in the tree alongside the canonical `src/auth-module` +
54+ `src/users` stack, each with their own JWT signing/expiry configuration
55+ (`backend/src/auth-module/auth.module.ts` vs `backend/src/users/users.module.ts`).
56+ They are not wired into `AppModule` (see the comment at the top of
57+ `backend/src/app.module.ts`), so they are not reachable at runtime today.
58+ **Impact**: Divergent, largely untested duplicate auth code increases the chance
59+ that a future refactor or module-wiring change accidentally reintroduces one of
60+ these stacks (or a bypass) into the request path.
61+ **Status**: Open
62+ **Assigned To**: Backend team
63+ **Resolution**: Pending — delete the deprecated modules once call sites are confirmed
64+ fully migrated to `auth-module`.
65+ **Resolved Date**: -
66+ ```
4967
5068---
5169
5270### Resolved Findings
5371
54- * No resolved findings yet*
72+ ```
73+ ### Finding #1 - Medium - 2026-07-25
74+ **Component**: Backend
75+ **Category**: Access Control / Observability (shallow liveness)
76+ **Description**: `HealthService.getHealth()` (`backend/src/health/health.service.ts`)
77+ always returned a static `up` without probing the database or any other
78+ subsystem, and it was the only liveness/readiness signal exposed.
79+ **Impact**: An orchestrator (k8s liveness/readiness probe, load balancer health
80+ check) polling `GET /health` would see a healthy instance even when its database
81+ connection was completely down, keeping traffic routed to a non-functional pod
82+ instead of failing over.
83+ **Status**: Resolved
84+ **Assigned To**: Backend team
85+ **Resolution**: Added `GET /v1/health/ready`, which probes the database
86+ (mandatory — 503 on failure) and Soroban RPC (optional, reported only).
87+ `GET /v1/health` remains a pure liveness check by design (see issue #1443).
88+ **Resolved Date**: 2026-07-25
89+
90+ ### Finding #2 - Medium - 2026-07-25
91+ **Component**: Backend
92+ **Category**: CI/CD Gap
93+ **Description**: CI (`.github/workflows/ci.yml`) ran only the unit test suite
94+ (`npm test`) on PRs. The e2e suite — which includes the access-control and
95+ transport-security regression tests in `backend/test/rbac.e2e-spec.ts`,
96+ `cors-security.e2e-spec.ts`, and `security-hardening.e2e-spec.ts` — was never
97+ executed automatically.
98+ **Impact**: A regression in RBAC enforcement, CORS policy, or other
99+ security-hardening behavior covered only by e2e tests could be merged to `main`
100+ without CI catching it.
101+ **Status**: Resolved
102+ **Assigned To**: Backend team
103+ **Resolution**: Added a `Backend E2E` job with a Postgres service to
104+ `.github/workflows/ci.yml`, running `npm run test:e2e` on every PR; local run
105+ steps documented in `DEVELOPMENT.md` (see issue #1444).
106+ **Resolved Date**: 2026-07-25
107+
108+ ### Finding #3 - Low - 2026-07-25
109+ **Component**: Backend
110+ **Category**: Process
111+ **Description**: This `SECURITY.md` findings tracker existed only as an empty
112+ template despite known, addressable exposures already present in the backend.
113+ **Impact**: Prior and ongoing security work was not discoverable from the
114+ document meant to track it, undermining the audit trail for reviewers.
115+ **Status**: Resolved
116+ **Assigned To**: Backend team
117+ **Resolution**: Populated with the findings in this section (see issue #1445).
118+ **Resolved Date**: 2026-07-25
119+
120+ ### Finding #4 - Medium - 2026-07-25
121+ **Component**: Backend
122+ **Category**: Access Control (missing authorization boundary)
123+ **Description**: The frontend expects creator-scoped `/earnings/*` endpoints,
124+ but the only server-side aggregation was `AnalyticsController`
125+ (`GET /v1/analytics/*`), which is shared between admins and creators, gated
126+ by a manual `scopeToOwner` check, and was not even registered in `AppModule`.
127+ **Impact**: Without a dedicated, strictly-scoped earnings surface, there was
128+ pressure to either bypass the backend for financial data or hand-roll a new
129+ endpoint without the existing admin/creator scoping discipline.
130+ **Status**: Resolved
131+ **Assigned To**: Backend team
132+ **Resolution**: Added `EarningsModule` (`backend/src/earnings/`), gated by
133+ `@Roles(UserRole.CREATOR)` with every query always scoped to
134+ `req.user.userId` — no cross-creator or admin override path exists on this
135+ controller (see issue #1438).
136+ **Resolved Date**: 2026-07-25
137+ ```
138+
139+ ---
140+
141+ ### Accepted Risks
142+
143+ ```
144+ ### Finding #5 - Low - 2026-07-25
145+ **Component**: Backend
146+ **Category**: Data Exposure (credentials in transit)
147+ **Description**: The Redis health probe (`pingRedis` in
148+ `backend/src/health/health.service.ts`) sends `AUTH <password>` in the clear
149+ when `REDIS_URL` uses the non-TLS `redis://` scheme instead of `rediss://`.
150+ **Impact**: On a network segment an attacker can observe, the Redis credential
151+ used for the health check could be captured.
152+ **Status**: Accepted Risk
153+ **Assigned To**: Backend team
154+ **Resolution**: Accepted — the probe only runs over the internal
155+ Docker/VPC network in current deployments. Recommend switching to `rediss://`
156+ in any environment where that network boundary is not trusted.
157+ **Resolved Date**: -
158+ ```
55159
56160---
57161
@@ -143,4 +247,4 @@ MyFans adheres to:
143247
144248This document is reviewed and updated quarterly or after significant security events.
145249
146- ** Last Updated** : 2026-04-22
250+ ** Last Updated** : 2026-07-25
0 commit comments