Working filtered HAR export

This commit is contained in:
Kuba Orlik 2021-11-08 20:14:28 +01:00
parent d750c6b22b
commit 59de744c2d
6 changed files with 265 additions and 152 deletions

View File

@ -1,6 +1,33 @@
import { StolenDataEntry } from "./stolen-data-entry"; import { StolenDataEntry } from "./stolen-data-entry";
import { getshorthost, parseCookie, Request } from "./util"; import { getshorthost, parseCookie, Request } from "./util";
export type HAREntry = {
pageref: string;
startedDateTime: string;
request: {
bodySize: number;
cookies: {}[];
headers: {}[];
headersSize: number;
httpVersion: string;
method: string;
postData: {
mimeType: string;
params: { name: string; value: string }[];
text: string;
};
queryString: { name: string; value: string }[];
url: string;
};
response: {}; // not relevant
cache: {};
timings: {};
time: number;
_securityState: string;
serverIPAddress: string;
connection: string;
};
const whitelisted_cookies = [ const whitelisted_cookies = [
/^Accept.*$/, /^Accept.*$/,
/^Host$/, /^Host$/,
@ -163,4 +190,10 @@ export default class ExtendedRequest {
getHost() { getHost() {
return new URL(this.url).host; return new URL(this.url).host;
} }
matchesHAREntry(har: HAREntry): boolean {
const rq = this.data;
const hrq = har.request;
return rq.url == hrq.url;
}
} }

View File

@ -0,0 +1,48 @@
import React from "react";
import { RequestCluster } from "../request-cluster";
import { Classifications, Sources } from "../stolen-data-entry";
const emailClassifications: Record<keyof typeof Classifications, string> = {
id: "sztucznie nadane mi ID",
history: "część mojej historii przeglądania",
};
const emailSources: Record<Sources, string> = {
header: "w nagłówku HTTP",
cookie: "z pliku Cookie",
pathname: "jako części adresu URL",
queryparams: "jako część adresu URL (query-params)",
};
export default function DomainSummary({
cluster,
}: {
cluster: RequestCluster;
}) {
return (
<li>
Właściciel domeny <strong>{cluster.id}</strong> otrzymał:{" "}
<ul>
{cluster
.getMarkedEntries()
.sort((entryA, entryB) => (entryA.value > entryB.value ? -1 : 1))
.reduce((acc, entry, index, arr) => {
if (index === 0) {
return [entry];
}
if (entry.value != arr[index - 1].value) {
acc.push(entry);
}
return acc;
}, [])
.map((entry) => (
<li>
{emailClassifications[entry.classification]}{" "}
{emailSources[entry.source]}
&nbsp;(<code>{entry.name.trim()}</code>)
</li>
))}
</ul>
</li>
);
}

View File

@ -0,0 +1,121 @@
import React, { useState } from "react";
import { RequestCluster } from "../request-cluster";
import { StolenDataEntry } from "../stolen-data-entry";
import { getDate } from "../util";
import DomainSummary from "./domain-summary";
type PopupState = "not_clicked" | "clicked_but_invalid";
export default function EmailTemplate({
marked_entries,
clusters,
}: {
marked_entries: StolenDataEntry[];
clusters: Record<string, RequestCluster>;
}): JSX.Element {
const [popupState, setPopupState] = useState<PopupState>("not_clicked");
return (
<div>
<label htmlFor="popupState">Status okienka o rodo:</label>
<select
id="popupState"
value={popupState}
onChange={(e) => setPopupState(e.target.value as PopupState)}
>
<option value="not_clicked">Nic nie kliknięte</option>
<option value="clicked_but_invalid">Kliknięte, ale nieważne</option>
</select>
<p>
Dzień dobry, w dniu {getDate()} odwiedziłem stronę{" "}
{marked_entries[0].request.originalURL}. Strona ta wysłała moje dane
osobowe do podmiotów trzecich - bez mojej zgody.{" "}
</p>
<ul>
{Object.values(clusters)
.filter((cluster) => cluster.hasMarks())
.map((cluster) => (
<DomainSummary cluster={cluster} />
))}
</ul>
{popupState === "not_clicked" ? (
<p>
Dane te zostały wysłane przez Państwa stronę zanim zdążyłem w ogóle
przeczytać treść wyskakującego okienka ze zgodami.
</p>
) : null}
<p>
Nie widzę zatem przesłanki legalizującej takie przetwarzanie moich
danych osobowych (na pewno nie jest to przetwarzanie konieczne do
wyświetlenia strony z technicznego punktu widzenia). Jeżeli takie
przesłanki legalizujące jednak występują, proszę o ich wskazanie,
<strong> dla każdego z celów i podmiotów z osobna</strong>.
</p>
<p>
Jeżeli wskazaną przez Państwa przesłanką legalizującą dany element
procesu przetwarzania danych osobowych przez Państwa stronę jest Art 6.
pkt 1 lit. a) RODO (zgoda), na mocy Art. 7 pkt 1 RODO proszę o
wykazanie, że udzieliłem Państwu zgodę na takie przetwarzanie moich
danych osobowych zanim to przetwarzanie nastąpiło, oraz że ta zgoda jest
ważna w świetle RODO (odnosząc się w szczególności do art. 7 ust. 3
RODO). Z góry zaznaczam, że ustawienia przeglądarki nie stanowią
ważnej w świetle RODO zgody.
</p>
<p>
Jeżeli wskazaną przez Państwa przesłanką legalizującą dany element
procesu przetwarzania danych osobowych przez Państwa stronę jest Art 6.
pkt 1 lit. b) RODO (niezbędność takiego przetwarzania do wykonania
umowy), proszę o wskazanie, w jaki sposób ta konieczność zachodzi, oraz
co sprawia, że Państwa zdaniem nie można wykonać umowy związanej z
wyświetleniem Państwa strony bez przekazywania sztucznie nadanego ID w
plikach Cookies lub historii przeglądania w nagłówku Referer do
wskazanych podmiotów trzecich.
</p>
<p>
Jeżeli wskazaną przez Państwa przesłanką legalizującą dany element
procesu przetwarzania danych osobowych przez Państwa stronę jest Art 6.
pkt 1 lit. f) RODO (uzasadniony interes), proszę o wskazanie, jaki to
jest <strong>konkretny interes</strong> (prosze o bardziej dokładny opis
niż np. tylko "marketing"), oraz o wynik testu równowagi pomiędzy
Państwa interesem a moimi podstawowymi wolnościami i prawami - ze
wskazaniem tego, co sprawia, że w Państwa ocenie Państwa uzasadniony
interes przeważa moje prawa i interesy w kontekście wspomnianych powyżej
procesów przetwarzania danych.
</p>
<p>
Niniejszym zwracam się także z żądaniem wycofania przesłanych przez
Państwa stronę moich danych osobowych z baz wyżej wymienionych podmiotów
oraz przesłania potwierdzenia uwiarygadniającego pomyślne wycofanie tych
danych. Proszę też o przesłanie tożsamości podmiotów, które
właścicielami wyżej wymienionych domen, abym mógł zapoznać się z ich
politykami prywatności.
</p>
<p>
Proszę też o wysłanie kopii danych zebranych na mój temat i wysłanych do
wyżej wymienionych podmiotów.
</p>
<p>
W odpowiedzi proszę się nie powoływać na IAB Europe i ich rzekomą renomę
w tworzeniu rozwiązań zgodnych z RODO. IAB chroni interes reklamodawców,
a nie Użytkowników i ich rozwiązania (np. TCF) notorycznie niezgodne
z RODO i pozbawione szacunku dla Użytkowników.
</p>
<p>
Apeluję także o wprowadzenie stosownych zmian na stronie tak, aby nie
pozostawiać cienia wątpliwości odnośnie tego, na mocy jakiej przesłanki
legalizującej dane przetwarzane przez wspomniane podmioty trzecie,
lub tak, aby te dane po prostu nie były wysyłane. Pomoże to zachować
prywatność innym użytkownikom Państwa strony. Polecam Państwa uwadze
oficjalne wytyczne EROD dotyczące zgody w kontekście RODO:
https://edpb.europa.eu/sites/default/files/files/file1/edpb_guidelines_202005_consent_pl.pdf
). Aby na przykład zapobiec automatycznemu wysyłaniu historii
przeglądania do podmiotów trzecich przez Państwa stronę, można po prostu
ustawić odpowiednio treść nagłówka{" "}
<a href="https://developer.mozilla.org/pl/docs/Web/HTTP/Headers/Referrer-Policy">
Referrer-Policy{" "}
</a>
.
</p>
</div>
);
}

View File

@ -0,0 +1,53 @@
import React, { useState } from "react";
import { HAREntry } from "../extended-request";
import { StolenDataEntry } from "../stolen-data-entry";
function handleNewFile(
element: HTMLInputElement,
marked_entries: StolenDataEntry[],
setFiltered: (Blob) => void
) {
const reader = new FileReader();
reader.addEventListener("load", () => {
const content = JSON.parse(reader.result as string);
content.log.entries = content.log.entries.filter((har_entry: HAREntry) =>
marked_entries.some((stolen_entry) =>
stolen_entry.matchesHAREntry(har_entry)
)
);
setFiltered(
new Blob([JSON.stringify(content)], { type: "application/json" })
);
});
reader.readAsText(element.files[0]);
}
export default function HARConverter({
marked_entries,
}: {
marked_entries: StolenDataEntry[];
}) {
const [filtered, setFiltered] = useState<Blob | null>(null);
const [filename, setFilename] = useState("");
return (
<div>
<input
type="file"
accept=".har"
onChange={(e) => {
setFilename(e.target.files[0].name);
handleNewFile(e.target, marked_entries, setFiltered);
}}
/>
{(filtered && (
<a
href={URL.createObjectURL(filtered)}
download={filename.replace(".har", "-filtered.har")}
>
Pobierz wyfiltrowany HAR
</a>
)) ||
null}
</div>
);
}

View File

@ -1,55 +1,10 @@
import React, { useState } from "react"; import React from "react";
import ReactDOM from "react-dom"; import ReactDOM from "react-dom";
import { getMemory } from "../memory"; import { getMemory } from "../memory";
import { RequestCluster } from "../request-cluster"; import EmailTemplate from "./email-template";
import { Classifications, Sources } from "../stolen-data-entry"; import HARConverter from "./har-converter";
import { getDate } from "../util";
const emailClassifications: Record<keyof typeof Classifications, string> = {
id: "sztucznie nadane mi ID",
history: "część mojej historii przeglądania",
};
const emailSources: Record<Sources, string> = {
header: "w nagłówku HTTP",
cookie: "z pliku Cookie",
pathname: "jako części adresu URL",
queryparams: "jako część adresu URL (query-params)",
};
type PopupState = "not_clicked" | "clicked_but_invalid";
function DomainSummary({ cluster }: { cluster: RequestCluster }) {
return (
<li>
Właściciel domeny <strong>{cluster.id}</strong> otrzymał:{" "}
<ul>
{cluster
.getMarkedEntries()
.sort((entryA, entryB) => (entryA.value > entryB.value ? -1 : 1))
.reduce((acc, entry, index, arr) => {
if (index === 0) {
return [entry];
}
if (entry.value != arr[index - 1].value) {
acc.push(entry);
}
return acc;
}, [])
.map((entry) => (
<li>
{emailClassifications[entry.classification]}{" "}
{emailSources[entry.source]}
&nbsp;(<code>{entry.name.trim()}</code>)
</li>
))}
</ul>
</li>
);
}
function Report() { function Report() {
const [popupState, setPopupState] = useState<PopupState>("not_clicked");
const origin = new URL(document.location.toString()).searchParams.get( const origin = new URL(document.location.toString()).searchParams.get(
"origin" "origin"
); );
@ -111,108 +66,8 @@ function Report() {
))} ))}
</tbody> </tbody>
</table> </table>
<label htmlFor="popupState">Status okienka o rodo:</label> <EmailTemplate {...{ marked_entries, clusters }} />
<select <HARConverter {...{ marked_entries }} />
id="popupState"
value={popupState}
onChange={(e) => setPopupState(e.target.value as PopupState)}
>
<option value="not_clicked">Nic nie kliknięte</option>
<option value="clicked_but_invalid">Kliknięte, ale nieważne</option>
</select>
<div>
<p>
Dzień dobry, w dniu {getDate()} odwiedziłem stronę{" "}
{marked_entries[0].request.originalURL}. Strona ta wysłała moje dane
osobowe do podmiotów trzecich - bez mojej zgody.{" "}
</p>
<ul>
{Object.values(clusters)
.filter((cluster) => cluster.hasMarks())
.map((cluster) => (
<DomainSummary cluster={cluster} />
))}
</ul>
{popupState === "not_clicked" ? (
<p>
Dane te zostały wysłane przez Państwa stronę zanim zdążyłem w ogóle
przeczytać treść wyskakującego okienka ze zgodami.
</p>
) : null}
<p>
Nie widzę zatem przesłanki legalizującej takie przetwarzanie moich
danych osobowych (na pewno nie jest to przetwarzanie konieczne do
wyświetlenia strony z technicznego punktu widzenia). Jeżeli takie
przesłanki legalizujące jednak występują, proszę o ich wskazanie,
<strong> dla każdego z celów i podmiotów z osobna</strong>.
</p>
<p>
Jeżeli wskazaną przez Państwa przesłanką legalizującą dany element
procesu przetwarzania danych osobowych przez Państwa stronę jest Art
6. pkt 1 lit. a) RODO (zgoda), na mocy Art. 7 pkt 1 RODO proszę o
wykazanie, że udzieliłem Państwu zgodę na takie przetwarzanie moich
danych osobowych zanim to przetwarzanie nastąpiło, oraz że ta zgoda
jest ważna w świetle RODO (odnosząc się w szczególności do art. 7 ust.
3 RODO). Z góry zaznaczam, że ustawienia przeglądarki nie stanowią
ważnej w świetle RODO zgody.
</p>
<p>
Jeżeli wskazaną przez Państwa przesłanką legalizującą dany element
procesu przetwarzania danych osobowych przez Państwa stronę jest Art
6. pkt 1 lit. b) RODO (niezbędność takiego przetwarzania do wykonania
umowy), proszę o wskazanie, w jaki sposób ta konieczność zachodzi,
oraz co sprawia, że Państwa zdaniem nie można wykonać umowy związanej
z wyświetleniem Państwa strony bez przekazywania sztucznie nadanego ID
w plikach Cookies lub historii przeglądania w nagłówku Referer do
wskazanych podmiotów trzecich.
</p>
<p>
Jeżeli wskazaną przez Państwa przesłanką legalizującą dany element
procesu przetwarzania danych osobowych przez Państwa stronę jest Art
6. pkt 1 lit. f) RODO (uzasadniony interes), proszę o wskazanie, jaki
to jest <strong>konkretny interes</strong> (prosze o bardziej dokładny
opis niż np. tylko "marketing"), oraz o wynik testu równowagi pomiędzy
Państwa interesem a moimi podstawowymi wolnościami i prawami - ze
wskazaniem tego, co sprawia, że w Państwa ocenie Państwa uzasadniony
interes przeważa moje prawa i interesy w kontekście wspomnianych
powyżej procesów przetwarzania danych.
</p>
<p>
Niniejszym zwracam się także z żądaniem wycofania przesłanych przez
Państwa stronę moich danych osobowych z baz wyżej wymienionych
podmiotów oraz przesłania potwierdzenia uwiarygadniającego pomyślne
wycofanie tych danych. Proszę też o przesłanie tożsamości podmiotów,
które właścicielami wyżej wymienionych domen, abym mógł zapoznać
się z ich politykami prywatności.
</p>
<p>
Proszę też o wysłanie kopii danych zebranych na mój temat i wysłanych
do wyżej wymienionych podmiotów.
</p>
<p>
W odpowiedzi proszę się nie powoływać na IAB Europe i ich rzekomą
renomę w tworzeniu rozwiązań zgodnych z RODO. IAB chroni interes
reklamodawców, a nie Użytkowników i ich rozwiązania (np. TCF)
notorycznie niezgodne z RODO i pozbawione szacunku dla Użytkowników.
</p>
<p>
Apeluję także o wprowadzenie stosownych zmian na stronie tak, aby nie
pozostawiać cienia wątpliwości odnośnie tego, na mocy jakiej
przesłanki legalizującej dane przetwarzane przez wspomniane
podmioty trzecie, lub tak, aby te dane po prostu nie były wysyłane.
Pomoże to zachować prywatność innym użytkownikom Państwa strony.
Polecam Państwa uwadze oficjalne wytyczne EROD dotyczące zgody w
kontekście RODO:
https://edpb.europa.eu/sites/default/files/files/file1/edpb_guidelines_202005_consent_pl.pdf
). Aby na przykład zapobiec automatycznemu wysyłaniu historii
przeglądania do podmiotów trzecich przez Państwa stronę, można po
prostu ustawić odpowiednio treść nagłówka{" "}
<a href="https://developer.mozilla.org/pl/docs/Web/HTTP/Headers/Referrer-Policy">
Referrer-Policy{" "}
</a>
.
</p>
</div>
</div> </div>
); );
} }

View File

@ -1,5 +1,5 @@
import { TCModel } from "@iabtcf/core"; import { TCModel } from "@iabtcf/core";
import ExtendedRequest from "./extended-request"; import ExtendedRequest, { HAREntry } from "./extended-request";
import { getMemory } from "./memory"; import { getMemory } from "./memory";
import { import {
getshorthost, getshorthost,
@ -142,7 +142,6 @@ export class StolenDataEntry {
} else { } else {
result = "id"; result = "id";
} }
console.log("classifying", this.value, result, this.request.origin);
return result; return result;
} }
@ -151,6 +150,10 @@ export class StolenDataEntry {
(entry) => (entry.classification = "id") (entry) => (entry.classification = "id")
); );
} }
matchesHAREntry(har: HAREntry): boolean {
return this.request.matchesHAREntry(har);
}
} }
export class MergedStolenDataEntry { export class MergedStolenDataEntry {