Compare commits

..

No commits in common. "develop" and "unknown-purpose" have entirely different histories.

17 changed files with 82 additions and 189 deletions

127
README.md
View File

@ -1,70 +1,8 @@
<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> <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> 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.
**Features:**
- analysis of web traffic generated by the visited website;
- visualization of data transmitted to third parties by the visited site (user's browsing history and cookies);
- preparation of screenshots of development tools as evidence of data transmitted to third parties;
- 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
- OS: Linux x86_64
- Node.js: 16.x version
- npm: 7.x version or higher
### Build steps
1. Pull repository or download a zip package
2. Go to the root directory of the pulled repository
3. Run command: `npm install`
4. Run command: `npm run build`
5. Run command: `npm run create-package`
6. Go to the `web-ext-artifacts` directory
7. You will find a zip archive: `rentgen-x-x-x.zip` (`x-x-x` means add-on version)
### Run steps
1. Run Firefox and go to `about:debugging`
2. Click _This Firefox_ tab
3. Click _Load Temporary Add-on..._ button
4. Pick the zip archive from last step of build process.
## 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.
## Screenshots
<img src="./assets/screenshots/image-14.png" />
<img src="./assets/screenshots/image-15.png" />
<img src="./assets/screenshots/3a.png" />
<img src="./assets/screenshots/3b.png" />
<img src="./assets/screenshots/4a.png" />
<img src="./assets/screenshots/4b.png" />
<img src="./assets/screenshots/5a.png" />
<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. <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:** **Funkcje Rentgena:**
- analiza ruchu sieciowego generowanego przez stronę internetową; - analiza ruchu sieciowego generowanego przez stronę internetową;
@ -73,10 +11,6 @@ Each issue will be reviewed and moved to an internal issues list of our Gitea in
- pomoc w oszacowaniu potencjalnych obszarów roboczych względem zgodności z RODO; - 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. - 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ł ## Jak zbudować i uruchomić Rentgena ze źródeł
### Wymagania wstępne ### Wymagania wstępne
@ -104,7 +38,7 @@ Firefox: https://addons.mozilla.org/pl/firefox/addon/rentgen/
## Zgłaszanie błędów ## Zgłaszanie błędów
Jeżeli znajdziesz jakieś problem, napisz do nas maila: kontakt@internet-czas-dzialac.pl 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. Nie przyjmujemy zgłoszeń na platformie Microsoft Github.
@ -112,3 +46,60 @@ Każdy problem zostanie sprawdzony i przeniesiony na wewnętrzną listę problem
--- ---
## 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.
**Features:**
- analysis of web traffic generated by the visited website;
- visualization of data transmitted to third parties by the visited site (user's browsing history and cookies);
- preparation of screenshots of development tools as evidence of data transmitted to third parties;
- 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.
## How to build and run Rentgen on your own
### Pre-requirements
- OS: Linux x86_64
- Node.js: 16.x version
- npm: 7.x version or higher
### Build steps
1. Pull repository or download a zip package
2. Go to the root directory of the pulled repository
3. Run command: `npm install`
4. Run command: `npm run build`
5. Run command: `npm run create-package`
6. Go to the `web-ext-artifacts` directory
7. You will find a zip archive: `rentgen-x-x-x.zip` (`x-x-x` means add-on version)
### Run steps
1. Run Firefox and go to `about:debugging`
2. Click _This Firefox_ tab
3. Click _Load Temporary Add-on..._ button
4. Pick the zip archive from last step of build process.
## Issue tracker
Link to issue tracker on our Discourse instance: https://forum.internet-czas-dzialac.pl/c/rentgen-issue-tracker
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.
## Screenshots
<img src="./assets/screenshots/image-14.png" />
<img src="./assets/screenshots/image-15.png" />
<img src="./assets/screenshots/3a.png" />
<img src="./assets/screenshots/3b.png" />
<img src="./assets/screenshots/4a.png" />
<img src="./assets/screenshots/4b.png" />
<img src="./assets/screenshots/5a.png" />
<img src="./assets/screenshots/5b.png" />
<img src="./assets/screenshots/2022-07-14_21-04.png" />

View File

@ -9,49 +9,7 @@ export const Explainers: Record<ExplainerKey, (zaimek_index: 0 | 1 | 2 | 3) => J
<p> <p>
Sztucznie wygenerowane identyfikatory przechowywane w plikach Cookies stanowią dane Sztucznie wygenerowane identyfikatory przechowywane w plikach Cookies stanowią dane
osobowe. Wskazuje na to wprost Art. 4. pkt 1. RODO, wymieniając identyfikator osobowe. Wskazuje na to wprost Art. 4. pkt 1. RODO, wymieniając identyfikator
internetowy i numer identyfikacyjny jako przykłady danych osobowych. Losowe internetowy i numer identyfikacyjny jako przykłady danych osobowych.
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ą
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> </p>
</> </>
), ),

View File

@ -44,7 +44,7 @@ export default class NoInformationAtAllProblem extends Problem {
<li>Jaki jest cel takiego przetwarzania danych przez Państwa stronę?</li> <li>Jaki jest cel takiego przetwarzania danych przez Państwa stronę?</li>
<li> <li>
Jaka jest podstawa prawna takiego przetwarzania{' '} 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ę? {mode == 'report' ? 'użytkowników końcowych' : ''} przez Państwa stronę?
</li> </li>
</ul> </ul>

View File

@ -5,8 +5,7 @@ import { Problem } from './problem';
export class TransferOutsideEU extends Problem { export class TransferOutsideEU extends Problem {
getNecessaryExplainers(): ExplainerKey[] { getNecessaryExplainers(): ExplainerKey[] {
const has_cookies = this.getRelatedClusters().some((cluster) => cluster.hasCookies()); return [];
return has_cookies ? ['cookies_are_pii'] : [];
} }
qualifies(): boolean { qualifies(): boolean {

View File

@ -19,8 +19,7 @@ export class UnknownIdentity extends Problem {
{mode == 'email' ? ( {mode == 'email' ? (
<p> <p>
Na Państwa stronie nie {_('znalazłem')} sposobu na poznanie tożsamości Na Państwa stronie nie {_('znalazłem')} sposobu na poznanie tożsamości
administratora strony <strong>przed</strong> podjęciem wyboru dotyczącego administratora strony przed podjęciem wyboru dotyc
przetwarzania danych mnie dotyczących.
</p> </p>
) : ( ) : (
<p>Na stronie brakuje sposobu na poznanie tożsamości administratora strony.</p> <p>Na stronie brakuje sposobu na poznanie tożsamości administratora strony.</p>

View File

@ -21,11 +21,7 @@ const testCluster: (cluster: RequestCluster, answers: ParsedHostAnswers | undefi
export class UnknownLegalBasis extends Problem { export class UnknownLegalBasis extends Problem {
getNecessaryExplainers(): ExplainerKey[] { getNecessaryExplainers(): ExplainerKey[] {
const has_cookies = this.getRelatedClusters().some((cluster) => cluster.hasCookies()); return ['responsibility_for_third_parties'];
return [
'responsibility_for_third_parties',
...(has_cookies ? ['cookies_are_pii' as ExplainerKey] : []),
];
} }
qualifies(): boolean { qualifies(): boolean {
@ -74,7 +70,7 @@ export class UnknownLegalBasis extends Problem {
Na stronie nie znajdują się informacje o tym, jaka jest podstawa prawna Na stronie nie znajdują się informacje o tym, jaka jest podstawa prawna
takiego przetwarzania danych osobowych, jakimi jest część historii takiego przetwarzania danych osobowych, jakimi jest część historii
przeglądania. Zgodnie z treścią Artykułu 13. p. 1 lit. c) RODO, aby przeglądania. Zgodnie z treścią Artykułu 13. p. 1 lit. c) RODO, aby
przetwarzać dane osobowe, trzeba poinformować osobę, której dane dotyczą, o przetwarzać dane osobowe, trzeba poinformować osobę, któ©ej dane dotyczą, o
tym, jak ajest podstaw aprawna takiego przetwarzania danych. tym, jak ajest podstaw aprawna takiego przetwarzania danych.
</p> </p>
)} )}

View File

@ -6,13 +6,8 @@ import { Problem } from './problem';
export class UnknownPurposes extends Problem { export class UnknownPurposes extends Problem {
getNecessaryExplainers(): ExplainerKey[] { getNecessaryExplainers(): ExplainerKey[] {
const has_cookies = this.getAffectedClusters().some((cluster) => cluster.hasCookies());
if (has_cookies) {
return ['cookies_are_pii'];
} else {
return []; return [];
} }
}
isHostAffected(host: string) { isHostAffected(host: string) {
const answers = this.answers.hosts[host]; const answers = this.answers.hosts[host];

View File

@ -38,7 +38,7 @@ interface screenshotTask {
} }
function createTaskEndpoint(visited_url: string, domains: string[]) { function createTaskEndpoint(visited_url: string, domains: string[]) {
return `${SS_URL}/api/requests?url=${encodeURIComponent(visited_url)}${domains.reduce( return `${SS_URL}/api/requests?url=${visited_url}${domains.reduce(
(prev: string, curr: string) => prev + '&domains[]=' + curr, (prev: string, curr: string) => prev + '&domains[]=' + curr,
'' ''
)}`; )}`;

View File

@ -7,15 +7,6 @@
flex-flow: column; flex-flow: column;
border-bottom: none; border-bottom: none;
&__header {
display: flex;
align-items: center;
.icon.cookie-data {
margin-left: 0.25rem;
}
}
.domain-checkbox { .domain-checkbox {
margin-right: 0.5rem; margin-right: 0.5rem;
width: 0.875rem; width: 0.875rem;

View File

@ -2,10 +2,12 @@ import React from 'react';
import { getMemory } from '../../memory'; import { getMemory } from '../../memory';
import { StolenDataEntry } from '../../stolen-data-entry'; import { StolenDataEntry } from '../../stolen-data-entry';
import { useEmitter } from '../../util'; import { maskString, useEmitter } from '../../util';
import './stolen-data-cluster.scss'; import './stolen-data-cluster.scss';
const MAX_STRING_VALUE_LENGTH = 100;
function StolenDataValue({ entry }: { entry: StolenDataEntry; prefixKey?: string }) { function StolenDataValue({ entry }: { entry: StolenDataEntry; prefixKey?: string }) {
const [version] = useEmitter(entry); const [version] = useEmitter(entry);
let body = null; let body = null;
@ -41,16 +43,13 @@ function StolenDataRow({ entry }: { entry: StolenDataEntry }) {
<input <input
type="checkbox" type="checkbox"
checked={entry.isMarked} checked={entry.isMarked}
id={entry.id.toString()}
onChange={() => { onChange={() => {
entry.toggleMark(); entry.toggleMark();
getMemory().emit('change', entry.request.shorthost); getMemory().emit('change', entry.request.shorthost);
}} }}
/> />
</td> </td>
<th title={`Nazwa: ${entry.name}\nŹródło: ${entry.source}`}> <th title={`Nazwa: ${entry.name}\nŹródło: ${entry.source}`}>{entry.name}</th>
<label htmlFor={entry.id.toString()}>{entry.name}</label>
</th>
<td className="icons"> <td className="icons">
{entry.source === 'cookie' ? ( {entry.source === 'cookie' ? (
<span title="Dane przechowywane w Cookies"> <span title="Dane przechowywane w Cookies">
@ -121,7 +120,7 @@ export default function StolenDataCluster({
return ( return (
<div className="stolen-data-cluster-container"> <div className="stolen-data-cluster-container">
<header className="domains-container"> <header className="domains-container">
<div className="domains-container__header"> <div>
<input <input
type="checkbox" type="checkbox"
className="domain-checkbox" className="domain-checkbox"
@ -138,17 +137,7 @@ export default function StolenDataCluster({
/> />
<a className="domain" href={'https://' + cluster.id} target="_blank"> <a className="domain" href={'https://' + cluster.id} target="_blank">
{cluster.id} {cluster.id}
</a>{' '} </a>
{cluster.hasCookies() ? (
<img
src="/assets/icons/cookie.svg"
height={16}
width={16}
className="icon cookie-data"
/>
) : (
''
)}
</div> </div>
<div className="subdomains-container"> <div className="subdomains-container">
{fullHosts.map((host, index) => ( {fullHosts.map((host, index) => (

View File

@ -14,15 +14,6 @@ async function getCurrentTab() {
import './../../styles/global.scss'; import './../../styles/global.scss';
import './toolbar.scss'; import './toolbar.scss';
function isDomainHighlySuspicious(domain: string): boolean {
return (
domain.includes('facebook') ||
domain.includes('twitter') ||
domain.includes('linkedin') ||
false
);
}
const Toolbar = () => { const Toolbar = () => {
const [origin, setOrigin] = React.useState<string | null>(null); const [origin, setOrigin] = React.useState<string | null>(null);
const [eventCounts] = useEmitter(getMemory()); const [eventCounts] = useEmitter(getMemory());
@ -62,13 +53,6 @@ const Toolbar = () => {
if (!origin) return; if (!origin) return;
const exposedOriginDomains = Object.values(getMemory().getClustersForOrigin(origin)) const exposedOriginDomains = Object.values(getMemory().getClustersForOrigin(origin))
.filter((cluster) => cluster.exposesOrigin()) .filter((cluster) => cluster.exposesOrigin())
.sort((cluster1, cluster2) =>
isDomainHighlySuspicious(cluster1.id)
? -1
: isDomainHighlySuspicious(cluster2.id)
? 1
: 0
)
.map((cluster) => cluster.id); .map((cluster) => cluster.id);
setExposedOriginDomainCopy(''); setExposedOriginDomainCopy('');
@ -102,13 +86,6 @@ const Toolbar = () => {
if (!origin) return; if (!origin) return;
const cookieDomains = Object.values(getMemory().getClustersForOrigin(origin)) const cookieDomains = Object.values(getMemory().getClustersForOrigin(origin))
.filter((cluster) => cluster.hasCookies()) .filter((cluster) => cluster.hasCookies())
.sort((cluster1, cluster2) =>
isDomainHighlySuspicious(cluster1.id)
? -1
: isDomainHighlySuspicious(cluster2.id)
? 1
: 0
)
.map((cluster) => cluster.id); .map((cluster) => cluster.id);
setCookieDomainCopy(''); setCookieDomainCopy('');

View File

@ -305,10 +305,6 @@ export default class ExtendedRequest {
return this.stolenData.filter((data) => data.isMarked); return this.stolenData.filter((data) => data.isMarked);
} }
unmarkAllEntries() {
this.stolenData.forEach((entry) => entry.unmark());
}
getHost() { getHost() {
return new URL(this.url).host; return new URL(this.url).host;
} }

View File

@ -3,7 +3,7 @@
"manifest_version": 2, "manifest_version": 2,
"name": "Rentgen", "name": "Rentgen",
"short_name": "Rentgen", "short_name": "Rentgen",
"version": "0.1.10", "version": "0.1.8",
"author": "Kuba Orlik, Arkadiusz Wieczorek (Internet. Czas działać!)", "author": "Kuba Orlik, Arkadiusz Wieczorek (Internet. Czas działać!)",
"homepage_url": "https://git.internet-czas-dzialac.pl/icd/rentgen", "homepage_url": "https://git.internet-czas-dzialac.pl/icd/rentgen",
"background": { "background": {

4
package-lock.json generated
View File

@ -1,12 +1,12 @@
{ {
"name": "rentgen", "name": "rentgen",
"version": "0.1.10", "version": "0.1.7",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "rentgen", "name": "rentgen",
"version": "0.1.10", "version": "0.1.7",
"license": "GPL-3.0-or-later", "license": "GPL-3.0-or-later",
"dependencies": { "dependencies": {
"@iabtcf/core": "^1.3.1", "@iabtcf/core": "^1.3.1",

View File

@ -1,6 +1,6 @@
{ {
"name": "rentgen", "name": "rentgen",
"version": "0.1.10", "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.", "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.",
"main": "esbuild.config.js", "main": "esbuild.config.js",
"type": "module", "type": "module",

View File

@ -191,7 +191,9 @@ export class RequestCluster extends SaferEmitter {
undoMark() { undoMark() {
this.calculateRepresentativeStolenData(); this.calculateRepresentativeStolenData();
this.requests.forEach((request) => request.unmarkAllEntries()); this.representativeStolenData.forEach((entry) => {
entry.unmark();
});
} }
getDataTypeDescription(noun = 'Twojej') { getDataTypeDescription(noun = 'Twojej') {

View File

@ -78,7 +78,7 @@ export function useEmitter(
export function parseCookie(cookie: string): Record<string, string> { export function parseCookie(cookie: string): Record<string, string> {
return cookie return cookie
.split(';') .split(';')
.map((l) => [l.slice(0, l.indexOf('=')), l.slice(l.indexOf('=') + 1)]) .map((l) => l.split('='))
.reduce( .reduce(
(acc, [key, value]) => ({ (acc, [key, value]) => ({
...acc, ...acc,