├── .gitignore ├── Cargo.toml ├── README.md ├── .github └── workflows │ └── rust.yml ├── list.txt ├── LICENSE.txt ├── src └── main.rs └── Cargo.lock /.gitignore: -------------------------------------------------------------------------------- 1 | /target/ -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "check-extensions" 3 | version = "1.0.0" 4 | edition = "2021" 5 | 6 | [profile.release] 7 | panic = "abort" 8 | strip = true 9 | opt-level = "z" 10 | lto = true 11 | codegen-units = 1 12 | 13 | [dependencies] 14 | app_dirs2 = "2.5.5" 15 | enum-iterator = "1.4.1" 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Potentially malicious browser extensions 2 | 3 | I’ve been documenting lots of potentially malicious browser extensions in Chrome Web Store [[1]](https://palant.info/2023/05/31/more-malicious-extensions-in-chrome-web-store/) [[2]](https://palant.info/2023/06/05/introducing-pcvark-and-their-malicious-ad-blockers/) [[3]](https://palant.info/2023/06/08/another-cluster-of-potentially-malicious-chrome-extensions/). As the lists of affected extension IDs are getting long and difficult to keep track of, I decided to add them to this repository (see list.txt). 4 | 5 | Note: Some extensions listed are no longer available via Chrome Web Store. If they were installed prior to removal however, they often remain installed. 6 | 7 | ## Using check-extensions utility 8 | 9 | Instead of checking extension IDs against the list manually, you can also [download the check-extensions utility](https://github.com/palant/malicious-extensions-list/releases/). When run without parameters, it will try locating all browser profiles of Chrome and Chromium-based browsers under your user account. A list of browser profiles to check can also be given explicitly as command line parameters. 10 | -------------------------------------------------------------------------------- /.github/workflows/rust.yml: -------------------------------------------------------------------------------- 1 | name: Rust 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | pull_request: 7 | branches: [ main ] 8 | 9 | env: 10 | CARGO_TERM_COLOR: always 11 | 12 | jobs: 13 | build: 14 | 15 | runs-on: ${{ matrix.os }} 16 | 17 | strategy: 18 | matrix: 19 | os: [ubuntu-latest, windows-latest, macos-latest] 20 | toolchain: [nightly-2023-04-16, stable] 21 | include: 22 | - toolchain: nightly-2023-04-16 23 | flags: -Z build-std=std,panic_abort -Z build-std-features=panic_immediate_abort 24 | - toolchain: stable 25 | flags: 26 | - os: ubuntu-latest 27 | target: x86_64-unknown-linux-gnu 28 | target_name: check-extensions 29 | - os: windows-latest 30 | target: x86_64-pc-windows-msvc 31 | target_name: check-extensions.exe 32 | - os: macos-latest 33 | target: x86_64-apple-darwin 34 | target_name: check-extensions 35 | env: 36 | RUSTFLAGS: 37 | 38 | steps: 39 | - uses: actions/checkout@v3 40 | - name: Install toolchain 41 | uses: actions-rust-lang/setup-rust-toolchain@v1 42 | with: 43 | toolchain: ${{ matrix.toolchain }} 44 | components: rust-src 45 | - name: Build 46 | run: cargo +${{ matrix.toolchain }} build ${{ matrix.flags }} --target ${{ matrix.target }} --release --verbose 47 | - name: Upload check-extensions artifact 48 | uses: actions/upload-artifact@v3 49 | with: 50 | name: ${{ matrix.target_name }} ${{ matrix.os }} ${{ matrix.toolchain }} 51 | path: target/${{ matrix.target }}/release/${{ matrix.target_name }} 52 | -------------------------------------------------------------------------------- /list.txt: -------------------------------------------------------------------------------- 1 | # https://palant.info/2023/05/31/more-malicious-extensions-in-chrome-web-store/ 2 | lgjdgmdbfhobkdbcjnpnlmhnplnidkkp 3 | chmfnmjfghjpdamlofhlonnnnokkpbao 4 | lklmhefoneonjalpjcnhaidnodopinib 5 | ciifcakemmcbbdpmljdohdmbodagmela 6 | meljmedplehjlnnaempfdoecookjenph 7 | lipmdblppejomolopniipdjlpfjcojob 8 | lmcboojgmmaafdmgacncdpjnpnnhpmei 9 | icnekagcncdgpdnpoecofjinkplbnocm 10 | bahogceckgcanpcoabcdgmoidngedmfo 11 | bkpdalonclochcahhipekbnedhklcdnp 12 | magnkhldhhgdlhikeighmhlhonpmlolk 13 | edadmcnnkkkgmofibeehgaffppadbnbi 14 | ajneghihjbebmnljfhlpdmjjpifeaokc 15 | nadenkhojomjfdcppbhhncbfakfjiabp 16 | pbdpfhmbdldfoioggnphkiocpidecmbp 17 | hdgdghnfcappcodemanhafioghjhlbpb 18 | fbjfihoienmhbjflbobnmimfijpngkpa 19 | kjeffohcijbnlkgoaibmdcfconakaajm 20 | djmpbcihmblfdlkcfncodakgopmpgpgh 21 | obeokabcpoilgegepbhlcleanmpgkhcp 22 | mcmdolplhpeopapnlpbjceoofpgmkahc 23 | dppnhoaonckcimpejpjodcdoenfjleme 24 | idgncaddojiejegdmkofblgplkgmeipk 25 | deebfeldnfhemlnidojiiidadkgnglpi 26 | gfbgiekofllpkpaoadjhbbfnljbcimoh 27 | pbebadpeajadcmaoofljnnfgofehnpeo 28 | flmihfcdcgigpfcfjpdcniidbfnffdcf 29 | pinnfpbpjancnbidnnhpemakncopaega 30 | iicpikopjmmincpjkckdngpkmlcchold 31 | bjlcpoknpgaoaollojjdnbdojdclidkh 32 | okclicinnbnfkgchommiamjnkjcibfid 33 | pcjmcnhpobkjnhajhhleejfmpeoahclc 34 | hinhmojdkodmficpockledafoeodokmc 35 | gcnceeflimggoamelclcbhcdggcmnglm 36 | 37 | # https://palant.info/2023/06/05/introducing-pcvark-and-their-malicious-ad-blockers/ 38 | kacljcbejojnapnmiifgckbafkojcncf 39 | jhkhlgaomejplkanglolfpcmfknnomle 40 | nkmooloiipfcknccapehflmampkaniji 41 | kgddnoifhgfdhcpbkkjdgokfnkkmdcen 42 | 43 | # https://palant.info/2023/06/08/another-cluster-of-potentially-malicious-chrome-extensions/ 44 | gbdjcgalliefpinpmggefbloehmmknca 45 | eggeoellnjnnglaibpcmggjnjifeebpi 46 | ionpbgeeliajehajombdeflogfpgmmel 47 | jaekigmcljkkalnicnjoafgfjoefkpeg 48 | aeilijiaejfdnbagnpannhdoaljpkbhe 49 | afdfpkhbdpioonfeknablodaejkklbdn 50 | anflghppebdhjipndogapfagemgnlblh 51 | anmbbeeiaollmpadookgoakpfjkbidaf 52 | bebmphofpgkhclocdbgomhnjcpelbenh 53 | bmkgbgkneealfabgnjfeljaiegpginpl 54 | ccjlpblmgkncnnimcmbanbnhbggdpkie 55 | cclhgechkjghfaoebihpklmllnnlnbdb 56 | cfegchignldpfnjpodhcklmgleaoanhi 57 | cfllfglbkmnbkcibbjoghimalbileaic 58 | cjljdgfhkjbdbkcdkfojleidpldagmao 59 | coabfkgengacobjpmdlmmihhhfnhbjdm 60 | dcaffjpclkkjfacgfofgpjbmgjnjlpmh 61 | djekgpcemgcnfkjldcclcpcjhemofcib 62 | dkbccihpiccbcheieabdbjikohfdfaje 63 | dlpimjmonhbmamocpboifndnnakgknbf 64 | dmbjkidogjmmlejdmnecpmfapdmidfjg 65 | dneifdhdmnmmlobjbimlkcnhkbidmlek 66 | doiiaejbgndnnnomcdhefcbfnbbjfbib 67 | dpfofggmkhdbfcciajfdphofclabnogo 68 | eabhkjojehdleajkbigffmpnaelncapp 69 | ealojglnbikknifbgleaceopepceakfn 70 | ebdbcfomjliacpblnioignhfhjeajpch 71 | edlifbnjlicfpckhgjhflgkeeibhhcii 72 | ehmneimbopigfgchjglgngamiccjkijh 73 | ehpgcagmhpndkmglombjndkdmggkgnge 74 | ejllkedmklophclpgonojjkaliafeilj 75 | ekjogkoigkhbgdgpolejnjfmhdcgaoof 76 | elpdbicokgbedckgblmbhoamophfbchi 77 | emeokgokialpjadjaoeiplmnkjoaegng 78 | eokjikchkppnkdipbiggnmlkahcdkikp 79 | epeigjgefhajkiiallmfblgglmdbhfab 80 | eplfglplnlljjpeiccbgnijecmkeimed 81 | fbbjijdngocdplimineplmdllhjkaece 82 | fbjhgeaafhlbjiejehpjdnghinlcceak 83 | fedchalbmgfhdobblebblldiblbmpgdj 84 | fobaamfiblkoobhjpiigemmdegbmpohd 85 | gaiceihehajjahakcglkhmdbbdclbnlf 86 | gceehiicnbpehbbdaloolaanlnddailm 87 | ggacghlcchiiejclfdajbpkbjfgjhfol 88 | gjjbmfigjpgnehjioicaalopaikcnheo 89 | gpdfpljioapjogbnlpmganakfjcemifk 90 | hjlekdknhjogancdagnndeenmobeofgm 91 | hlbdhflagoegglpdminhlpenkdgloabe 92 | hnfabcchmopgohnhkcojhocneefbnffg 93 | iabflonngmpkalkpbjonemaamlgdghea 94 | ibppednjgooiepmkgdcoppnmbhmieefh 95 | icchadngbpkcegnabnabhkjkfkfflmpj 96 | ielooaepfhfcnmihgnabkldnpddnnldl 97 | ifdepgnnjpnbkcgempionjablajancjc 98 | ijejnggjjphlenbhmjhhgcdpehhacaal 99 | iklgljbighkgbjoecoddejooldolenbj 100 | imopknpgdihifjkjpmjaagcagkefddnb 101 | jchmabokofdoabocpiicjljelmackhho 102 | jdlkkmamiaikhfampledjnhhkbeifokk 103 | jglemppahimembneahjbkhjknnefeeio 104 | jiaopkfkampgnnkckajcbdgannoipcne 105 | jjgnkfncaadmaobenjjpmngdpgalemho 106 | jlbpahgopcmomkgegpbmopfodolajhbl 107 | jpefmbpcbebpjpmelobfakahfdcgcmkl 108 | khdnaopfklkdcloiinccnaflffmfcioa 109 | kjgkmceledmpdnmgmppiekdbnamccdjp 110 | laameccjpleogmfhilmffpdbiibgbekf 111 | lagdcjmbchphhndlbpfajelapcodekll 112 | lbohagbplppjcpllnhdichjldhfgkicb 113 | ledkggjjapdgojgihnaploncccgiadhg 114 | lgecddhfcfhlmllljooldkbbijdcnlpe 115 | lkahpjghmdhpiojknppmlenngmpkkfma 116 | lkciiknpgglgbbcgcpbpobjabglmpkle 117 | lkhhagecaghfakddbncibijbjmgfhfdm 118 | lknpbgnookklokdjomiildnlalffjmma 119 | lojpdfjjionbhgplcangflkalmiadhfi 120 | mdkiofbiinbmlblcfhfjgmclhdfikkpm 121 | meffljleomgifbbcffejnmhjagncfpbd 122 | mejjgaogggabifjfjdbnobinfibaamla 123 | mhpcabliilgadobjpkameggapnpeppdg 124 | mkjjckchdfhjbpckippbnipkdnlidbeb 125 | mldaiedoebimcgkokmknonjefkionldi 126 | mlkjjjmhjijlmafgjlpkiobpdocdbncj 127 | mndiaaeaiclnmjcnacogaacoejchdclp 128 | mnlohknjofogcljbcknkakphddjpijak 129 | nhnfcgpcbfclhfafjlooihdfghaeinfc 130 | ninecedhhpccjifamhafbdelibdjibgd 131 | nmigaijibiabddkkmjhlehchpmgbokfj 132 | npdkkcjlmhcnnaoobfdjndibfkkhhdfn 133 | npmjjkphdlmbeidbdbfefgedondknlaf 134 | oakbcaafbicdddpdlhbchhpblmhefngh 135 | obdhcplpbliifflekgclobogbdliddjd 136 | ocginjipilabheemhfbedijlhajbcabh 137 | oepjogknopbbibcjcojmedaepolkghpb 138 | ofpnikijgfhlmmjlpkfaifhhdonchhoi 139 | ogadflejmplcdhcldlloonbiekhnlopp 140 | ogfjgagnmkiigilnoiabkbbajinanlbn 141 | okkffdhbfplmbjblhgapnchjinanmnij 142 | oodkhhminilgphkdofffddlgopkgbgpm 143 | pegfdldddiilihjahcpdehhhfcbibipg 144 | phfkifnjcmdcmljnnablahicoabkokbg 145 | phjbepamfhjgjdgmbhmfflhnlohldchb 146 | pjbgfifennfhnbkhoidkdchbflppjncb 147 | plmlopfeeobajiecodiggabcihohcnge 148 | pmilcmjbofinpnbnpanpdadijibcgifc 149 | pmnphobdokkajkpbkajlaiooipfcpgio 150 | pnanegnllonoiklmmlegcaajoicfifcm 151 | pnlphjjfielecalmmjjdhjjninkbjdod 152 | pooaemmkohlphkekccfajnbcokjlbehk 153 | 154 | # https://palant.info/2023/06/08/another-cluster-of-potentially-malicious-chrome-extensions/#c000003 155 | fmlpbbognkocpajihchioognkmdeeldo 156 | goaebigflkhjjblmofhoggdhebgnielo 157 | igkkmokkmlbkkgdnkkancbonkbbmkioc 158 | lopnbnfpjmgpbppclhclehhgafnifija 159 | 160 | # https://palant.info/2023/06/14/why-browser-extension-games-need-access-to-all-websites/ 161 | kgfeiebnfmmfpomhochmlfmdmjmfedfj 162 | pmlcjncilaaaemknfefmegedhcgelmee 163 | ohdgnoepeabcfdkboidmaedenahioohf 164 | dnbipceilikdgjmeiagblfckeialaela 165 | aciipkgmbljbcokcnhjbjdhilpngemnj 166 | nlmjpeojbncdmlfkpppngdnolhfgiehn 167 | phjhbkdgnjaokligmkimgnlagccanodn 168 | fkhpfgpmejefmjaeelgoopkcglgafedm 169 | kekdpkbijjffmohdaonbpeeaiknhbkhj 170 | mcmmiinopedfbaoongoclagidncaacbd 171 | ndcokkmfmiaecmndbpohaogmpmchfpkk 172 | cpmpjapeeidaikiiemnddfgfdfjjhgif 173 | ajefbooiifdkmgkpjkanmgbjbndfbfhg 174 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | CC0 1.0 Universal 2 | 3 | Statement of Purpose 4 | 5 | The laws of most jurisdictions throughout the world automatically confer 6 | exclusive Copyright and Related Rights (defined below) upon the creator and 7 | subsequent owner(s) (each and all, an "owner") of an original work of 8 | authorship and/or a database (each, a "Work"). 9 | 10 | Certain owners wish to permanently relinquish those rights to a Work for the 11 | purpose of contributing to a commons of creative, cultural and scientific 12 | works ("Commons") that the public can reliably and without fear of later 13 | claims of infringement build upon, modify, incorporate in other works, reuse 14 | and redistribute as freely as possible in any form whatsoever and for any 15 | purposes, including without limitation commercial purposes. These owners may 16 | contribute to the Commons to promote the ideal of a free culture and the 17 | further production of creative, cultural and scientific works, or to gain 18 | reputation or greater distribution for their Work in part through the use and 19 | efforts of others. 20 | 21 | For these and/or other purposes and motivations, and without any expectation 22 | of additional consideration or compensation, the person associating CC0 with a 23 | Work (the "Affirmer"), to the extent that he or she is an owner of Copyright 24 | and Related Rights in the Work, voluntarily elects to apply CC0 to the Work 25 | and publicly distribute the Work under its terms, with knowledge of his or her 26 | Copyright and Related Rights in the Work and the meaning and intended legal 27 | effect of CC0 on those rights. 28 | 29 | 1. Copyright and Related Rights. A Work made available under CC0 may be 30 | protected by copyright and related or neighboring rights ("Copyright and 31 | Related Rights"). Copyright and Related Rights include, but are not limited 32 | to, the following: 33 | 34 | i. the right to reproduce, adapt, distribute, perform, display, communicate, 35 | and translate a Work; 36 | 37 | ii. moral rights retained by the original author(s) and/or performer(s); 38 | 39 | iii. publicity and privacy rights pertaining to a person's image or likeness 40 | depicted in a Work; 41 | 42 | iv. rights protecting against unfair competition in regards to a Work, 43 | subject to the limitations in paragraph 4(a), below; 44 | 45 | v. rights protecting the extraction, dissemination, use and reuse of data in 46 | a Work; 47 | 48 | vi. database rights (such as those arising under Directive 96/9/EC of the 49 | European Parliament and of the Council of 11 March 1996 on the legal 50 | protection of databases, and under any national implementation thereof, 51 | including any amended or successor version of such directive); and 52 | 53 | vii. other similar, equivalent or corresponding rights throughout the world 54 | based on applicable law or treaty, and any national implementations thereof. 55 | 56 | 2. Waiver. To the greatest extent permitted by, but not in contravention of, 57 | applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and 58 | unconditionally waives, abandons, and surrenders all of Affirmer's Copyright 59 | and Related Rights and associated claims and causes of action, whether now 60 | known or unknown (including existing as well as future claims and causes of 61 | action), in the Work (i) in all territories worldwide, (ii) for the maximum 62 | duration provided by applicable law or treaty (including future time 63 | extensions), (iii) in any current or future medium and for any number of 64 | copies, and (iv) for any purpose whatsoever, including without limitation 65 | commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes 66 | the Waiver for the benefit of each member of the public at large and to the 67 | detriment of Affirmer's heirs and successors, fully intending that such Waiver 68 | shall not be subject to revocation, rescission, cancellation, termination, or 69 | any other legal or equitable action to disrupt the quiet enjoyment of the Work 70 | by the public as contemplated by Affirmer's express Statement of Purpose. 71 | 72 | 3. Public License Fallback. Should any part of the Waiver for any reason be 73 | judged legally invalid or ineffective under applicable law, then the Waiver 74 | shall be preserved to the maximum extent permitted taking into account 75 | Affirmer's express Statement of Purpose. In addition, to the extent the Waiver 76 | is so judged Affirmer hereby grants to each affected person a royalty-free, 77 | non transferable, non sublicensable, non exclusive, irrevocable and 78 | unconditional license to exercise Affirmer's Copyright and Related Rights in 79 | the Work (i) in all territories worldwide, (ii) for the maximum duration 80 | provided by applicable law or treaty (including future time extensions), (iii) 81 | in any current or future medium and for any number of copies, and (iv) for any 82 | purpose whatsoever, including without limitation commercial, advertising or 83 | promotional purposes (the "License"). The License shall be deemed effective as 84 | of the date CC0 was applied by Affirmer to the Work. Should any part of the 85 | License for any reason be judged legally invalid or ineffective under 86 | applicable law, such partial invalidity or ineffectiveness shall not 87 | invalidate the remainder of the License, and in such case Affirmer hereby 88 | affirms that he or she will not (i) exercise any of his or her remaining 89 | Copyright and Related Rights in the Work or (ii) assert any associated claims 90 | and causes of action with respect to the Work, in either case contrary to 91 | Affirmer's express Statement of Purpose. 92 | 93 | 4. Limitations and Disclaimers. 94 | 95 | a. No trademark or patent rights held by Affirmer are waived, abandoned, 96 | surrendered, licensed or otherwise affected by this document. 97 | 98 | b. Affirmer offers the Work as-is and makes no representations or warranties 99 | of any kind concerning the Work, express, implied, statutory or otherwise, 100 | including without limitation warranties of title, merchantability, fitness 101 | for a particular purpose, non infringement, or the absence of latent or 102 | other defects, accuracy, or the present or absence of errors, whether or not 103 | discoverable, all to the greatest extent permissible under applicable law. 104 | 105 | c. Affirmer disclaims responsibility for clearing rights of other persons 106 | that may apply to the Work or any use thereof, including without limitation 107 | any person's Copyright and Related Rights in the Work. Further, Affirmer 108 | disclaims responsibility for obtaining any necessary consents, permissions 109 | or other rights required for any use of the Work. 110 | 111 | d. Affirmer understands and acknowledges that Creative Commons is not a 112 | party to this document and has no duty or obligation with respect to this 113 | CC0 or use of the Work. 114 | 115 | For more information, please see 116 | 117 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | #![deny(elided_lifetimes_in_paths)] 2 | #![deny(explicit_outlives_requirements)] 3 | #![deny(keyword_idents)] 4 | #![deny(meta_variable_misuse)] 5 | #![deny(missing_debug_implementations)] 6 | #![deny(non_ascii_idents)] 7 | #![warn(noop_method_call)] 8 | #![deny(pointer_structural_match)] 9 | #![deny(single_use_lifetimes)] 10 | #![deny(trivial_casts)] 11 | #![deny(trivial_numeric_casts)] 12 | #![deny(unsafe_code)] 13 | #![warn(unused_crate_dependencies)] 14 | #![deny(unused_import_braces)] 15 | #![deny(unused_lifetimes)] 16 | #![warn(unused_macro_rules)] 17 | #![warn(unused_tuple_struct_fields)] 18 | #![deny(variant_size_differences)] 19 | 20 | use std::collections::HashMap; 21 | use std::path::{Path, PathBuf}; 22 | 23 | use enum_iterator::Sequence; 24 | 25 | #[derive(Debug, Sequence)] 26 | enum Browser { 27 | Chrome, 28 | ChromeBeta, 29 | ChromeCanary, 30 | Chromium, 31 | Opera, 32 | OperaBeta, 33 | OperaDev, 34 | Vivaldi, 35 | VivaldiSnapshot, 36 | Edge, 37 | EdgeBeta, 38 | EdgeDev, 39 | EdgeCanary, 40 | } 41 | 42 | impl Browser { 43 | #[cfg(target_os = "linux")] 44 | pub fn get_profile_root(self) -> Option { 45 | let mut dir = app_dirs2::get_data_root(app_dirs2::AppDataType::UserConfig).ok()?; 46 | match self { 47 | // https://chromium.googlesource.com/chromium/src/+/master/docs/user_data_dir.md#Default-Location 48 | Self::Chrome => dir.push("google-chrome"), 49 | Self::ChromeBeta => dir.push("google-chrome-beta"), 50 | Self::ChromeCanary => dir.push("google-chrome-unstable"), 51 | Self::Chromium => dir.push("chromium"), 52 | Self::Opera => dir.push("opera"), 53 | Self::OperaBeta => dir.push("opera-beta"), 54 | Self::OperaDev => dir.push("opera-developer"), 55 | // https://help.vivaldi.com/desktop/privacy/preventing-vivaldi-profiles-from-being-uploaded-to-git-repositories/ 56 | Self::Vivaldi => dir.push("vivaldi"), 57 | Self::VivaldiSnapshot => dir.push("vivaldi-snapshot"), 58 | Self::Edge => dir.push("microsoft-edge"), 59 | Self::EdgeBeta => dir.push("microsoft-edge-beta"), 60 | Self::EdgeDev => dir.push("microsoft-edge-dev"), 61 | Self::EdgeCanary => dir.push("microsoft-edge-unstable"), 62 | } 63 | Some(dir) 64 | } 65 | 66 | #[cfg(target_os = "windows")] 67 | pub fn get_profile_root(self) -> Option { 68 | let mut dir = app_dirs2::get_data_root(app_dirs2::AppDataType::UserData).ok()?; 69 | match self { 70 | Self::Chrome => { 71 | dir.push("Google"); 72 | dir.push("Chrome"); 73 | } 74 | Self::ChromeBeta => { 75 | dir.push("Google"); 76 | dir.push("Chrome Beta"); 77 | } 78 | Self::ChromeCanary => { 79 | dir.push("Google"); 80 | dir.push("Chrome SxS"); 81 | } 82 | Self::Chromium => dir.push("Chromium"), 83 | Self::Opera => dir.push("Opera"), 84 | Self::OperaBeta => dir.push("Opera Beta"), 85 | Self::OperaDev => dir.push("Opera Developer"), 86 | Self::Vivaldi => dir.push("Vivaldi"), 87 | Self::VivaldiSnapshot => dir.push("Vivaldi Snapshot"), 88 | Self::Edge => { 89 | dir.push("Microsoft"); 90 | dir.push("Edge"); 91 | } 92 | Self::EdgeBeta => { 93 | dir.push("Microsoft"); 94 | dir.push("Edge Beta"); 95 | } 96 | Self::EdgeDev => { 97 | dir.push("Microsoft"); 98 | dir.push("Edge Dev"); 99 | } 100 | Self::EdgeCanary => { 101 | dir.push("Microsoft"); 102 | dir.push("Edge SxS"); 103 | } 104 | } 105 | dir.push("User Data"); 106 | Some(dir) 107 | } 108 | 109 | #[cfg(target_os = "macos")] 110 | pub fn get_profile_root(self) -> Option { 111 | let mut dir = app_dirs2::get_data_root(app_dirs2::AppDataType::UserData).ok()?; 112 | match self { 113 | Self::Chrome => { 114 | dir.push("Google"); 115 | dir.push("Chrome"); 116 | } 117 | Self::ChromeBeta => { 118 | dir.push("Google"); 119 | dir.push("Chrome Beta"); 120 | } 121 | Self::ChromeCanary => { 122 | dir.push("Google"); 123 | dir.push("Chrome Canary"); 124 | } 125 | Self::Chromium => dir.push("Chromium"), 126 | Self::Opera => dir.push("Opera"), 127 | Self::OperaBeta => dir.push("Opera Beta"), 128 | Self::OperaDev => dir.push("Opera Developer"), 129 | Self::Vivaldi => dir.push("Vivaldi"), 130 | Self::VivaldiSnapshot => dir.push("Vivaldi Snapshot"), 131 | Self::Edge => dir.push("Microsoft Edge"), 132 | Self::EdgeBeta => dir.push("Microsoft Edge Beta"), 133 | Self::EdgeDev => dir.push("Microsoft Edge Dev"), 134 | Self::EdgeCanary => dir.push("Microsoft Edge Canary"), 135 | } 136 | Some(dir) 137 | } 138 | } 139 | 140 | fn get_ids() -> HashMap { 141 | const DATA: &str = include_str!("../list.txt"); 142 | let mut current_url = String::new(); 143 | let mut result = HashMap::new(); 144 | for line in DATA.split(['\r', '\n']) { 145 | if line.is_empty() { 146 | continue; 147 | } 148 | 149 | if let Some(url) = line.strip_prefix('#') { 150 | current_url = url.trim().to_string(); 151 | } else { 152 | result.insert(line.trim().to_string(), current_url.clone()); 153 | } 154 | } 155 | result 156 | } 157 | 158 | fn is_profile(path: &Path) -> bool { 159 | if path.is_dir() { 160 | let mut preferences = path.to_path_buf(); 161 | preferences.push("Preferences"); 162 | preferences.is_file() 163 | } else { 164 | false 165 | } 166 | } 167 | 168 | fn get_profiles() -> Vec { 169 | let mut result = Vec::new(); 170 | for root in enum_iterator::all().filter_map(Browser::get_profile_root) { 171 | let entries = match root.read_dir() { 172 | Ok(entries) => entries, 173 | Err(_) => continue, 174 | }; 175 | 176 | result.extend( 177 | entries 178 | .filter_map(|entry| entry.ok()) 179 | .map(|entry| entry.path()) 180 | .filter(|path| is_profile(path)), 181 | ); 182 | if is_profile(&root) { 183 | result.push(root); 184 | } 185 | } 186 | result 187 | } 188 | 189 | fn main() { 190 | let args = std::env::args_os().collect::>(); 191 | 192 | let profiles = if args.len() > 1 { 193 | let mut paths = Vec::new(); 194 | for arg in &args[1..] { 195 | let path = PathBuf::from(arg); 196 | if is_profile(&path) { 197 | paths.push(path); 198 | } else { 199 | eprintln!("{} does not seem to be a browser profile, is it the directory containing Preferences file?", arg.to_string_lossy()); 200 | } 201 | } 202 | 203 | if paths.is_empty() { 204 | eprintln!("No valid browser profiles given."); 205 | return; 206 | } 207 | paths 208 | } else { 209 | get_profiles() 210 | }; 211 | 212 | if profiles.is_empty() { 213 | eprintln!("No browser profiles found, try passing a directory on command line explicitly."); 214 | return; 215 | } 216 | 217 | let ids = get_ids(); 218 | for path in profiles { 219 | eprintln!("Checking profile {}", path.as_os_str().to_string_lossy()); 220 | 221 | let mut extensions = path.clone(); 222 | extensions.push("Extensions"); 223 | 224 | let mut seen_extension = false; 225 | let mut seen_malicious = false; 226 | if let Ok(entries) = extensions.read_dir() { 227 | for entry in entries.filter_map(|entry| entry.ok()) { 228 | seen_extension = true; 229 | let name = entry.file_name(); 230 | let id = name.to_string_lossy(); 231 | if let Some(url) = ids.get(id.as_ref()) { 232 | eprintln!("Extension {id} is potentially malicious, see {url}"); 233 | seen_malicious = true; 234 | } 235 | } 236 | } 237 | 238 | if !seen_extension { 239 | eprintln!("Unable to find any extensions for this browser."); 240 | } else if !seen_malicious { 241 | eprintln!("No malicious extensions found."); 242 | } 243 | 244 | eprintln!(); 245 | } 246 | } 247 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "app_dirs2" 7 | version = "2.5.5" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "a7e7b35733e3a8c1ccb90385088dd5b6eaa61325cb4d1ad56e683b5224ff352e" 10 | dependencies = [ 11 | "jni", 12 | "ndk-context", 13 | "winapi", 14 | "xdg", 15 | ] 16 | 17 | [[package]] 18 | name = "bytes" 19 | version = "1.4.0" 20 | source = "registry+https://github.com/rust-lang/crates.io-index" 21 | checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" 22 | 23 | [[package]] 24 | name = "cesu8" 25 | version = "1.1.0" 26 | source = "registry+https://github.com/rust-lang/crates.io-index" 27 | checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" 28 | 29 | [[package]] 30 | name = "cfg-if" 31 | version = "1.0.0" 32 | source = "registry+https://github.com/rust-lang/crates.io-index" 33 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 34 | 35 | [[package]] 36 | name = "check-extensions" 37 | version = "1.0.0" 38 | dependencies = [ 39 | "app_dirs2", 40 | "enum-iterator", 41 | ] 42 | 43 | [[package]] 44 | name = "combine" 45 | version = "4.6.6" 46 | source = "registry+https://github.com/rust-lang/crates.io-index" 47 | checksum = "35ed6e9d84f0b51a7f52daf1c7d71dd136fd7a3f41a8462b8cdb8c78d920fad4" 48 | dependencies = [ 49 | "bytes", 50 | "memchr", 51 | ] 52 | 53 | [[package]] 54 | name = "enum-iterator" 55 | version = "1.4.1" 56 | source = "registry+https://github.com/rust-lang/crates.io-index" 57 | checksum = "7add3873b5dd076766ee79c8e406ad1a472c385476b9e38849f8eec24f1be689" 58 | dependencies = [ 59 | "enum-iterator-derive", 60 | ] 61 | 62 | [[package]] 63 | name = "enum-iterator-derive" 64 | version = "1.2.1" 65 | source = "registry+https://github.com/rust-lang/crates.io-index" 66 | checksum = "eecf8589574ce9b895052fa12d69af7a233f99e6107f5cb8dd1044f2a17bfdcb" 67 | dependencies = [ 68 | "proc-macro2", 69 | "quote", 70 | "syn", 71 | ] 72 | 73 | [[package]] 74 | name = "home" 75 | version = "0.5.5" 76 | source = "registry+https://github.com/rust-lang/crates.io-index" 77 | checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb" 78 | dependencies = [ 79 | "windows-sys 0.48.0", 80 | ] 81 | 82 | [[package]] 83 | name = "jni" 84 | version = "0.21.1" 85 | source = "registry+https://github.com/rust-lang/crates.io-index" 86 | checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" 87 | dependencies = [ 88 | "cesu8", 89 | "cfg-if", 90 | "combine", 91 | "jni-sys", 92 | "log", 93 | "thiserror", 94 | "walkdir", 95 | "windows-sys 0.45.0", 96 | ] 97 | 98 | [[package]] 99 | name = "jni-sys" 100 | version = "0.3.0" 101 | source = "registry+https://github.com/rust-lang/crates.io-index" 102 | checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" 103 | 104 | [[package]] 105 | name = "log" 106 | version = "0.4.19" 107 | source = "registry+https://github.com/rust-lang/crates.io-index" 108 | checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" 109 | 110 | [[package]] 111 | name = "memchr" 112 | version = "2.5.0" 113 | source = "registry+https://github.com/rust-lang/crates.io-index" 114 | checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" 115 | 116 | [[package]] 117 | name = "ndk-context" 118 | version = "0.1.1" 119 | source = "registry+https://github.com/rust-lang/crates.io-index" 120 | checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" 121 | 122 | [[package]] 123 | name = "proc-macro2" 124 | version = "1.0.60" 125 | source = "registry+https://github.com/rust-lang/crates.io-index" 126 | checksum = "dec2b086b7a862cf4de201096214fa870344cf922b2b30c167badb3af3195406" 127 | dependencies = [ 128 | "unicode-ident", 129 | ] 130 | 131 | [[package]] 132 | name = "quote" 133 | version = "1.0.28" 134 | source = "registry+https://github.com/rust-lang/crates.io-index" 135 | checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488" 136 | dependencies = [ 137 | "proc-macro2", 138 | ] 139 | 140 | [[package]] 141 | name = "same-file" 142 | version = "1.0.6" 143 | source = "registry+https://github.com/rust-lang/crates.io-index" 144 | checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" 145 | dependencies = [ 146 | "winapi-util", 147 | ] 148 | 149 | [[package]] 150 | name = "syn" 151 | version = "2.0.18" 152 | source = "registry+https://github.com/rust-lang/crates.io-index" 153 | checksum = "32d41677bcbe24c20c52e7c70b0d8db04134c5d1066bf98662e2871ad200ea3e" 154 | dependencies = [ 155 | "proc-macro2", 156 | "quote", 157 | "unicode-ident", 158 | ] 159 | 160 | [[package]] 161 | name = "thiserror" 162 | version = "1.0.40" 163 | source = "registry+https://github.com/rust-lang/crates.io-index" 164 | checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" 165 | dependencies = [ 166 | "thiserror-impl", 167 | ] 168 | 169 | [[package]] 170 | name = "thiserror-impl" 171 | version = "1.0.40" 172 | source = "registry+https://github.com/rust-lang/crates.io-index" 173 | checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" 174 | dependencies = [ 175 | "proc-macro2", 176 | "quote", 177 | "syn", 178 | ] 179 | 180 | [[package]] 181 | name = "unicode-ident" 182 | version = "1.0.9" 183 | source = "registry+https://github.com/rust-lang/crates.io-index" 184 | checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0" 185 | 186 | [[package]] 187 | name = "walkdir" 188 | version = "2.3.3" 189 | source = "registry+https://github.com/rust-lang/crates.io-index" 190 | checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698" 191 | dependencies = [ 192 | "same-file", 193 | "winapi-util", 194 | ] 195 | 196 | [[package]] 197 | name = "winapi" 198 | version = "0.3.9" 199 | source = "registry+https://github.com/rust-lang/crates.io-index" 200 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 201 | dependencies = [ 202 | "winapi-i686-pc-windows-gnu", 203 | "winapi-x86_64-pc-windows-gnu", 204 | ] 205 | 206 | [[package]] 207 | name = "winapi-i686-pc-windows-gnu" 208 | version = "0.4.0" 209 | source = "registry+https://github.com/rust-lang/crates.io-index" 210 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 211 | 212 | [[package]] 213 | name = "winapi-util" 214 | version = "0.1.5" 215 | source = "registry+https://github.com/rust-lang/crates.io-index" 216 | checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" 217 | dependencies = [ 218 | "winapi", 219 | ] 220 | 221 | [[package]] 222 | name = "winapi-x86_64-pc-windows-gnu" 223 | version = "0.4.0" 224 | source = "registry+https://github.com/rust-lang/crates.io-index" 225 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 226 | 227 | [[package]] 228 | name = "windows-sys" 229 | version = "0.45.0" 230 | source = "registry+https://github.com/rust-lang/crates.io-index" 231 | checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" 232 | dependencies = [ 233 | "windows-targets 0.42.2", 234 | ] 235 | 236 | [[package]] 237 | name = "windows-sys" 238 | version = "0.48.0" 239 | source = "registry+https://github.com/rust-lang/crates.io-index" 240 | checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" 241 | dependencies = [ 242 | "windows-targets 0.48.0", 243 | ] 244 | 245 | [[package]] 246 | name = "windows-targets" 247 | version = "0.42.2" 248 | source = "registry+https://github.com/rust-lang/crates.io-index" 249 | checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" 250 | dependencies = [ 251 | "windows_aarch64_gnullvm 0.42.2", 252 | "windows_aarch64_msvc 0.42.2", 253 | "windows_i686_gnu 0.42.2", 254 | "windows_i686_msvc 0.42.2", 255 | "windows_x86_64_gnu 0.42.2", 256 | "windows_x86_64_gnullvm 0.42.2", 257 | "windows_x86_64_msvc 0.42.2", 258 | ] 259 | 260 | [[package]] 261 | name = "windows-targets" 262 | version = "0.48.0" 263 | source = "registry+https://github.com/rust-lang/crates.io-index" 264 | checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" 265 | dependencies = [ 266 | "windows_aarch64_gnullvm 0.48.0", 267 | "windows_aarch64_msvc 0.48.0", 268 | "windows_i686_gnu 0.48.0", 269 | "windows_i686_msvc 0.48.0", 270 | "windows_x86_64_gnu 0.48.0", 271 | "windows_x86_64_gnullvm 0.48.0", 272 | "windows_x86_64_msvc 0.48.0", 273 | ] 274 | 275 | [[package]] 276 | name = "windows_aarch64_gnullvm" 277 | version = "0.42.2" 278 | source = "registry+https://github.com/rust-lang/crates.io-index" 279 | checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" 280 | 281 | [[package]] 282 | name = "windows_aarch64_gnullvm" 283 | version = "0.48.0" 284 | source = "registry+https://github.com/rust-lang/crates.io-index" 285 | checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" 286 | 287 | [[package]] 288 | name = "windows_aarch64_msvc" 289 | version = "0.42.2" 290 | source = "registry+https://github.com/rust-lang/crates.io-index" 291 | checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" 292 | 293 | [[package]] 294 | name = "windows_aarch64_msvc" 295 | version = "0.48.0" 296 | source = "registry+https://github.com/rust-lang/crates.io-index" 297 | checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" 298 | 299 | [[package]] 300 | name = "windows_i686_gnu" 301 | version = "0.42.2" 302 | source = "registry+https://github.com/rust-lang/crates.io-index" 303 | checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" 304 | 305 | [[package]] 306 | name = "windows_i686_gnu" 307 | version = "0.48.0" 308 | source = "registry+https://github.com/rust-lang/crates.io-index" 309 | checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" 310 | 311 | [[package]] 312 | name = "windows_i686_msvc" 313 | version = "0.42.2" 314 | source = "registry+https://github.com/rust-lang/crates.io-index" 315 | checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" 316 | 317 | [[package]] 318 | name = "windows_i686_msvc" 319 | version = "0.48.0" 320 | source = "registry+https://github.com/rust-lang/crates.io-index" 321 | checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" 322 | 323 | [[package]] 324 | name = "windows_x86_64_gnu" 325 | version = "0.42.2" 326 | source = "registry+https://github.com/rust-lang/crates.io-index" 327 | checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" 328 | 329 | [[package]] 330 | name = "windows_x86_64_gnu" 331 | version = "0.48.0" 332 | source = "registry+https://github.com/rust-lang/crates.io-index" 333 | checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" 334 | 335 | [[package]] 336 | name = "windows_x86_64_gnullvm" 337 | version = "0.42.2" 338 | source = "registry+https://github.com/rust-lang/crates.io-index" 339 | checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" 340 | 341 | [[package]] 342 | name = "windows_x86_64_gnullvm" 343 | version = "0.48.0" 344 | source = "registry+https://github.com/rust-lang/crates.io-index" 345 | checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" 346 | 347 | [[package]] 348 | name = "windows_x86_64_msvc" 349 | version = "0.42.2" 350 | source = "registry+https://github.com/rust-lang/crates.io-index" 351 | checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" 352 | 353 | [[package]] 354 | name = "windows_x86_64_msvc" 355 | version = "0.48.0" 356 | source = "registry+https://github.com/rust-lang/crates.io-index" 357 | checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" 358 | 359 | [[package]] 360 | name = "xdg" 361 | version = "2.5.0" 362 | source = "registry+https://github.com/rust-lang/crates.io-index" 363 | checksum = "688597db5a750e9cad4511cb94729a078e274308099a0382b5b8203bbc767fee" 364 | dependencies = [ 365 | "home", 366 | ] 367 | --------------------------------------------------------------------------------