August 8, 2026
Uncovering a Privacy Bug in Proton Meet โ How a Simple Logic โTypoโ Earned Me $100
this is the second bug bounty received by Proton ๐ฅ

By Kenjisubagja
1 min read
At first glance, it might look correct, but let's test it with simple mathematical logic. Imagine I am an Admin, but not a Host:
IsAdmin=trueIsHost=false
Let's plug these values into the if condition:
!IsAdminevaluates tofalse!IsHostevaluates totruefalse || trueresults intrue
Because the condition evaluates to true, the system executes the return; statement inside the if block. This means the function aborts early, and the recording status is never updated on the receiving clients! As a direct result, the participant-facing recording UI is completely bypassed.
Comparing it to the Correct Logic
Interestingly, in other parts of the receiver code, Proton used the correct expected logic by utilizing the && (AND) operator:
if (!senderParticipant?.IsAdmin && !senderParticipant?.IsHost) {
return;
}if (!senderParticipant?.IsAdmin && !senderParticipant?.IsHost) {
return;
}If we apply this correct code to the Admin-but-not-Host scenario (false && true), the result is false. The system will NOT return early, and the recording state (participantsRecording) will update properly, showing the warnings to everyone.
The Impact
Due to this bug, a meeting admin who isn't the host could silently record important discussions without other participants receiving the expected recording indicator or consent UI. On a privacy-first platform like Proton, user consent is non-negotiable.
I reported this finding with a suggested severity of Low to Medium, as it directly impacts privacy consent notifications.
Resolution and Fix
The reporting process was incredibly smooth. The Proton security team was highly responsive and quickly validated the finding.
The fix was straightforward: change the receiver role check to allow either admin or host by replacing the || with &&:
TypeScript
if (!senderParticipant?.IsAdmin && !senderParticipant?.IsHost) {
return;
}if (!senderParticipant?.IsAdmin && !senderParticipant?.IsHost) {
return;
}They also added unit/regression tests to cover all role combinations:
- Host only:
Accepted - Admin only:
Accepted - Host + Admin:
Accepted - Participant only:
Rejected
For this discovery, Proton awarded a $100 bounty and listed my name in their Security Hall of Fame.
Key Takeaways
- Bugs don't have to be complicated. Sometimes, critical privacy vulnerabilities don't stem from complex memory exploits or SQL injections, but from basic logic errors (|| vs &&).
- Read code carefully. Code review is crucial. When writing negative logic (using !), our brains can easily be tricked by De Morgan's laws.
- The Importance of Unit Testing. Always write tests that cover all permutations of user states or roles to catch edge cases like this.
That wraps up my bug hunting story for today! I hope this write-up inspires fellow security enthusiasts and bug bounty hunters. Keep looking, pay attention to the smallest details, and never give up!
Happy Hacking! ๐ป๐ฅ