Coordinated vulnerability disclosure
Every piece of software has bugs. We'd rather you found ours first.
This is diagnos's vulnerability disclosure program. We don't pay cash — right now we simply can't. We pay in public gratitude, a spot in the hall of fame, and the certainty that somebody's medical report got safer because of your contribution.
curl https://diagnos.health/.well-known/security.txt Contact: mailto:[email protected]Contact: mailto:[email protected]Policy: https://diagnos.health/en/bounty/Preferred-Languages: pt-BR, en, es, it, frExpires: 2027-09-16T00:00:00Z Quick access
All ten sections on this page — jump straight to the one you need.
Hall of fame
Every valid vulnerability lands on this list, under whatever name you pick — your name, your handle, your @, or none of the above.
| # | Researcher | What they found | When |
|---|---|---|---|
| 001 | YOU | this row is reserved | whenever you like |
| 002 | — | — | — |
| 003 | — | — | — |
| 004 | — | — | — |
| 005 | — | — | — |
I WANT YOU
FOR DIAGNOS SECURITY
Security posture
Controls already in production
-
Your password never reaches us
Login runs on OPAQUE, a PAKE: the server never sees your password, not even during login. It only keeps a registration_record, which is useless on its own.
-
The server can't open your vault
Keys are born on your device. The server only ever receives ciphertext — there's no line of code on the other end that opens a KEK.
-
Replaying a request doesn't work
Every sensitive request carries a nonce + timestamp, primary key (scope_id, ts, nonce) in D1, a 120s clock tolerance, and a 300s retention window swept by cron.
-
Every relevant request becomes a record
We write one object per relevant request to R2. The write is billed and runs off the response's critical path — auditing doesn't slow anyone down.
-
The most sensitive domain is the most locked down
sign.diagnos.health runs a genuinely enforced default-src 'none' CSP — it blocks, not just reports — with SRI computed at build time. The device cookie is __Host-, HttpOnly, Secure, SameSite=Strict.
-
Clinical data knows where it lives
Reports and images sit in an R2 bucket with EU jurisdiction tied directly to the binding — not a promise in a contract, a setting the infrastructure enforces.
Known gaps
- We've never hired an independent penetration test. Nobody outside the company has audited this.
- No SOC 2, no ISO 27001.
- HIPAA: the technical requirements are covered, but the subprocessor contract chain (BAA) is incomplete — only two signed, the rest still in negotiation.
- The app's CSP is still report-only: it reports violations, it doesn't block anything.
- Automated vulnerability scanning still happens ad hoc, not as a continuous routine.
- The rate-limit circuit breaker is a conservative guess, never calibrated against real production traffic.
The first list is what we've already built. The second is why this page exists. We're not asking you to trust us — we're asking you to distrust us, on the record.
Program scope
Nine possible targets. The tag next to each one says whether it's in, out, or in-with-fine-print — read it before you point a tool at any of them.
| Target | Status | What it is |
|---|---|---|
| vault.diagnos.health | In scope | The product's main server — the "vault". Session, OPAQUE unlock, the ledger, signed R2 URLs, AI agents, MCP and OAuth all run through here. |
| api.diagnos.health | In scope | The same server, under the other name the product uses for it. Both entries live side by side in the code today — both are valid. |
| /api/internal/v1/* | In scope, with a catch | A prefix inside the API itself, reserved for the official app — it requires headers a bare curl won't produce on its own. Read the note below before testing this line. |
| sign.diagnos.health | In scope | The report-signing ceremony — WebAuthn/passkey, reached by link or QR code. The product's most sensitive domain. |
| app.diagnos.health | In scope | diagnos's web app. |
| diagnos.health | In scope | This site, the one you're reading right now. It's in scope even though it's static marketing HTML — but set your expectations: the worst thing you'll find here is an open redirect. |
| SDK · CLI · API Apache-2.0 | In scope | SDK, CLI and API in Python, Apache-2.0 licensed. The code is heading to a public repository soon — reading it is welcome. |
| *.diagnos.health | Out of scope | Any *.diagnos.health not on this list is out of scope and outside the safe harbor. It's the standard GitHub made popular: we can only authorize research on systems that are ours. |
| cloudflare · google · modal · sentry · … | Out of scope | Cloudflare, Google/Firebase, Modal, Sentry and the like. Report to them, not us — unless the problem is clearly in our integration. |
About the "internal" audience (and why curl alone gets you nowhere)
Required headers
The internal audience requires, all at once:
Authorization: Bearer <Firebase ID token>X-AppCheck-TokenX-Signature-HmacX-Signature-NonceX-Signature-Timestamp
What doesn't exist
- There's no X-Device-Challenge. The name circulated internally, but it never existed in a single line of code.
- There's no automatic workspace lockout. No wrong call locks an account by itself — that one also circulated, and it's also false.
What's actually there
What's actually there, and says the same thing:
- Per-route rate limiting, plus a circuit breaker per scope: 600 requests per window.
- Real replay protection: primary key (scope_id, ts, nonce) — a repeated nonce returns 409, not 401.
- Brute-force throttling on login: 10 attempts in 15 minutes per account, best-effort.
- Every 4xx/5xx becomes an anonymous security signal; high-severity ones open an exception a human reviews before any block happens.
Test the internal audience through the web app, with your own account — the headers get emitted naturally, and everything you do there is in scope and covered by the safe harbor. Hammering /api/internal/v1/* directly with curl proves nothing beyond a collection of 401s — and it just creates noise a human has to triage by hand.
Patient data
What not to do
- Don't open the exam.
- Don't scroll.
- Don't take a screenshot.
- Don't copy the ID "to check later".
What to do
- Report it right away, with the minimum detail needed to prove the problem exists.
- The proof of concept demonstrates access, never content — for example: "I could list records from other workspaces via endpoint X by swapping parameter Y", without pasting the report itself.
- Delete every local copy: cache, screenshots, Burp history, proxy logs.
- Never exfiltrate, download, share, publish, or try to monetize patient data — not even to prove impact.
Legal grounds
Health data is sensitive personal data under Brazil's LGPD, its data-protection law (Article 5, II combined with Article 11).
And §4 of Article 154-A of the Brazilian Penal Code increases the sentence by 1/3 to 2/3 for disclosing, selling, or transmitting the data obtained to a third party — even when the initial access was authorized. In other words: this policy's safe harbor covers you getting in; it doesn't cover you taking anything out.
Tem uma consequência que é sua, não só nossa: quem decide o que fazer com o dado é, por definição, o controlador dele. Se você baixar, guardar ou compartilhar o que achou, você deixa de ser alguém testando o sistema e vira isso sozinho — respondendo direto perante o titular nos termos dos dois regimes, sem cobertura nenhuma desta política. E tirar esse dado do bucket europeu para qualquer outro lugar também é transferência internacional de dado pessoal, com regime próprio nos dois lados: LGPD, arts. 33 a 36; GDPR, Capítulo V, arts. 44 a 49.
E se o que você achou não é uma falha em potencial, mas exposição que já aconteceu, o seu relatório é o que dispara, para nós, o prazo legal de notificar a autoridade e o titular — até 72 horas pelo GDPR (Art. 33), até 3 dias úteis pela LGPD (Resolução CD/ANPD nº 15/2024). É por isso que pedimos para reportar na hora, em vez de continuar investigando atrás de um achado mais completo.
This isn't bureaucracy. It's that on the other side of that JSON is a biopsy result with someone's full name on it.
Rules of engagement
While testing
- Test with your own test accounts, or accounts you created yourself.
- Run automated tooling — scanners, fuzzers — with good judgment.
- Stop at the first sign of real patient data and report it.
- Accessing, or attempting to access, someone else's account.
- Volumetric DoS, or pointing a scanner that fires thousands of requests per minute at production — dumping traffic isn't research, it's abuse.
- Social engineering our team, our patients, or our partners.
- Physical attacks.
Stopping isn't a suggestion — it's the single most important rule on this page. Full detail in Patient data.
AI use in reports
- Using AI to explore or write is fine — we're not going to pretend it doesn't happen. But you're responsible for every word and every technical claim in the report, AI-generated or not.
- Explicitly say whether an AI tool helped.
- Every report needs a proof of concept that actually works, reproduced by you. Scanner or LLM output without manual confirmation isn't a vulnerability — it's a hypothesis, and an unverified hypothesis gets closed as invalid.
A fabricated, exaggerated, or non-reproducing report gets closed without detailed feedback. Repeat offenses get you banned from the program.
In January 2026, the curl project shut down its entire bug bounty program after AI-generated reports came to vastly outnumber valid ones. In years of tracking it, not a single report produced solely by AI, without human verification, ever found a real vulnerability.
We'd rather not end up there.
Response timelines
-
Acknowledgment
We confirm receipt of your report within 5 business days.
-
Triage
We assess severity and tell you where it's headed.
-
Fix
We work the fix with priority proportional to severity.
-
Notice
We let you know once the fix ships.
-
Recognition
We offer optional public credit — and we never retaliate against good-faith research.
The full severity-and-priority ladder is in the Severity classification.
Public disclosure
We ask for 90 calendar days counted from confirmation of the issue — not from submission, which is a date only you control — before any publication.
If the fix ships sooner, we can agree on a joint disclosure date earlier.
If the issue is being actively exploited by someone else right now, that window shrinks — tell us immediately.
And never publish patient data, real credentials, or anything that raises the risk, even after the window closes.
Legal safe harbor
In practice, we commit to:
- Not pursuing or supporting any civil claim, criminal complaint, or police report against you for research done under this policy — including for any technical measure used to access a system in scope.
- If a third party threatens or brings legal action against you over that research, stating publicly and formally that your conduct was authorized, good-faith security research.
And that has limits, just as visible as the promise:
- It only covers the systems listed under Scope. We can't authorize research on a third party's system, even one reachable from ours.
- It doesn't cover conduct outside this policy's scope or rules.
- It doesn't cover taking data with you. Accessing to test is one thing; extracting is another — see Patient data and §4 of Article 154-A, which raises the penalty specifically for that.
- It doesn't apply to research done to extort or coerce anyone, nor to anyone excluded under Recognition.
Testing us from outside Brazil? This authorization is still grounded in Brazilian law — it's the law that governs the systems you'd be touching. As a courtesy, we also treat this policy as a good-faith authorization to access under whatever computer-crime law applies where you live.
Not sure whether a specific test fits this policy? Ask us first, at [email protected].
Legal basis under Brazilian law
Brazil has no CFAA, no DMCA. Those are American statutes, and pasting that language into a Brazilian policy protects nobody here — it just gives away that the text was translated, not thought through.
What actually applies is Article 154-A of the Brazilian Penal Code (Law 12,737/2012, amended by Law 14,155/2021). It makes it a crime to break into someone else's computer system "without the express or tacit authorization" of the person who uses that system.
One detail changes everything. The 2012 wording only applied when the break-in happened by "unduly violating a security mechanism" — you had to defeat some kind of lock. Law 14,155/2021 removed that requirement. Today the crime no longer turns on breaking anything: it turns on acting without authorization. Authorization became the single decisive element.
That's why this page is the express authorization the law is talking about. And that's stronger than a promise not to sue you: with authorization, the crime never comes into existence in the first place — it isn't a defense you raise after the fact, it's the absence of an element of the offense itself. Authorized conduct never becomes a crime.
Ineligible findings
It's not that we don't care — it's that without demonstrated impact, there's no way to tell it apart from noise.
Configuration and headers
- Missing security header (CSP, HSTS, X-Frame-Options) without a real exploitation PoC.
- Missing or misconfigured SPF, DKIM, or DMARC record.
- Software version disclosure in a banner, header, or public changelog, with no exploitation attached.
- Missing certificate pinning in a mobile app.
Interface and interaction
- Clickjacking on a page that performs no sensitive action.
- Self-XSS — the victim has to paste their own payload.
- Open redirect with no demonstrated additional impact.
Enumeration and rate limits
- User or email enumeration — finding out whether an account exists.
- Missing rate limiting with no proof of a viable brute force.
- CSV injection with no proven execution in the victim's environment.
Infrastructure and availability
- Volumetric denial of service, or anything that depends on generating massive traffic.
- An attack that requires intercepting someone else's traffic, without a flaw of ours that makes it possible.
Third parties and dependencies
- A flaw in a third-party library, without a PoC of specific exploitation in our environment.
- A flaw in a service or infrastructure we don't operate.
Report quality
- Scanner output with no manual PoC and no confirmation of real exploitation.
- AI-generated report with no human verification and no reproducible PoC.
Outside the threat model
- Social engineering against our team, our partners, or our patients.
- Physical attacks against an office, employee, or device.
- A bug that only shows up in an outdated browser or OS no longer supported by its maker.
- An attack that depends on the victim following the attacker's own instructions — pasting a command, installing an extension.
Think your case is the exception? Send it anyway and explain why. This list is a filter, not a wall.
Severity classification
Severity decides one thing: where you land in the fix queue. Nothing else.
| Severity | General criteria | Examples at diagnos |
|---|---|---|
| Critical | Compromises confidentiality for more than one patient, or breaks the core end-to-end guarantee — no click required from the victim. |
|
| High | Compromises data within a single workspace, or grants admin privilege inside it — still no interaction from the victim. |
|
| Medium | Real but limited impact: needs a click from the victim, or exposes metadata instead of the report's content. |
|
| Low | Minimal impact, needs unlikely conditions to line up, or is purely informational — no clear path to patient data. |
|
The final call is ours — but we explain the reasoning. Disagree, and we'll take another look.
Recognition and eligibility
Four things, in this order — the first one stings a little.
-
No money. Zero.
No "we're currently evaluating this." Zero, actually. We're a small company, and whatever money exists pays for servers and people. If that changes one day, this page changes with it — and you'll be among the first to know.
-
Product credit, maybe.
We may — at our own discretion and with zero obligation — offer credit toward the platform. No agreed value, no guarantee, not negotiable. It's not payment: it's gratitude with an invoice taped to it.
-
A spot in the hall of fame.
Every valid vulnerability gets listed — under whatever name you pick: your real name, a handle, a social @, or anonymous.
See the hall of fame -
Gratitude from people you'll never meet.
On the other end of this are doctors and patients who will never know your name. It's not much. We know it's not much. But it's true.
And we ask for one thing back: permission to cite your report — technical, no patient data — in our security changelog, once the fix ships.
Who can take part
Anyone can report a bug, and we fix it either way. What changes is credit — no public recognition or product credit for:
- Anyone who works or worked at MedDeck in the last six months — contractors included.
- A close relative of someone with privileged information about the system being tested.
- A person or entity on a sanctions list (OFAC/SDN, EU) or in a country under comprehensive embargo.
- Anyone who reached the flaw through a breach of contract or an internal leak, rather than independent research.
How to submit a report
Most reports go through the standard box. The other one exists for when waiting would actually cost us.
Only when waiting is expensive
Active exploitation happening right now. Patient data already exposed publicly. A leaked credential. This box is for that — and only that.
This can't wait What your report needs to include
- Numbered reproduction steps, in the order you actually did them.
- The real impact — what an attacker can DO, not just "I got X."
- The environment, browser, and account you used.
- A minimal, non-destructive proof of concept.
It doesn't need to be in English, and it doesn't need to look like a CVE. Clarity beats formality.
Keep everything on the private channel with us until we've agreed on disclosure together.
The file that does this for you. It's already live, and it's how an automated tool finds us before any human reads this: /.well-known/security.txt
Encrypted reports
We haven't published a PGP key yet. Want to encrypt anyway? Ask us by email and we'll send you a way to do it.
Frequently asked questions
Do you really pay nothing?
Nothing. Not cash, not crypto, not a t-shirt. We might offer product credit when it makes sense, with zero guarantee — that's gratitude with a limit, not a price in disguise.
Can I test with my real account?
You can, and it's the recommended way if you're part of the internal audience — see the "Scope" section. What you can never do, under any circumstance, is test with someone else's account.
I found patient data. Now what?
Stop. Don't open the exam, don't scroll, don't copy the ID "to confirm later." Report the finding without pasting the report's content — the "Patient data" section has the step by step, and it isn't red tape: it's the line between security research and a crime.
How long until someone replies?
We confirm receipt within 5 business days; after that, you get a position on severity and next steps. That's a service goal we hold ourselves to, not a contractual SLA clause.
Can I publish what I found?
Yes — 90 calendar days after the issue is confirmed, or sooner if we agree on a date together. Never with patient data inside, even after the window closes.
I used AI to find this. Is that a problem?
None, as long as you verified and reproduced the issue yourself, in a real environment. AI output without that check isn't a vulnerability, it's a hypothesis — the "Rules" section explains why.
Will you sue me?
No, if you followed this policy. The "Safe harbor" section is, in one sentence, the express authorization that Article 154-A of the Brazilian Penal Code requires for what you're about to do to not be a crime — that's not rhetoric, it's the text of the law.
I already reported and got no reply.
Resend it mentioning the date of your first email — email gets lost. If it's genuinely urgent, use the urgent inbox. It's not indifference: we're a small team, not a 24-hour security operations center.
That's it. Go ahead.
If you read this far, you already care about these patients' data more than plenty of people who handle it for a living. Thank you — and happy hunting.
Report a vulnerability