Compare commits
	
		
			26 Commits
		
	
	
		
			unknown-pu
			...
			develop
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| cf94d45ee1 | |||
| f1b1b6e720 | |||
| e1d9b8c874 | |||
| 95bb5248ef | |||
| d167a2138c | |||
| a617d82716 | |||
| 546233e093 | |||
| ea70d26a38 | |||
| 1680026bc4 | |||
| d5a8172759 | |||
| 039698264a | |||
| 7cf1b95461 | |||
| 799f17eac8 | |||
| 5c96a7f4cb | |||
| 32107f0ebc | |||
| 3910b5c67e | |||
| b2487c0511 | |||
| 1106e86b41 | |||
| c16e8f3d7c | |||
| aae1a7e970 | |||
| 3a32456534 | |||
| 67544a4bff | |||
| e3f4f8858d | |||
| e3d6e6b83c | |||
| cc713004b0 | |||
| 65e1ab2ecc | 
							
								
								
									
										7
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										7
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -5,3 +5,10 @@ sidebar.js | ||||
| lib/* | ||||
| /yarn-error.log | ||||
| /rentgen.zip | ||||
| 
 | ||||
| # Generated PNG icons (build artifacts) | ||||
| /assets/icons/*.png | ||||
| /assets/icon-addon-*.png | ||||
| 
 | ||||
| # Exception: do not ignore the `browser-api` directory inside `lib` | ||||
| !/lib/browser-api/ | ||||
							
								
								
									
										107
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										107
									
								
								README.md
									
									
									
									
									
								
							| @ -1,53 +1,5 @@ | ||||
| <h1 style="display: flex; align-items: center;"><img src="./assets/icon-addon-2048.png" alt="Rentgen logo" style="margin-right: 1rem;" width="48"/> Rentgen</h1> | ||||
| 
 | ||||
| <strong>Rentgen</strong> to wtyczka dla przeglądarek opartych o Firefoxa, która automatycznie wizualizuje, jakie dane zostały ~~wykradzione~~ wysłane do podmiotów trzecich przez odwiedzane strony. Wtyczka obrazuje ilość skryptów śledzących na stronie internetowej i pomaga w sformułowaniu maila do administratora strony, który może być podstawą do skargi RODO w Urzędzie Ochrony Danych Osobowych. | ||||
| 
 | ||||
| 
 | ||||
| **Funkcje Rentgena:** | ||||
| 
 | ||||
| -   analiza ruchu sieciowego generowanego przez stronę internetową; | ||||
| -   wizualizacja danych przekazanych do podmiotów trzecich przez odwiedzaną stronę (historia przeglądania użytkownika oraz jego ciasteczka); | ||||
| -   przygotowywanie zrzutów ekranów narzędzi deweloperskich będących dowodem przekazanych danych do podmiotów trzecich; | ||||
| -   pomoc w oszacowaniu potencjalnych obszarów roboczych względem zgodności z RODO; | ||||
| -   generowanie raportu lub treści maila, którą można wysłać do administratora oraz Urzędu Ochrony Danych Osobowych. | ||||
| 
 | ||||
| ## Jak zbudować i uruchomić Rentgena ze źródeł | ||||
| 
 | ||||
| ### Wymagania wstępne | ||||
| 
 | ||||
| -   System operacyjny: Linux x86_64 | ||||
| -   Node.js: 16.x | ||||
| -   npm: 7.x lub wyższy | ||||
| 
 | ||||
| ### Proces budowy | ||||
| 
 | ||||
| 1. Pobierz repozytorium przez `git pull https://git.internet-czas-dzialac.pl/icd/rentgen.git` lub pobierz archwium zip | ||||
| 2. Przejdź do głównego katalogu pobranego repozytorium | ||||
| 3. Uruchom komendę: `npm install` | ||||
| 4. Uruchom komendę: `npm run build` | ||||
| 5. Uruchom komendę: `npm run create-package` | ||||
| 6. Przejdź do katalogu `web-ext-artifacts` | ||||
| 7. Znajdziesz tam archiwum zip: `rentgen-x-x-x.zip` (`x-x-x` oznaczają wersję wtyczki) | ||||
| 
 | ||||
| ### Kroki do uruchomienia | ||||
| 
 | ||||
| 1. Uruchom Firefoxa i przejdź do strony `about:debugging` | ||||
| 2. Kliknij zakładkę _This Firefox_ | ||||
| 3. Kliknij przycisk _Load Temporary Add-on..._ | ||||
| 4. Wybierz archiwum, które zbudowałeś w ostatnim kroku procesu budowy | ||||
| 
 | ||||
| ## Zgłaszanie błędów | ||||
| 
 | ||||
| Link do issue trackera na naszej instancji Discourse: https://forum.internet-czas-dzialac.pl/c/rentgen-issue-tracker | ||||
| 
 | ||||
| Nie przyjmujemy zgłoszeń na platformie Microsoft Github. | ||||
| 
 | ||||
| Każdy problem zostanie sprawdzony i przeniesiony na wewnętrzną listę problemów na naszej instancji Gitea: https://git.internet-czas-dzialac.pl/icd/rentgen/issues. Korzystamy z Gitea i najprawdopodobniej w przyszłości dzięki federalizacji Gitea będziemy w stanie wpuścić użytkowników do zgłaszania błędów bezpośrednio ze strony Gitea. | ||||
| 
 | ||||
| --- | ||||
| 
 | ||||
| ## English description 🇬🇧 | ||||
| 
 | ||||
| <strong>Rentgen</strong> is an add-on prepared for Firefox-based browsers. This extension will automatically visualize all the data that a given website ~~steals~~ sends to third parties. | ||||
| 
 | ||||
| Note: At the moment, we support Polish language because this extension generates mail content that is dedicated to Polish website owners. In further versions of this add-on, we will add other languages as well. | ||||
| @ -60,6 +12,10 @@ Note: At the moment, we support Polish language because this extension generates | ||||
| -   assisting in the evaluation of potential work areas for compliance with GDPR; | ||||
| -   generating a report or email content that can be sent to an administrator and Personal Data Protection Office in Poland. | ||||
| 
 | ||||
| ## Installation | ||||
| 
 | ||||
| Firefox: https://addons.mozilla.org/en-US/firefox/addon/rentgen/ | ||||
| 
 | ||||
| ## How to build and run Rentgen on your own | ||||
| 
 | ||||
| ### Pre-requirements | ||||
| @ -87,7 +43,9 @@ Note: At the moment, we support Polish language because this extension generates | ||||
| 
 | ||||
| ## Issue tracker | ||||
| 
 | ||||
| Link to issue tracker on our Discourse instance: https://forum.internet-czas-dzialac.pl/c/rentgen-issue-tracker | ||||
| If you find a problem, please send us an email: kontakt@internet-czas-dzialac.pl | ||||
| 
 | ||||
| We don't receive issues on Microsoft Github. | ||||
| 
 | ||||
| Each issue will be reviewed and moved to an internal issues list of our Gitea instance: https://git.internet-czas-dzialac.pl/icd/rentgen/issues. We use Gitea and most likely in the future with the federalization of Gitea, we will be able to let users in to report issues directly from the Gitea site. | ||||
| 
 | ||||
| @ -103,3 +61,54 @@ Each issue will be reviewed and moved to an internal issues list of our Gitea in | ||||
| <img src="./assets/screenshots/5b.png" /> | ||||
| <img src="./assets/screenshots/2022-07-14_21-04.png" /> | ||||
| 
 | ||||
| --- | ||||
| 
 | ||||
| <strong>Rentgen</strong> to wtyczka dla przeglądarek opartych o Firefoxa, która automatycznie wizualizuje, jakie dane zostały ~~wykradzione~~ wysłane do podmiotów trzecich przez odwiedzane strony. Wtyczka obrazuje ilość skryptów śledzących na stronie internetowej i pomaga w sformułowaniu maila do administratora strony, który może być podstawą do skargi RODO w Urzędzie Ochrony Danych Osobowych. | ||||
| 
 | ||||
| **Funkcje Rentgena:** | ||||
| 
 | ||||
| -   analiza ruchu sieciowego generowanego przez stronę internetową; | ||||
| -   wizualizacja danych przekazanych do podmiotów trzecich przez odwiedzaną stronę (historia przeglądania użytkownika oraz jego ciasteczka); | ||||
| -   przygotowywanie zrzutów ekranów narzędzi deweloperskich będących dowodem przekazanych danych do podmiotów trzecich; | ||||
| -   pomoc w oszacowaniu potencjalnych obszarów roboczych względem zgodności z RODO; | ||||
| -   generowanie raportu lub treści maila, którą można wysłać do administratora oraz Urzędu Ochrony Danych Osobowych. | ||||
| 
 | ||||
| ## Instalacja | ||||
| 
 | ||||
| Firefox: https://addons.mozilla.org/pl/firefox/addon/rentgen/ | ||||
| 
 | ||||
| ## Jak zbudować i uruchomić Rentgena ze źródeł | ||||
| 
 | ||||
| ### Wymagania wstępne | ||||
| 
 | ||||
| -   System operacyjny: Linux x86_64 | ||||
| -   Node.js: 16.x | ||||
| -   npm: 7.x lub wyższy | ||||
| 
 | ||||
| ### Proces budowy | ||||
| 
 | ||||
| 1. Pobierz repozytorium przez `git pull https://git.internet-czas-dzialac.pl/icd/rentgen.git` lub pobierz archwium zip | ||||
| 2. Przejdź do głównego katalogu pobranego repozytorium | ||||
| 3. Uruchom komendę: `npm install` | ||||
| 4. Uruchom komendę: `npm run build` | ||||
| 5. Uruchom komendę: `npm run create-package` | ||||
| 6. Przejdź do katalogu `web-ext-artifacts` | ||||
| 7. Znajdziesz tam archiwum zip: `rentgen-x-x-x.zip` (`x-x-x` oznaczają wersję wtyczki) | ||||
| 
 | ||||
| ### Kroki do uruchomienia | ||||
| 
 | ||||
| 1. Uruchom Firefoxa i przejdź do strony `about:debugging` | ||||
| 2. Kliknij zakładkę _This Firefox_ | ||||
| 3. Kliknij przycisk _Load Temporary Add-on..._ | ||||
| 4. Wybierz archiwum, które zbudowałeś w ostatnim kroku procesu budowy | ||||
| 
 | ||||
| ## Zgłaszanie błędów | ||||
| 
 | ||||
| Jeżeli znajdziesz jakieś problem, napisz do nas maila: kontakt@internet-czas-dzialac.pl | ||||
| 
 | ||||
| Nie przyjmujemy zgłoszeń na platformie Microsoft Github. | ||||
| 
 | ||||
| Każdy problem zostanie sprawdzony i przeniesiony na wewnętrzną listę problemów na naszej instancji Gitea: https://git.internet-czas-dzialac.pl/icd/rentgen/issues. Korzystamy z Gitea i najprawdopodobniej w przyszłości dzięki federalizacji Gitea będziemy w stanie wpuścić użytkowników do zgłaszania błędów bezpośrednio ze strony Gitea. | ||||
| 
 | ||||
| --- | ||||
| 
 | ||||
|  | ||||
| @ -9,7 +9,49 @@ export const Explainers: Record<ExplainerKey, (zaimek_index: 0 | 1 | 2 | 3) => J | ||||
|             <p> | ||||
|                 Sztucznie wygenerowane identyfikatory przechowywane w plikach Cookies stanowią dane | ||||
|                 osobowe. Wskazuje na to wprost Art. 4. pkt 1. RODO, wymieniając „identyfikator | ||||
|                 internetowy” i „numer identyfikacyjny” jako przykłady danych osobowych. | ||||
|                 internetowy” i „numer identyfikacyjny” jako przykłady danych osobowych. Losowe | ||||
|                 przypisane identyfikatory mogą nie zawierać imienia i nazwiska osoby, której | ||||
|                 dotyczą, ani nie prowadzić wprost do ich ustalenia, ale pozwalają odróżnić jedną, | ||||
|                 daną konkretną osobę, od innych. | ||||
|             </p> | ||||
|             <p> | ||||
|                 Por. komentarz z D. Lubasz [w:] Ochrona Danych Osobowych [red.] D. Lubasz, Warszawa | ||||
|                 2020 r., str. 81: | ||||
|             </p> | ||||
|             <p> | ||||
|                 <em> | ||||
|                     Zidentyfikowaną osobą fizyczną jest osoba, której tożsamość jest ustalona - | ||||
|                     bezpośrednio i natychmiast, czyli taka, którą bezpośrednio można wskazać, | ||||
|                     wyodrębnić lub wyróżnić z określonej zbiorowości.{' '} | ||||
|                     <strong>Nie musi to natomiast polegać na podaniu jej imienia nazwiska</strong>. | ||||
|                     Konstatacja ta jest zwłaszcza istotna w środowisku cyfrowym, w którym | ||||
|                     identyfikacja sprowadza się do oznaczenia danego użytkownika w celu wywierania | ||||
|                     na niego określonego wpływu. (...) Możliwą do zidentyfikowania jest osoba, | ||||
|                     której tożsamość dopiero administrator może ustalić -{' '} | ||||
|                     <strong>niezależnie od tego, czy to zrobi, czy nie</strong>. | ||||
|                 </em> | ||||
|             </p> | ||||
|             <p> | ||||
|                 Podobnie za{' '} | ||||
|                 <em> | ||||
|                     P. Litwiński [w:] Rozporządzenie UE w sprawie ochrony osób fizycznych w związku | ||||
|                     z przetwarzaniem danych osobowych i w sprawie swobodnego przepływu takich | ||||
|                     danych, Komentarz [red.] P. Litwiński, Warszawa 2018 r. | ||||
|                 </em> | ||||
|                 : | ||||
|             </p> | ||||
|             <p> | ||||
|                 <em> | ||||
|                     Jak zwrócono uwagę w nauce prawa, identyfikacja osoby powinna być rozumiana jako | ||||
|                     możliwość „fizycznego” wskazania tejże osoby, nie zaś jako ustalenie | ||||
|                     podstawowych danych tej osoby (...). Analogicznie,{' '} | ||||
|                     <em>identyfikacja osoby nie wymaga znajomości jej imienia lub nazwiska</em>, | ||||
|                     wymaga natomiast znajomości pewnych unikalnych cech tej osoby, które odróżniają | ||||
|                     ją od innych osób (...). W ten sam sposób należy więc rozumieć zwrot „można | ||||
|                     zidentyfikować” - nie tylko jako możliwość odniesienia konkretnej informacji do | ||||
|                     konkretnej osoby, lecz także jako możliwość wskazania tej osoby, rozumianego | ||||
|                     jako faktyczne wyodrębnienie jej spośród innych osób. | ||||
|                 </em> | ||||
|             </p> | ||||
|         </> | ||||
|     ), | ||||
|  | ||||
| @ -44,7 +44,7 @@ export default class NoInformationAtAllProblem extends Problem { | ||||
|                     <li>Jaki jest cel takiego przetwarzania danych przez Państwa stronę?</li> | ||||
|                     <li> | ||||
|                         Jaka jest podstawa prawna takiego przetwarzania{' '} | ||||
|                         {mode == 'email' ? _('moich') : ''} danych osobowych $ | ||||
|                         {mode == 'email' ? _('moich') : ''} danych osobowych | ||||
|                         {mode == 'report' ? 'użytkowników końcowych' : ''} przez Państwa stronę? | ||||
|                     </li> | ||||
|                 </ul> | ||||
|  | ||||
| @ -5,7 +5,8 @@ import { Problem } from './problem'; | ||||
| 
 | ||||
| export class TransferOutsideEU extends Problem { | ||||
|     getNecessaryExplainers(): ExplainerKey[] { | ||||
|         return []; | ||||
|         const has_cookies = this.getRelatedClusters().some((cluster) => cluster.hasCookies()); | ||||
|         return has_cookies ? ['cookies_are_pii'] : []; | ||||
|     } | ||||
| 
 | ||||
|     qualifies(): boolean { | ||||
|  | ||||
| @ -19,7 +19,8 @@ export class UnknownIdentity extends Problem { | ||||
|                 {mode == 'email' ? ( | ||||
|                     <p> | ||||
|                         Na Państwa stronie nie {_('znalazłem')} sposobu na poznanie tożsamości | ||||
|                         administratora strony przed podjęciem wyboru dotyc | ||||
|                         administratora strony <strong>przed</strong> podjęciem wyboru dotyczącego | ||||
|                         przetwarzania danych mnie dotyczących. | ||||
|                     </p> | ||||
|                 ) : ( | ||||
|                     <p>Na stronie brakuje sposobu na poznanie tożsamości administratora strony.</p> | ||||
|  | ||||
| @ -21,7 +21,11 @@ const testCluster: (cluster: RequestCluster, answers: ParsedHostAnswers | undefi | ||||
| 
 | ||||
| export class UnknownLegalBasis extends Problem { | ||||
|     getNecessaryExplainers(): ExplainerKey[] { | ||||
|         return ['responsibility_for_third_parties']; | ||||
|         const has_cookies = this.getRelatedClusters().some((cluster) => cluster.hasCookies()); | ||||
|         return [ | ||||
|             'responsibility_for_third_parties', | ||||
|             ...(has_cookies ? ['cookies_are_pii' as ExplainerKey] : []), | ||||
|         ]; | ||||
|     } | ||||
| 
 | ||||
|     qualifies(): boolean { | ||||
| @ -70,8 +74,8 @@ export class UnknownLegalBasis extends Problem { | ||||
|                         Na stronie nie znajdują się informacje o tym, jaka jest podstawa prawna | ||||
|                         takiego przetwarzania danych osobowych, jakimi jest część historii | ||||
|                         przeglądania. Zgodnie z treścią Artykułu 13. p. 1 lit. c) RODO, aby | ||||
|                         przetwarzać dane osobowe, trzeba poinformować osobę, któ©ej dane dotyczą, o | ||||
|                         tym, jak ajest podstaw aprawna takiego przetwarzania danych. | ||||
|                         przetwarzać dane osobowe, trzeba poinformować osobę, której dane dotyczą, o | ||||
|                         tym, jaka jest podstawa prawna takiego przetwarzania danych. | ||||
|                     </p> | ||||
|                 )} | ||||
|                 {mode == 'email' ? ( | ||||
|  | ||||
| @ -6,7 +6,12 @@ import { Problem } from './problem'; | ||||
| 
 | ||||
| export class UnknownPurposes extends Problem { | ||||
|     getNecessaryExplainers(): ExplainerKey[] { | ||||
|         return []; | ||||
|         const has_cookies = this.getAffectedClusters().some((cluster) => cluster.hasCookies()); | ||||
|         if (has_cookies) { | ||||
|             return ['cookies_are_pii']; | ||||
|         } else { | ||||
|             return []; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     isHostAffected(host: string) { | ||||
|  | ||||
| @ -34,7 +34,7 @@ export class UnlawfulCookieAccess extends Problem { | ||||
|         const _ = (key: string) => v(key, this.answers.zaimek); | ||||
|         return ( | ||||
|             <> | ||||
|                 <h2>Dostęp do cookies niezgodny z ustawą Prawo Telekomunikacyjne</h2> | ||||
|                 <h2>Dostęp do cookies niezgodny z ustawą Prawo Komunikacji Elektronicznej</h2> | ||||
|                 <p> | ||||
|                     Państwa strona {mode == 'email' ? 'dokonała' : 'dokonuje'} odczytu plików Cookie | ||||
|                     zapisanych na dysku twardym{' '} | ||||
| @ -67,9 +67,9 @@ export class UnlawfulCookieAccess extends Problem { | ||||
|                     })} | ||||
|                 </ul> | ||||
|                 <p> | ||||
|                     Zgodnie z treścią Art. 173.{' '} | ||||
|                     <a href="https://isap.sejm.gov.pl/isap.nsf/download.xsp/WDU20041711800/U/D20041800Lj.pdf"> | ||||
|                         ustawy Prawo Telekomunikacyjne | ||||
|                     Zgodnie z treścią Art. 399.{' '} | ||||
|                     <a href="https://isap.sejm.gov.pl/isap.nsf/DocDetails.xsp?id=WDU20240001221"> | ||||
|                         ustawy Prawo Komunikacji Elektronicznej | ||||
|                     </a> | ||||
|                     , strona może pozyskać dostęp do treści plików cookies pod warunkiem spełnienia | ||||
|                     jednego z następujących warunków: | ||||
| @ -78,9 +78,10 @@ export class UnlawfulCookieAccess extends Problem { | ||||
|                     <li> | ||||
|                         Użytkownik wyraził zgodę na takie przetwarzanie danych <em>po</em> tym, jak | ||||
|                         został poinformowany bezpośrednio o celu uzyskania dostępu do tej | ||||
|                         informacji. Zgodnie z Art. 174 ustawy Prawo Telekomunikacyjne, taka zgoda | ||||
|                         musi spełniać warunki zgody ustalone przez RODO, aby mogła być jako podstawa | ||||
|                         prawna uzyskania dostępu do cookies i podobnych technologii w przeglądarce; | ||||
|                         informacji. Zgodnie z Art. 400 ustawy Prawo Komunikacji Elektronicznej, taka | ||||
|                         zgoda musi spełniać warunki zgody ustalone przez RODO, aby mogła być użyta | ||||
|                         jako podstawa prawna uzyskania dostępu do cookies i podobnych technologii w | ||||
|                         przeglądarce; | ||||
|                     </li> | ||||
|                     <li> | ||||
|                         Dostęp do treści plików cookies jest konieczny do dostarczania usługi | ||||
| @ -110,7 +111,8 @@ export class UnlawfulCookieAccess extends Problem { | ||||
|                                         przetwarzanie danych osobowych. Aby zgoda była ważna w | ||||
|                                         świetle RODO, musi być dobrowolna. Brak możliwości | ||||
|                                         odmówienia zgody sprawia, że tak wyrażona „zgoda” nie jest | ||||
|                                         ważna w świetle RODO. Dlatego nie jest spełniony warunek 1.{' '} | ||||
|                                         ważna w świetle RODO. Dlatego nie jest spełniony warunek | ||||
|                                         1.{' '} | ||||
|                                     </> | ||||
|                                 ) : ( | ||||
|                                     <> | ||||
|  | ||||
| @ -38,7 +38,7 @@ interface screenshotTask { | ||||
| } | ||||
| 
 | ||||
| function createTaskEndpoint(visited_url: string, domains: string[]) { | ||||
|     return `${SS_URL}/api/requests?url=${visited_url}${domains.reduce( | ||||
|     return `${SS_URL}/api/requests?url=${encodeURIComponent(visited_url)}${domains.reduce( | ||||
|         (prev: string, curr: string) => prev + '&domains[]=' + curr, | ||||
|         '' | ||||
|     )}`;
 | ||||
|  | ||||
| @ -7,6 +7,15 @@ | ||||
|         flex-flow: column; | ||||
|         border-bottom: none; | ||||
| 
 | ||||
|         &__header { | ||||
|             display: flex; | ||||
|             align-items: center; | ||||
| 
 | ||||
|             .icon.cookie-data { | ||||
|                 margin-left: 0.25rem; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         .domain-checkbox { | ||||
|             margin-right: 0.5rem; | ||||
|             width: 0.875rem; | ||||
|  | ||||
| @ -2,12 +2,10 @@ import React from 'react'; | ||||
| import { getMemory } from '../../memory'; | ||||
| import { StolenDataEntry } from '../../stolen-data-entry'; | ||||
| 
 | ||||
| import { maskString, useEmitter } from '../../util'; | ||||
| import { useEmitter } from '../../util'; | ||||
| 
 | ||||
| import './stolen-data-cluster.scss'; | ||||
| 
 | ||||
| const MAX_STRING_VALUE_LENGTH = 100; | ||||
| 
 | ||||
| function StolenDataValue({ entry }: { entry: StolenDataEntry; prefixKey?: string }) { | ||||
|     const [version] = useEmitter(entry); | ||||
|     let body = null; | ||||
| @ -43,13 +41,16 @@ function StolenDataRow({ entry }: { entry: StolenDataEntry }) { | ||||
|                 <input | ||||
|                     type="checkbox" | ||||
|                     checked={entry.isMarked} | ||||
|                     id={entry.id.toString()} | ||||
|                     onChange={() => { | ||||
|                         entry.toggleMark(); | ||||
|                         getMemory().emit('change', entry.request.shorthost); | ||||
|                     }} | ||||
|                 /> | ||||
|             </td> | ||||
|             <th title={`Nazwa: ${entry.name}\nŹródło: ${entry.source}`}>{entry.name}</th> | ||||
|             <th title={`Nazwa: ${entry.name}\nŹródło: ${entry.source}`}> | ||||
|                 <label htmlFor={entry.id.toString()}>{entry.name}</label> | ||||
|             </th> | ||||
|             <td className="icons"> | ||||
|                 {entry.source === 'cookie' ? ( | ||||
|                     <span title="Dane przechowywane w Cookies"> | ||||
| @ -120,7 +121,7 @@ export default function StolenDataCluster({ | ||||
|     return ( | ||||
|         <div className="stolen-data-cluster-container"> | ||||
|             <header className="domains-container"> | ||||
|                 <div> | ||||
|                 <div className="domains-container__header"> | ||||
|                     <input | ||||
|                         type="checkbox" | ||||
|                         className="domain-checkbox" | ||||
| @ -137,7 +138,17 @@ export default function StolenDataCluster({ | ||||
|                     /> | ||||
|                     <a className="domain" href={'https://' + cluster.id} target="_blank"> | ||||
|                         {cluster.id} | ||||
|                     </a> | ||||
|                     </a>{' '} | ||||
|                     {cluster.hasCookies() ? ( | ||||
|                         <img | ||||
|                             src="/assets/icons/cookie.svg" | ||||
|                             height={16} | ||||
|                             width={16} | ||||
|                             className="icon cookie-data" | ||||
|                         /> | ||||
|                     ) : ( | ||||
|                         '' | ||||
|                     )} | ||||
|                 </div> | ||||
|                 <div className="subdomains-container"> | ||||
|                     {fullHosts.map((host, index) => ( | ||||
|  | ||||
| @ -14,6 +14,15 @@ async function getCurrentTab() { | ||||
| import './../../styles/global.scss'; | ||||
| import './toolbar.scss'; | ||||
| 
 | ||||
| function isDomainHighlySuspicious(domain: string): boolean { | ||||
|     return ( | ||||
|         domain.includes('facebook') || | ||||
|         domain.includes('twitter') || | ||||
|         domain.includes('linkedin') || | ||||
|         false | ||||
|     ); | ||||
| } | ||||
| 
 | ||||
| const Toolbar = () => { | ||||
|     const [origin, setOrigin] = React.useState<string | null>(null); | ||||
|     const [eventCounts] = useEmitter(getMemory()); | ||||
| @ -53,6 +62,13 @@ const Toolbar = () => { | ||||
|         if (!origin) return; | ||||
|         const exposedOriginDomains = Object.values(getMemory().getClustersForOrigin(origin)) | ||||
|             .filter((cluster) => cluster.exposesOrigin()) | ||||
|             .sort((cluster1, cluster2) => | ||||
|                 isDomainHighlySuspicious(cluster1.id) | ||||
|                     ? -1 | ||||
|                     : isDomainHighlySuspicious(cluster2.id) | ||||
|                       ? 1 | ||||
|                       : 0 | ||||
|             ) | ||||
|             .map((cluster) => cluster.id); | ||||
|         setExposedOriginDomainCopy(''); | ||||
| 
 | ||||
| @ -86,6 +102,13 @@ const Toolbar = () => { | ||||
|         if (!origin) return; | ||||
|         const cookieDomains = Object.values(getMemory().getClustersForOrigin(origin)) | ||||
|             .filter((cluster) => cluster.hasCookies()) | ||||
|             .sort((cluster1, cluster2) => | ||||
|                 isDomainHighlySuspicious(cluster1.id) | ||||
|                     ? -1 | ||||
|                     : isDomainHighlySuspicious(cluster2.id) | ||||
|                       ? 1 | ||||
|                       : 0 | ||||
|             ) | ||||
|             .map((cluster) => cluster.id); | ||||
|         setCookieDomainCopy(''); | ||||
| 
 | ||||
| @ -226,7 +249,7 @@ const Toolbar = () => { | ||||
|                                 <p> | ||||
|                                     Takie przetwarzanie danych może być niezgodne z prawem. Przejdź | ||||
|                                     do analizy aby pomóc ustalić, czy ta strona nie narusza RODO lub | ||||
|                                     ustawy Prawo Telekomunikacyjne. | ||||
|                                     ustawy Prawo Komunikacji Elektronicznej. | ||||
|                                 </p> | ||||
|                             </section> | ||||
|                             <section className="actions"> | ||||
|  | ||||
| @ -305,6 +305,10 @@ export default class ExtendedRequest { | ||||
|         return this.stolenData.filter((data) => data.isMarked); | ||||
|     } | ||||
| 
 | ||||
|     unmarkAllEntries() { | ||||
|         this.stolenData.forEach((entry) => entry.unmark()); | ||||
|     } | ||||
| 
 | ||||
|     getHost() { | ||||
|         return new URL(this.url).host; | ||||
|     } | ||||
|  | ||||
							
								
								
									
										54
									
								
								lib/browser-api/chrome.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								lib/browser-api/chrome.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,54 @@ | ||||
| /** | ||||
|  * Chrome Browser API Implementation | ||||
|  *  | ||||
|  * Mapuje Chrome chrome.* API na nasze ujednolicone BrowserAPI | ||||
|  */ | ||||
| 
 | ||||
| import type { BrowserAPI } from './types'; | ||||
| 
 | ||||
| // Chrome używa globalnego obiektu `chrome`
 | ||||
| declare const chrome: any; | ||||
| 
 | ||||
| export const chromeAPI: BrowserAPI = { | ||||
|     // Tabs API - chrome.tabs.* → tabs.*
 | ||||
|     tabs: { | ||||
|         query: chrome.tabs.query, | ||||
|         onUpdated: { | ||||
|             addListener: chrome.tabs.onUpdated.addListener, | ||||
|             removeListener: chrome.tabs.onUpdated.removeListener, | ||||
|         }, | ||||
|     }, | ||||
| 
 | ||||
|     // Badge API - Chrome używa action (nie browserAction)
 | ||||
|     badge: { | ||||
|         setBadgeText: chrome.action.setBadgeText, | ||||
|         setTitle: chrome.action.setTitle, | ||||
|         setBadgeBackgroundColor: chrome.action.setBadgeBackgroundColor, | ||||
|     }, | ||||
| 
 | ||||
|     // WebRequest API - chrome.webRequest.* → webRequest.*
 | ||||
|     webRequest: { | ||||
|         onBeforeRequest: { | ||||
|             addListener: chrome.webRequest.onBeforeRequest.addListener, | ||||
|         }, | ||||
|         onBeforeSendHeaders: { | ||||
|             addListener: chrome.webRequest.onBeforeSendHeaders.addListener, | ||||
|         }, | ||||
|     }, | ||||
| 
 | ||||
|     // Cookies API - chrome.cookies.* → cookies.*
 | ||||
|     cookies: { | ||||
|         getAll: chrome.cookies.getAll, | ||||
|         remove: chrome.cookies.remove, | ||||
|     }, | ||||
| 
 | ||||
|     // Extension API - chrome.extension.* → extension.*
 | ||||
|     extension: { | ||||
|         getBackgroundPage: chrome.extension.getBackgroundPage, | ||||
|     }, | ||||
| 
 | ||||
|     // Windows API - chrome.windows.* → windows.*  
 | ||||
|     windows: { | ||||
|         WINDOW_ID_CURRENT: chrome.windows.WINDOW_ID_CURRENT, | ||||
|     }, | ||||
| }; | ||||
							
								
								
									
										54
									
								
								lib/browser-api/firefox.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								lib/browser-api/firefox.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,54 @@ | ||||
| /** | ||||
|  * Firefox Browser API Implementation | ||||
|  *  | ||||
|  * Mapuje Firefox browser.* API na nasze ujednolicone BrowserAPI | ||||
|  */ | ||||
| 
 | ||||
| import type { BrowserAPI } from './types'; | ||||
| 
 | ||||
| // Firefox używa globalnego obiektu `browser`
 | ||||
| declare const browser: any; | ||||
| 
 | ||||
| export const firefoxAPI: BrowserAPI = { | ||||
|     // Tabs API - direct mapping
 | ||||
|     tabs: { | ||||
|         query: browser.tabs.query, | ||||
|         onUpdated: { | ||||
|             addListener: browser.tabs.onUpdated.addListener, | ||||
|             removeListener: browser.tabs.onUpdated.removeListener, | ||||
|         }, | ||||
|     }, | ||||
| 
 | ||||
|     // Badge API - Firefox używa browserAction
 | ||||
|     badge: { | ||||
|         setBadgeText: browser.browserAction.setBadgeText, | ||||
|         setTitle: browser.browserAction.setTitle, | ||||
|         setBadgeBackgroundColor: browser.browserAction.setBadgeBackgroundColor, | ||||
|     }, | ||||
| 
 | ||||
|     // WebRequest API - direct mapping
 | ||||
|     webRequest: { | ||||
|         onBeforeRequest: { | ||||
|             addListener: browser.webRequest.onBeforeRequest.addListener, | ||||
|         }, | ||||
|         onBeforeSendHeaders: { | ||||
|             addListener: browser.webRequest.onBeforeSendHeaders.addListener, | ||||
|         }, | ||||
|     }, | ||||
| 
 | ||||
|     // Cookies API - direct mapping
 | ||||
|     cookies: { | ||||
|         getAll: browser.cookies.getAll, | ||||
|         remove: browser.cookies.remove, | ||||
|     }, | ||||
| 
 | ||||
|     // Extension API - direct mapping
 | ||||
|     extension: { | ||||
|         getBackgroundPage: browser.extension.getBackgroundPage, | ||||
|     }, | ||||
| 
 | ||||
|     // Windows API - direct mapping
 | ||||
|     windows: { | ||||
|         WINDOW_ID_CURRENT: browser.windows.WINDOW_ID_CURRENT, | ||||
|     }, | ||||
| }; | ||||
							
								
								
									
										27
									
								
								lib/browser-api/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								lib/browser-api/index.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,27 @@ | ||||
| /** | ||||
|  * Browser API Abstraction - Main Export | ||||
|  *  | ||||
|  * Eksportuje właściwą implementację na podstawie TARGET build variable | ||||
|  */ | ||||
| 
 | ||||
| import type { BrowserAPI } from './types'; | ||||
| 
 | ||||
| // Build-time selection of browser API implementation
 | ||||
| let browserApi: BrowserAPI; | ||||
| 
 | ||||
| // TARGET jest ustawiane przez esbuild.config.js na podstawie npm script
 | ||||
| if (process.env.TARGET === 'chrome') { | ||||
|     // Chrome build - używamy chrome adapter
 | ||||
|     const { chromeAPI } = require('./chrome'); | ||||
|     browserApi = chromeAPI; | ||||
| } else { | ||||
|     // Firefox build (default) - używamy firefox adapter  
 | ||||
|     const { firefoxAPI } = require('./firefox'); | ||||
|     browserApi = firefoxAPI; | ||||
| } | ||||
| 
 | ||||
| // Eksportuj jako default export
 | ||||
| export default browserApi; | ||||
| 
 | ||||
| // Re-export typów dla wygody
 | ||||
| export * from './types'; | ||||
							
								
								
									
										124
									
								
								lib/browser-api/types.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										124
									
								
								lib/browser-api/types.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,124 @@ | ||||
| /** | ||||
|  * Browser API Abstraction - Typy na podstawie faktycznego użycia w kodzie | ||||
|  *  | ||||
|  * Przeanalizowane pliki: | ||||
|  * - util.ts: tabs.query, Tab.id | ||||
|  * - tab-dropdown.tsx: tabs.query, Tab.id, Tab.title   | ||||
|  * - toolbar.tsx: tabs.query, tabs.onUpdated, Tab.url, windows.WINDOW_ID_CURRENT | ||||
|  * - memory.ts: browserAction.*, webRequest.*, cookies.*, extension.* | ||||
|  */ | ||||
| 
 | ||||
| // === Tab API (util.ts, tab-dropdown.tsx, toolbar.tsx) ===
 | ||||
| export interface Tab { | ||||
|     id?: number;      // util.ts: tab.id, tab-dropdown.tsx: tab.id
 | ||||
|     title?: string;   // tab-dropdown.tsx: tab.title
 | ||||
|     url?: string;     // toolbar.tsx: tab.url
 | ||||
| } | ||||
| 
 | ||||
| export interface TabQuery { | ||||
|     currentWindow?: boolean; // util.ts, tab-dropdown.tsx
 | ||||
|     active?: boolean;        // toolbar.tsx
 | ||||
|     windowId?: number;       // toolbar.tsx
 | ||||
| } | ||||
| 
 | ||||
| // === Badge/BrowserAction API (memory.ts) ===
 | ||||
| export interface BadgeTextDetails { | ||||
|     text: string;    // memory.ts: setBadgeText
 | ||||
|     tabId?: number;  // memory.ts: setBadgeText (optional)
 | ||||
| } | ||||
| 
 | ||||
| export interface BadgeTitleDetails { | ||||
|     title: string;   // memory.ts: setTitle
 | ||||
|     tabId?: number;  // memory.ts: setTitle (optional)
 | ||||
| } | ||||
| 
 | ||||
| export interface BadgeColorDetails { | ||||
|     color: string;   // memory.ts: setBadgeBackgroundColor
 | ||||
| } | ||||
| 
 | ||||
| // === WebRequest API (memory.ts) ===
 | ||||
| export interface RequestDetails { | ||||
|     requestId: string;                    // memory.ts: request.requestId
 | ||||
|     requestHeaders?: RequestHeader[];     // memory.ts: request.requestHeaders
 | ||||
|     // Note: ExtendedRequest konstruktor używa więcej pól, 
 | ||||
|     // ale tu skupiamy się na tym co bezpośrednio używa browser API
 | ||||
| } | ||||
| 
 | ||||
| export interface RequestHeader { | ||||
|     name: string; | ||||
|     value?: string; | ||||
| } | ||||
| 
 | ||||
| export interface RequestFilter { | ||||
|     urls: string[];  // memory.ts: { urls: ['<all_urls>'] }
 | ||||
| } | ||||
| 
 | ||||
| export type RequestListener = (details: RequestDetails) => void; | ||||
| 
 | ||||
| // === Cookies API (memory.ts) ===
 | ||||
| export interface Cookie { | ||||
|     name: string;    // memory.ts: cookie.name
 | ||||
|     domain: string;  // memory.ts: cookie.domain
 | ||||
| } | ||||
| 
 | ||||
| export interface CookieQuery { | ||||
|     domain?: string; // memory.ts: { domain: shorthost }
 | ||||
| } | ||||
| 
 | ||||
| export interface CookieRemove { | ||||
|     name: string;    // memory.ts: { name: cookie.name, url: ... }
 | ||||
|     url: string;     // memory.ts: { url: `https://${cookie.domain}` }
 | ||||
| } | ||||
| 
 | ||||
| // === Main Browser API Interface ===
 | ||||
| export interface BrowserAPI { | ||||
|     // Tabs API
 | ||||
|     tabs: { | ||||
|         query(queryInfo: TabQuery): Promise<Tab[]>; | ||||
|         onUpdated: { | ||||
|             addListener(listener: (tabId: number, changeInfo: any, tab: Tab) => void): void; | ||||
|             removeListener(listener: (tabId: number, changeInfo: any, tab: Tab) => void): void; | ||||
|         }; | ||||
|     }; | ||||
| 
 | ||||
|     // Badge API (Firefox: browserAction, Chrome: action)
 | ||||
|     badge: { | ||||
|         setBadgeText(details: BadgeTextDetails): void; | ||||
|         setTitle(details: BadgeTitleDetails): void; | ||||
|         setBadgeBackgroundColor(details: BadgeColorDetails): void; | ||||
|     }; | ||||
| 
 | ||||
|     // WebRequest API
 | ||||
|     webRequest: { | ||||
|         onBeforeRequest: { | ||||
|             addListener( | ||||
|                 listener: RequestListener, | ||||
|                 filter: RequestFilter, | ||||
|                 extraInfoSpec?: string[] | ||||
|             ): void; | ||||
|         }; | ||||
|         onBeforeSendHeaders: { | ||||
|             addListener( | ||||
|                 listener: RequestListener, | ||||
|                 filter: RequestFilter, | ||||
|                 extraInfoSpec?: string[] | ||||
|             ): void; | ||||
|         }; | ||||
|     }; | ||||
| 
 | ||||
|     // Cookies API
 | ||||
|     cookies: { | ||||
|         getAll(details: CookieQuery): Promise<Cookie[]>; | ||||
|         remove(details: CookieRemove): Promise<Cookie | null>; | ||||
|     }; | ||||
| 
 | ||||
|     // Extension API
 | ||||
|     extension: { | ||||
|         getBackgroundPage(): Window | null; | ||||
|     }; | ||||
| 
 | ||||
|     // Windows API
 | ||||
|     windows: { | ||||
|         WINDOW_ID_CURRENT: number; | ||||
|     }; | ||||
| } | ||||
| @ -3,8 +3,8 @@ | ||||
|     "manifest_version": 2, | ||||
|     "name": "Rentgen", | ||||
|     "short_name": "Rentgen", | ||||
|     "version": "0.1.8", | ||||
|     "author": "Kuba Orlik, Arkadiusz Wieczorek (Internet. Czas działać!)", | ||||
|     "version": "0.2.1", | ||||
|     "author": "Kuba Orlik, Arkadiusz Wieczorek (Internet. Time to act! Foundation)", | ||||
|     "homepage_url": "https://git.internet-czas-dzialac.pl/icd/rentgen", | ||||
|     "background": { | ||||
|         "scripts": ["lib/background.js"] | ||||
|  | ||||
							
								
								
									
										985
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										985
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										13
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								package.json
									
									
									
									
									
								
							| @ -1,15 +1,23 @@ | ||||
| { | ||||
|     "name": "rentgen", | ||||
|     "version": "0.1.8", | ||||
|     "description": "Rentgen is an add-on prepared for Firefox-based browsers. This extension will automatically visualize all the data that a given website sends to third parties.", | ||||
|     "version": "0.2.1", | ||||
|     "description": "Rentgen is an add-on prepared for both Firefox-based and Chromium-based browsers. This extension will automatically visualize all the data that a given website sends to third parties.", | ||||
|     "main": "esbuild.config.js", | ||||
|     "type": "module", | ||||
|     "scripts": { | ||||
|         "build": "node esbuild.config.js", | ||||
|         "build:firefox": "TARGET=firefox node esbuild.config.js", | ||||
|         "build:chrome": "TARGET=chrome node esbuild.config.js", | ||||
|         "watch": "node esbuild.config.js --watch", | ||||
|         "watch:firefox": "TARGET=firefox node esbuild.config.js --watch", | ||||
|         "watch:chrome": "TARGET=chrome node esbuild.config.js --watch", | ||||
|         "ext-test": "web-ext run", | ||||
|         "build-addon": "npm i && npm run build && npm run create-package", | ||||
|         "build-addon:firefox": "npm i && npm run build:firefox && npm run create-package:firefox", | ||||
|         "build-addon:chrome": "npm i && npm run build:chrome && npm run create-package:chrome", | ||||
|         "create-package": "web-ext build --ignore-files '!**/node_modules' '!**/node_modules/**/react-dom' '!**/node_modules/**/react-dom/umd' '!**/node_modules/**/*/react-dom.production.min.js' '!**/node_modules/**/react' '!**/node_modules/**/react/umd' '!**/node_modules/**/*/react.production.min.js' '!**/node_modules/**/survey-react'  '!**/node_modules/**/survey-react/*.min.js' '!**/node_modules/**/survey-react/*.min.css' --overwrite-dest", | ||||
|         "create-package:firefox": "web-ext build --overwrite-dest --artifacts-dir ../web-ext-artifacts", | ||||
|         "create-package:chrome": "cd dist-chrome && 7z a -tzip ../web-ext-artifacts/rentgen-chrome-0.1.10.zip * && cd ..", | ||||
|         "typecheck": "tsc --noEmit", | ||||
|         "lint": "web-ext lint" | ||||
|     }, | ||||
| @ -43,6 +51,7 @@ | ||||
|         "tracking" | ||||
|     ], | ||||
|     "devDependencies": { | ||||
|         "@types/chrome": "^0.1.3", | ||||
|         "@types/events": "^3.0.0", | ||||
|         "@types/react-dom": "^17.0.9", | ||||
|         "addons-linter": "^4.7.0", | ||||
|  | ||||
| @ -191,9 +191,7 @@ export class RequestCluster extends SaferEmitter { | ||||
| 
 | ||||
|     undoMark() { | ||||
|         this.calculateRepresentativeStolenData(); | ||||
|         this.representativeStolenData.forEach((entry) => { | ||||
|             entry.unmark(); | ||||
|         }); | ||||
|         this.requests.forEach((request) => request.unmarkAllEntries()); | ||||
|     } | ||||
| 
 | ||||
|     getDataTypeDescription(noun = 'Twojej') { | ||||
|  | ||||
							
								
								
									
										2
									
								
								util.ts
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								util.ts
									
									
									
									
									
								
							| @ -78,7 +78,7 @@ export function useEmitter( | ||||
| export function parseCookie(cookie: string): Record<string, string> { | ||||
|     return cookie | ||||
|         .split(';') | ||||
|         .map((l) => l.split('=')) | ||||
|         .map((l) => [l.slice(0, l.indexOf('=')), l.slice(l.indexOf('=') + 1)]) | ||||
|         .reduce( | ||||
|             (acc, [key, value]) => ({ | ||||
|                 ...acc, | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user