Security Development Checklist — OWASP ASVS L2 + IEC 82304-1 §6
Two scope cones, one checklist
OWASP ASVS v4.0.3 Level 2 is the operative generic application
security baseline for EPPA. IEC 82304-1 §6 is the product-level safety
and security requirement for health software. The two are largely
complementary; where ASVS L2 is silent and IEC 82304-1 speaks (e.g.
product-information-for-safety), the IEC clause governs.
1. Document identity
2. Legend
- ✓ — implemented and verified.
- ◐ — partial (in code but unverified, or in one path but not all).
- ✗ — not started.
- n/a — not applicable to EPPA's current scope.
3. V1 Architecture, design and threat modelling (ASVS V1)
| Item |
ASVS ref |
Status |
EPPA notes / file |
| Use a secure SDLC (input from V1.1.1) |
V1.1.1 |
◐ |
Process defined in 11-iec-62304-lifecycle.md; not yet operational |
| Threat-model every significant feature |
V1.1.2 |
✗ |
First threat model to be produced for Epic E3 (auth + persistence) |
| Verify a single trusted code path |
V1.1.4 |
◐ |
Backend is single source of truth, but frontend currently has analysis logic too — refactor |
| Treat each tier as a separate trust zone |
V1.1.5 |
◐ |
Defined; not enforced (CORS-only) |
| Verify the high-level architecture is documented |
V1.2.1 |
✗ |
Software Architecture Description missing (see 11-iec-62304-lifecycle.md §7) |
| Verify all components are identified and have a known need |
V1.2.2 |
◐ |
Implicit in package.json / pyproject.toml; SOUP register pending |
4. V2 Authentication (ASVS V2) — auth implemented in Epic E3
| Item |
ASVS ref |
Status |
EPPA notes / file |
| Passwords ≥ 12 chars; permit longer |
V2.1.1 |
✗ |
Auth not yet implemented |
| Verify users can use Unicode passwords |
V2.1.2 |
✗ |
Same |
| Hash passwords with Argon2id (recommended) or scrypt/bcrypt with appropriate cost |
V2.4.1 |
✓ |
Argon2id is the chosen algorithm; library: argon2-cffi (Python). Configuration: time_cost=3, memory_cost=64*1024 KiB, parallelism=4 |
| Salt is unique per user (handled by argon2-cffi) |
V2.4.2 |
✓ |
Library-handled |
| Rate-limit authentication attempts |
V2.2.1 |
✗ |
Rate-limit middleware planned in Epic E3 |
| MFA available for privileged accounts |
V2.7.1 |
✗ |
MFA via TOTP (RFC 6238) planned |
| Verify reauth required for sensitive actions |
V2.5.6 |
✗ |
E.g. before exporting patient data |
| Avoid security questions |
V2.1.12 |
✓ |
No security-questions in scope |
| Session tokens are JWT RS256 (recommended) |
V2.10 |
✗ |
Plan: JWT RS256 with rotated keys; refresh-token rotation; aud, iss, exp, sub, iat mandatory |
| Verify HTTPS-only auth surface |
V2.2.6 |
◐ |
TLS terminator inherited from hosting; HSTS planned (see V14) |
| Account-lockout after N failed attempts with exponential backoff |
V2.2.1 |
✗ |
Planned |
5. V3 Session management (ASVS V3)
| Item |
ASVS ref |
Status |
EPPA notes / file |
| Sessions generated by trusted server-side generator |
V3.2.1 |
✗ |
JWT issuance server-side (Epic E3) |
| Verify session tokens have at least 64 bits of entropy |
V3.2.2 |
✗ |
UUIDv4 or longer for refresh tokens |
| Logout invalidates the session |
V3.3.1 |
✗ |
Server-side refresh-token revocation list |
| Inactivity timeout in minutes |
V3.3.2 |
✗ |
Plan: 10 min idle; 8 h max |
| Absolute session lifetime |
V3.3.3 |
✗ |
Same |
| Re-authenticate before sensitive actions |
V3.3.4 |
✗ |
Re-auth for data export |
| Verify session tokens not transmitted in URL |
V3.2.3 |
✗ |
Auth header only |
6. V4 Access control (ASVS V4)
| Item |
ASVS ref |
Status |
EPPA notes / file |
| Verify that access control is enforced at trusted service layer |
V4.1.1 |
✗ |
Backend route guards (FastAPI dependencies); no client-side gating |
| Verify that all user data is owned by a user / org |
V4.2.1 |
◐ |
Patient and related entities will carry organization_id (Epic E3) |
| Verify principle of least privilege |
V4.1.3 |
✗ |
Three roles planned: admin, clinician, viewer |
| Verify directory browsing disabled and access to source / metadata files blocked |
V4.1.5 |
✗ |
nginx/Cloudflare default deny on .git, .env, etc. |
| Verify access to administrative interfaces enforced |
V4.3.1 |
✗ |
Admin routes require admin role and MFA |
| Verify that no exposed admin paths in production builds |
V4.3.2 |
✗ |
Confirm against any FastAPI debug router |
7. V5 Validation, sanitisation, encoding (ASVS V5)
| Item |
ASVS ref |
Status |
EPPA notes / file |
| Verify input validation occurs server-side |
V5.1.1 |
◐ |
Pydantic models in FastAPI; comprehensive coverage TBD |
| Verify URL path/parameters use allow-listed schemas |
V5.1.4 |
◐ |
Pydantic-based |
| Verify structured data is validated against a schema |
V5.1.5 |
◐ |
Marker JSON validated; image upload size capped |
| Verify HTML sanitisation for any user content |
V5.2.1 |
✓ |
React's default escaping; no dangerouslySetInnerHTML permitted |
| Verify SSRF protections on any URL fetch |
V5.2.6 |
✗ |
EPPA does not currently fetch external URLs on behalf of users |
| Verify parameterised queries everywhere (no string-concat SQL) |
V5.3.4 |
✓ |
SQLAlchemy ORM only; no raw SQL |
| Verify file uploads enforce expected MIME and size |
V5.4.2 |
◐ |
Size capped; MIME check planned |
| Verify deserialisation of untrusted data is safe |
V5.5.1 |
✓ |
JSON only; no pickle |
8. V7 Error handling and logging (ASVS V7)
| Item |
ASVS ref |
Status |
EPPA notes / file |
| Verify generic 4xx/5xx responses with no stack traces in production |
V7.1.1 |
◐ |
FastAPI: debug=false in production; verify across deployment configs |
| Verify all auth decisions are logged |
V7.1.3 |
✗ |
Audit log in Epic E3 |
| Verify all sensitive operations are logged |
V7.1.4 |
✗ |
Same |
| Verify log integrity (write-once / append-only) |
V7.2.1 |
✗ |
Plan: AuditLog table with insert-only DB role + WORM bucket |
| Verify no sensitive data in logs (PII, PHI, credentials) |
V7.1.4 |
◐ |
Convention in place; periodic audit pending |
| Verify time source authoritative across all components |
V7.3.1 |
✗ |
NTP / time server alignment |
| Verify log retention aligns with regulatory requirement |
V7.3.4 |
✗ |
10 years for clinical records (see 30-gdpr-dpia.md §7); 90 days for web access logs |
9. V8 Data protection (ASVS V8)
| Item |
ASVS ref |
Status |
EPPA notes / file |
| Verify sensitive data is identified and protected per policy |
V8.1.1 |
◐ |
DPIA defines scope |
| Verify data minimisation (capture only what's needed) |
V8.1.6 |
✓ |
Photos limited to required views; no audio; no continuous video |
| Verify encryption at rest for PII / PHI |
V8.3.4 |
✗ |
pgcrypto planned (Epic E3) |
| Verify keys are managed via a KMS / HSM |
V8.3.5 |
✗ |
Cloud KMS-backed (Epic E3) |
| Verify removable media restrictions for backups |
V8.2.1 |
✗ |
Backups stored in encrypted object storage only |
| Verify no caching of sensitive responses by the browser |
V8.3.6 |
✗ |
Cache-Control: no-store on authenticated routes |
| Verify autocomplete disabled on sensitive forms |
V8.2.2 |
✗ |
autocomplete="off" on password fields |
10. V9 Communications (ASVS V9)
| Item |
ASVS ref |
Status |
EPPA notes / file |
| TLS 1.2 or 1.3 only |
V9.1.1 |
◐ |
TLS 1.3 in current deployment; verify cipher list |
| Verify weak ciphers disabled (no RC4, DES, MD5) |
V9.1.2 |
◐ |
Confirm via testssl.sh |
HSTS with includeSubDomains; preload |
V9.1.4 |
✗ |
Plan: 6-month max-age, preload after stable |
| Verify certificates monitored for expiry |
V9.1.3 |
◐ |
Let's Encrypt auto-rotation in place |
| Verify TLS for all outbound calls including processors |
V9.2.1 |
◐ |
All outbound HTTPS |
| Verify backend-to-DB encryption |
V9.2.2 |
◐ |
TLS to Postgres (Epic E3) |
11. V10 Malicious code (ASVS V10)
| Item |
ASVS ref |
Status |
EPPA notes / file |
| Verify integrity controls (SRI for third-party scripts) |
V10.1.1 |
✗ |
No third-party CDN scripts currently; if added, SRI mandatory |
| Verify dependencies are scanned (SCA) |
V10.3.1 |
✓ |
CI runs SBOM/SOUP generation plus Node/Python audit report evaluation with a high severity gate; policy: fronts/eppa/docs/security/supply-chain-policy.md |
| Verify build pipeline is hardened (signed releases) |
V10.3.2 |
✗ |
Plan: cosign/sigstore for container images |
| Verify supply-chain integrity (lockfiles + reproducible builds) |
V10.3.3 |
◐ |
package-lock.json and python/requirements.txt are the current dependency sources; SBOM/SOUP generation verifies they remain parseable |
12. V11 Business logic (ASVS V11)
| Item |
ASVS ref |
Status |
EPPA notes / file |
| Verify business workflows have a defined sequence |
V11.1.1 |
◐ |
Four-view capture has a defined order; enforced in UI but not server-side |
| Verify rate-limit on business-sensitive actions (export, multiple analyses) |
V11.1.4 |
✗ |
Plan: per-user export rate limit |
| Verify idempotency keys on POST endpoints that create data |
V11.1.6 |
✗ |
Required to prevent duplicate analyses on retries (also mitigates H3 in 12-iso-14971-risk.md) |
13. V12 Files and resources (ASVS V12)
| Item |
ASVS ref |
Status |
EPPA notes / file |
| File uploads quarantined and scanned |
V12.1.1 |
✗ |
Plan: per-file size and MIME validation; antivirus scan optional |
| File-upload paths never set by user input |
V12.1.2 |
✓ |
Storage keys are server-generated UUIDs |
| Verify files not stored as executables |
V12.1.3 |
✓ |
Image files only; Content-Disposition: attachment on download |
| Verify file uploads accept only safe MIME types |
V12.3.5 |
◐ |
image/jpeg, image/png, image/heic |
| Verify image processing library has known-good version |
V12.4.1 |
◐ |
Pillow / OpenCV — version pinning required (SOUP register) |
14. V13 API and web service (ASVS V13)
| Item |
ASVS ref |
Status |
EPPA notes / file |
| Verify API authentication is enforced on every endpoint |
V13.1.1 |
✗ |
Public health-check endpoint excepted |
| Verify schema validation on every JSON payload |
V13.1.4 |
✓ |
Pydantic on FastAPI |
| Verify CORS allow-list is configured |
V13.2.1 |
◐ |
CORS configured; verify per environment |
| Verify HTTP methods are restricted per route |
V13.2.2 |
✓ |
FastAPI route decorators |
| Verify idempotent operations are explicitly handled |
V13.2.3 |
✗ |
Same as V11.1.6 |
| Verify error responses are structured |
V13.2.5 |
◐ |
Standard FastAPI {detail: ...} |
15. V14 Configuration (ASVS V14)
| Item |
ASVS ref |
Status |
EPPA notes / file |
| Verify a hardened production configuration |
V14.1.1 |
◐ |
debug=false; verify environment matrix |
| Verify dependencies pinned and reproducible |
V14.2.1 |
◐ |
package-lock.json and python/requirements.txt feed the machine-generated SBOM/SOUP artifacts; Python range specifiers remain to be tightened where clinically relevant |
| Verify default credentials removed |
V14.3.1 |
✓ |
No default creds in code |
| Verify secrets in env vars or KMS, not in source |
V14.3.2 |
✓ |
.env not committed; secret manager planned |
| Verify subresource integrity for any CDN-hosted assets |
V14.4.1 |
✗ |
None currently |
| Verify CSP set with sane defaults |
V14.4.3 |
✗ |
Plan: nonce-based CSP, no unsafe-inline |
Verify cookies have HttpOnly, Secure, SameSite=Strict (or Lax only when required) |
V14.4.6 |
✗ |
Auth cookies (when used) |
| Verify HSTS header set |
V14.4.5 |
✗ |
Same as V9.1.4 |
Verify X-Content-Type-Options: nosniff |
V14.4.4 |
✗ |
Default header |
Verify Referrer-Policy: strict-origin-when-cross-origin |
V14.4.7 |
✗ |
Default header |
16. Health-software security (IEC 82304-1 §6)
| IEC 82304-1 §6 requirement |
EPPA mapping |
Status |
| §6.1 Information for safety in product information |
Non-device disclaimer in every surface |
✓ DRAFT — see 91-non-device-disclaimer.md |
| §6.2 Product safety risk management aligned with ISO 14971 |
Risk file |
✓ DRAFT — see 12-iso-14971-risk.md |
| §6.3 Security risk management aligned with IEC TR 60601-4-5 / IEC 81001-5-1 |
Security risk register |
✗ |
| §6.4 Verification of the safety and security of the health software |
V&V plan + this checklist |
◐ |
| §6.5 Validation of the health software |
Clinical evaluation (out of this doc's scope) |
✗ |
| §6.6 Maintenance and changes |
Change management process |
◐ — see 11-iec-62304-lifecycle.md §9 |
| §6.7 Decommissioning |
Procedure for end-of-life data export and key destruction |
✗ |
17. Cybersecurity for medical devices — MDCG 2019-16 cross-reference
MDCG 2019-16 Rev.1 lays out cybersecurity expectations for the EU MDR
technical file. Most of MDCG 2019-16 is covered by the ASVS L2 + IEC 82304-1
items above. Specific MDCG 2019-16 requirements additional to ASVS:
| MDCG 2019-16 item |
Mapping |
| SBOM (Software Bill of Materials) |
SOUP register in 11-iec-62304-lifecycle.md §5 + automated SBOM generation and vulnerability gate in CI |
| Coordinated vulnerability disclosure (CVD) |
EPPA must publish security.txt (RFC 9116) and an Acceptable Use Policy |
| Patch and update mechanism |
OTA update plan for backend; mandatory release-note section on security fixes |
| Post-market cybersecurity surveillance |
Subscribe to CVE feeds for all SOUP; severity triage SLA |
18. Coordinated vulnerability disclosure — security.txt
A /.well-known/security.txt (RFC 9116) skeleton:
Contact: mailto:security@labis-uca.com.ar
Expires: 2027-05-22T00:00:00Z
Preferred-Languages: es, en
Canonical: https://eppa-docs.pages.dev/.well-known/security.txt
Policy: https://eppa-docs.pages.dev/security-policy
Acknowledgments: https://eppa-docs.pages.dev/security-acknowledgments
19. Aggregated open questions
- Confirm KMS provider for at-rest encryption and JWT signing key
storage.
- Confirm CSP policy before any release that admits third-party
scripts.
- Confirm SBOM toolchain —
cyclonedx-py and cyclonedx-node are
conventional.
- Confirm penetration-test cadence — annual minimum for Class IIa SaMD
per MDCG 2019-16.
- Confirm rate-limit thresholds per route — must not block legitimate
clinician usage but must throttle credential stuffing.
References