โ† Tilbage til My Medicus
Sprog ยท Language
๐Ÿ‡ฉ๐Ÿ‡ฐ DK๐Ÿ‡ฌ๐Ÿ‡ง EN๐Ÿ‡ช๐Ÿ‡ธ ES๐Ÿ‡ฉ๐Ÿ‡ช DE๐Ÿ‡ซ๐Ÿ‡ท FR๐Ÿ‡ฎ๐Ÿ‡น IT๐Ÿ‡ต๐Ÿ‡น PT๐Ÿ‡น๐Ÿ‡ท TR

What is your security around My Medicus?

medicus.global ยท 2026-05-05


The patient's voice

"All the information was entered by me, and I understand that rescuers
and doctors can read it โ€” to give them the best possible advance
knowledge of my entirely personal situation, especially in an emergency.
My love for life is greater than the country's rules about data security."

That is the adult, voluntary decision behind every created My Medicus profile. Our job is to honour the patient's choice: keep the data secure, show it only to whoever holds the correct PIN, let the patient see every scan, and let the patient revoke the card the second it's lost. The rest of this document explains how.


Question

"What security do you have for My Medicus?"

Answer โ€” our core view

In an emergency, the patient's greatest wish is to recover. That's what we serve. Security is the means, not the end.

Three principles stand above everything else:

  1. The patient is the author. All information on the card is entered by the patient themselves with consent. We don't import from other databases. Less is better.
  2. The benchmark is everyday life, not an ideal state. A lost wallet contains national ID, social security card, organ donor card, credit cards, photos. The pharmacy shouts your ID number across the counter. Our card is better than the exposure that already happens every week โ€” encrypted, PIN-locked, audit-logged, revocable.
  3. We do everything possible, and we are honest about what we cannot. When a paramedic legitimately scans the card, that person can take a photo of the screen. We cannot prevent it. Defense: the patient sees every scan in their "My log" and can revoke the card with one click.

What was concretely tested

19 attack scenarios against two accounts in the live database โ€” one demo account and one real new user. Tools: direct HTTP requests, parallel execution, SQL introspection of the production database, response parsing.

Result: 14 attacks met defenses that held. 5 vulnerabilities were found and closed the same day.

The 14 defense layers that held

Attack Why the attack failed
Theft of the entire database Allergies, medication, national IDs, passport, EHIC and insurance numbers are encrypted with AES-256-GCM. The key lives in a separate secret store, never in the database. If you steal the DB file, you get unreadable text
Brute-force on 6-digit PIN Progressive delays kick in at the 5th wrong attempt: 5 sec โ†’ 30 sec โ†’ 60 sec between each
SQL injection on login form All database queries use parameterized queries โ€” five different injection payloads were rejected
Direct API calls without login All protected endpoints return HTTP 401
Token guessing Tokens are 32 hex characters derived via SHA-256. Search space: 16^32. 50 random guesses โ†’ 0 hits
Path traversal to backups or config /_db_backups/, /.env, /.git, /medicus.db, /wp-config.php all return 404
Email enumeration via "forgot password" Consistent generic response regardless of whether the email exists โ€” no info leak
XSS in public fields Server rejects malformed input, no reflection of HTML/JS
Physical wallet theft without the card's PIN PIN gate stops all incorrect attempts
10 parallel brute-force attempts Rate-limit applies per token, not per request
Audit-log deletion via DELETE endpoint No DELETE endpoints exposed
Admin token guess (admin, 1234, letmein) All return 401
Trying to make the server leak secrets via error payloads Neither the encryption key nor Stripe secrets appear in error output
Cross-origin abuse from another website Browser blocks via same-origin policy

The 5 vulnerabilities found and closed

# What Severity What was done
F1 Login responded 200 ms slower when the email was registered than when it wasn't. An attacker could thus determine if an account exists ๐Ÿ”ด Critical Login now runs Argon2id verification always (also against unknown emails, with a dummy hash). Constant response time. Generic error message
F2 No security headers (HSTS, CSP, X-Frame, X-Content-Type, Referrer-Policy, Permissions-Policy) ๐Ÿ”ด Critical All 6 headers now added to all responses via middleware. CSP locks script/img/style/frame to whitelisted sources
F3 A stolen card has the QR code + PIN printed directly on it. The thief gets access until the owner revokes ๐ŸŸ  High (1) Patient sees every scan in their dashboard ("My log" โ€” IP prefix, country, timestamp). (2) Owner can revoke the card with one click โ†’ all old printed cards die instantly + new PIN generated
F4 /admin returned SPA HTML to everyone, revealing the admin panel's existence ๐ŸŸก Low Now returns the same 404 as nonexistent routes for unauthenticated users
F5 Forgot-password could be abused to flood a victim's inbox (1,000 reset emails/hour) โ€” and simultaneously damage our own sender reputation ๐ŸŸ  High If the user has a valid reset token (max 2 hours old), it is reused instead of sending a new email. Plus per-email rate-limit of 2/min

What we deliberately have NOT built โ€” and why

Choice Reasoning
No national-ID login (MitID, BankID, etc.) on paramedic view The patient is unconscious on the golf course. The paramedic doesn't have national-ID credentials โ€” and even if they did, we don't have 90 seconds to log them in. PIN-on-card is the practical answer that works globally
Not "zero-knowledge" The server CAN decrypt the fields โ€” that's a precondition for paramedic access. We don't call anything "zero-knowledge" that isn't
No automatic data import Every field is chosen by the user. No auto-import from other health platforms

What we cannot protect against

If a paramedic legitimately scans the card with the correct PIN, that person can photograph the screen. We cannot prevent it โ€” that's the price of having the data visible at all in an emergency. Defenses:

This is the same security model as a physical medical-ID bracelet for diabetics: data is visible to rescue personnel, and we accept that a pickpocket could also see it. The difference is that our model gives the patient control over who sees what and when โ€” not just visibility.

What we commit to


Questions? Write to peter@medicus.global

medicus.global ยท security-my-medicus-en.md