GenPRES is a medical decision support system for medication safety in pediatric and adult care. Security vulnerabilities in this software could directly impact patient safety. We take security extremely seriously and appreciate responsible disclosure of any security issues.
The current document is a first draft and will be expanded over time to include more details on our security practices, vulnerability management, and best practices for contributors.
| Version | Supported | Status |
|---|---|---|
0.1.x-alpha (current line, see Directory.Build.props) |
✅ | Pre-release, active development |
| Older pre-releases | ❌ | Not supported |
Versions are derived by EasyBuild.ShipIt from the commit history; see DEVELOPMENT.md.
DO NOT open a public issue for security vulnerabilities.
-
Report privately via one of these methods:
- GitHub Security Advisories (preferred): Use the "Report a vulnerability" button in the Security tab
- Email: info@genpres.nl
- Subject line:
[SECURITY] Brief description of issue
-
Include in your report:
- Description of the vulnerability
- Steps to reproduce the issue
- Potential impact (especially related to patient safety)
- Affected versions
- Suggested fix (if available)
- Whether you plan to publicly disclose (and timeline)
-
Expected response timeline:
- GenPRES is maintained by a small team. We respond as soon as possible and keep you informed while we assess and fix the issue.
- Security patch release: Based on severity
-
Coordinated disclosure:
- We will work with you to understand and validate the issue
- We will develop and test a fix
- We will coordinate public disclosure timing
- We will credit you in the security advisory (unless you prefer to remain anonymous)
We handle reports in order of severity: the more severe the issue, the higher its priority. We do our best to address every report as soon as possible, but cannot guarantee fixed response times.
- Remote code execution
- Privilege escalation
- Patient data exposure
- Authentication bypass
- Authorization bypass
- Sensitive data leakage
- Information disclosure
- Denial of service
- Minor information disclosure
- Configuration issues
- Never commit sensitive data (credentials, API keys, patient data)
- Use parameterized queries (SQL injection prevention)
- Validate and sanitize all user inputs
- Follow principle of least privilege
- Review CONTRIBUTING.md for secure coding guidelines
- Keep dependencies up to date
- Review dependency security advisories
- Use Dependabot or similar tools
- Audit third-party packages regularly
- Follow MDR (EU Medical Device Regulation 2017/745) security requirements
- Maintain audit logs for all security-relevant events
- Implement access controls appropriate for medical software
- Ensure GDPR compliance for patient data
- Implement secure session management
- Use strong password policies
- Support multi-factor authentication where applicable
- Implement proper role-based access control (RBAC)
- Encrypt sensitive data at rest and in transit
- Implement secure key management
- Follow data minimization principles
- Ensure secure backup and recovery procedures
A full posture assessment of GenPRES with file:line evidence, severity per deployment context (dev / on-prem / SaaS), MDR / 21 CFR Part 11 mapping, and a remediation roadmap is maintained in
docs/security/2026-04-10-security-review.md. The list below is the high-level summary; refer to the security review for the authoritative state. The threats themselves, by STRIDE category, are kept indocs/security/threat-model.md.
-
Input Validation
- Comprehensive validation of all medication orders
- Unit of measure validation
- Dosage range validation
- Type-safe F# domain modeling
LogAnalyzerenforces a strict regex allow-list (^genpres_[A-Za-z0-9_]+\.log$) on log filenames, explicitly rejects path-traversal segments (..,/,\), and applies a 50 MB size cap
-
Authentication & token handling
- Admin password compared with
CryptographicOperations.FixedTimeEquals(constant-time, no per-character timing leak), once, atAdminCommand.ValidatePassword - Every other admin operation (
ListLogFiles,AnalyzeLogFile,ReloadResources) is gated by the short-lived HMAC-SHA256 token (1-hour TTL) that exchange issued, signed under the server's mode, so a token of a demo or development server never verifies on a production server that shares its password; signature verification usesFixedTimeEquals; the password never travels again - Auth token kept in browser memory only — never persisted to
localStorage/sessionStorage; cleared on logout - Server fails closed: when
GENPRES_PASSWORDis unset (or empty / whitespace) all admin operations are rejected - Production password policy enforced at startup: when
GENPRES_PROD=1, the server refuses to bind any HTTP listener ifGENPRES_PASSWORDis shorter than 16 characters. A missing, empty or whitespace-only password starts the server with every admin operation disabled and prints a warning. Operators must inject a CSPRNG-generated value (e.g.openssl rand -base64 32)
- Admin password compared with
-
Logging
- Calculation operations and requests logged (operational logging)
- Error conditions recorded
- Debug logging (
GENPRES_LOG=d) and debug mode (GENPRES_DEBUG=1) refuse the start in production (GENPRES_PROD=1) - The audit of who did what is the
audit_entrytable of the session store (ADR-0007): every launch, Session opening and ending, signature committed or refused, failed PIN entry and PIN change, written in the same transaction as the act. It is built on the SQLite store in demo mode only, and nothing reads it back yet (#824). It is not tamper-evident; a tamper-evident audit trail is a §7.2 remediation item, see security review F1
-
Data Privacy
- Patient data is persisted by the session store (ADR-0007) and in the log files. The store keeps the signed order plan versions with the patient they were signed on (name and date of birth included), the EHR data each Session opened on, and the weight, height and gestational age measured in a Session. It runs on SQLite in demo and development only; a production server refuses
GENPRES_DB_CONNECTION, and until the scope decision (#580) refuses every launch, Session and signature. The order log holds age, weight and the order; handledata/logsas patient data - No retention limit yet: every store table is insert-only and no row is ever deleted. The retention period, and the legal basis for keeping what the audit records, are open questions of plan 516, to be answered before a production engine holds the store
- GDPR-compliant data handling
- Secure communication channels
- Secrets redacted in startup banner:
GENPRES_URL_IDis masked to its last-5 characters prefixed with***;GENPRES_PASSWORDis shown only as***orNOT SET. The full proprietary Sheet ID never reaches logs, screenshots, or bug reports
- Patient data is persisted by the session store (ADR-0007) and in the log files. The store keeps the signed order plan versions with the patient they were signed on (name and date of birth included), the EHR data each Session opened on, and the weight, height and gestational age measured in a Session. It runs on SQLite in demo and development only; a production server refuses
-
Code Security
- Type-safe F# implementation
- Immutable data structures
- Comprehensive test coverage
- Newtonsoft.Json
TypeNameHandlingis pinned toNoneinInformedica.Utils.Lib/Json.fsand guarded by three Expecto regression tests in theJsonSecuritysub-module — eliminates the canonical gadget-chain RCE vector by default. A SECURITY block-comment documents the policy; opting in to polymorphic deserialization requires a localSerializationBinderallow-list, never a global setting change
-
Dependency Management
- Dependencies pinned via
paket.lockandpackage-lock.json; updates are reviewed manually - Dependabot security updates are enabled for the client's npm dependencies and open a pull request per advisory; they do not cover the .NET side, since Dependabot cannot read Paket's lock file
- No SBOM generation or secret scanning (see the checklist below and security review E8)
- Dependencies pinned via
-
Build & Deployment
- Proprietary
GENPRES_URL_IDis never baked into the published Docker image — theDockerfiledeclaresENV GENPRES_URL_ID=/ENV GENPRES_PASSWORD=with empty defaults so the variables remain discoverable in container management UIs (Plesk, Portainer, Kubernetes manifests). Operators inject the real values at runtime viadocker run -e, Docker secret, or Kubernetes secret .envis gitignored (opt-in.gitignorestrategy) and never tracked- Pre-commit hooks (Husky + Fantomas + markdown-lint) prevent unformatted code from being committed
- Documented production password policy in
.env.exampleandDEVELOPMENT.md(Password policy section)
- Proprietary
- Dependency advisories — Dependabot security updates on the client's npm packages. The .NET packages are not covered: Dependabot does not read
paket.lock, so a Paket advisory is found only by a manual check - Security-focused code reviews — the security review of 2026-04-10 and the baseline in force it produced
- Threat model — STRIDE threat model, a living document revised in a pull request whenever a threat or a mitigation comes to mind
- Secret scanning — no
gitleaksor equivalent in the pre-commit hook or in CI (E8) - SBOM generation — nothing produces a bill of materials for a published image
- Advisory checks for the .NET dependencies — the gap Dependabot leaves
- Penetration testing — the review of 2026-04-10 was static with light dynamic verification only; nothing has probed a running deployment
- Security certification for medical device software — tracked with the rest of the MDR work, outside this repository
In the event of a confirmed security incident:
- Containment: Immediate actions to limit impact
- Assessment: Full scope and impact analysis
- Remediation: Fix development and testing
- Notification: Inform affected parties
- Documentation: Record the incident and how it was resolved
- Post-mortem: Lessons learned and process improvements
GenPRES is not MDR certified yet. Development is aimed at meeting the EU Medical Device Regulation (MDR 2017/745) and the GDPR; the applicable ISO / NEN standards will be added when the regulatory strategy is settled.
We believe in recognizing security researchers who help keep GenPRES secure:
- Public acknowledgment in security advisories (with permission)
- Credit in CHANGELOG.md for security fixes
- Recognition in the release notes
We currently do not offer a bug bounty program but greatly appreciate responsible disclosure.
For non-security questions about GenPRES, please use:
- GitHub Issues for bugs and features
- GitHub Discussions for questions and ideas
- See SUPPORT.md for more information
This security policy may be updated periodically. Check the commit history for changes.