Add API interaction code and garbage collection

This commit is contained in:
Darryl Nixon 2023-06-06 15:33:17 -07:00
parent a28b8ccab3
commit 6115e56171
4 changed files with 178 additions and 10 deletions

View file

@ -11,6 +11,8 @@ The addon collects collect the following information:
### SSL/TLS Certificate Data ### SSL/TLS Certificate Data
I collect SSL/TLS certificate data associated with the fully qualified domain names (FQDNs) of the websites you visit. This data includes information exposed by security information APIs, such as `webRequest.getSecurityInfo()` for Mozilla Firefox. Please note that these APIs are managed by the browser developer (e.g., Mozilla, Microsoft, Apple, Opera) and are subject to their security and privacy practices. This explicitly does not include data associated with requests you've made to these services such as URL paths, query parameters, authentication information, cookies, or anything unrelated to the certificate data the server sends you to verify they own the domain you are visiting. I collect SSL/TLS certificate data associated with the fully qualified domain names (FQDNs) of the websites you visit. This data includes information exposed by security information APIs, such as `webRequest.getSecurityInfo()` for Mozilla Firefox. Please note that these APIs are managed by the browser developer (e.g., Mozilla, Microsoft, Apple, Opera) and are subject to their security and privacy practices. This explicitly does not include data associated with requests you've made to these services such as URL paths, query parameters, authentication information, cookies, or anything unrelated to the certificate data the server sends you to verify they own the domain you are visiting.
If you are browsing sites which use internal, self-signed certificates, any information included in those certificates will be sent to CrowdTLS. The content of the certificates will not be accessible by CrowdTLS end users.
**TL;DR: I collect ONLY certificate data sent to you by the web domains you visit.** **TL;DR: I collect ONLY certificate data sent to you by the web domains you visit.**
### Metadata ### Metadata

View file

@ -37,16 +37,19 @@ You can see which permissions CrowdTLS requires in [manifest.json](manifest.json
| WebExtension Permission | CrowdTLS Usage | | WebExtension Permission | CrowdTLS Usage |
|---|---| |---|---|
| `webRequest` | Enables access and analyze web requests, allowing access to SSL/TLS certificate data. |
| `webRequestBlocking` | Required to handle and process HTTPS requests in a blocking manner. |
| `https://*/*` | Enables filtering specifically for HTTPS websites contacted, but not HTTP. | | `https://*/*` | Enables filtering specifically for HTTPS websites contacted, but not HTTP. |
| `notifications` | For displaying notifications for important updates or alerts. | | `webRequest` | Enables access and analyze web requests from above filter (i.e., SSL/TLS security data). |
| `storage` | Caches request/response content on your system so CrowdTLS functions more efficiently. | | `webRequestBlocking` | Required to handle and process HTTPS requests in a blocking manner. |
| `storage` | Stores local configuration and any ephemeral caching/optimization data. |
| `notifications` | Optional, for displaying notifications for important updates or alerts. |
Because CrowdTLS is written optimistically using [Manifest v3](https://developer.chrome.com/docs/extensions/mv3/intro/), local storage is used to store persistent and ephemeral data accessed through events rather than the traditional background page.
**What's your roadmap?** **What's your roadmap?**
The roadmap for CrowdTLS, if maintained, includes several exciting features and improvements. Here are some highlights: The roadmap for CrowdTLS, if maintained, includes several exciting features and improvements. Here are some highlights:
- Add alternative API support for browsers that don't support webRequest.getSecurityInfo().
- Enhancing the crowd-source validation process to provide more accurate and comprehensive certificate analysis. - Enhancing the crowd-source validation process to provide more accurate and comprehensive certificate analysis.
- Introducing user customization options to allow fine-tuning of validation criteria and feedback preferences. - Introducing user customization options to allow fine-tuning of validation criteria and feedback preferences.
- Collaborating with browser developers to streamline the integration of CrowdTLS functionalities natively into popular browsers. - Collaborating with browser developers to streamline the integration of CrowdTLS functionalities natively into popular browsers.

View file

@ -2,7 +2,7 @@
"manifest_version": 3, "manifest_version": 3,
"name": "CrowdTLS", "name": "CrowdTLS",
"version": "0.0.1", "version": "0.0.1",
"description": "Crowd-sourced validation of TLS/SSL certificates received.", "description": "Crowd-sourced validation for TLS/SSL certificates",
"icons": { "icons": {
"16": "icons/crowdtls-16.png", "16": "icons/crowdtls-16.png",
"24": "icons/crowdtls-24.png", "24": "icons/crowdtls-24.png",
@ -21,21 +21,27 @@
"default_title": "CrowdTLS", "default_title": "CrowdTLS",
"default_popup": "crowdtls.html" "default_popup": "crowdtls.html"
}, },
"default_locale": "en",
"host_permissions": [ "host_permissions": [
"https://*" "https://crowdtls.mips.uk/api/*",
"https://*/*"
], ],
"permissions": [ "permissions": [
"webRequest", "webRequest",
"webRequestBlocking", "webRequestBlocking",
"notifications",
"https://*/*",
"storage" "storage"
], ],
"optional_permissions": [
"notifications"
],
"background": { "background": {
"scripts": [ "scripts": [
"worker.js" "worker.js"
] ]
}, },
"offline_enabled": false "browser_specific_settings": {
"gecko": {
"id": "ext@crowdtls",
"strict_min_version": "101.0"
}
}
} }

157
worker.js
View file

@ -0,0 +1,157 @@
/**
* @file worker.js
* A background script for the CrowdTLS project.
* This script is used to process web requests and retrieve security information
* for each HTTPS response.
*/
"use strict";
const API_BASE = "https://crowdtls.mips.uk/api/v1";
/**
* Processes the given request details to extract and log security information.
*
* @async
* @function
* @param {Object} details - The details of the request.
* @param {string} details.requestId - The unique identifier for the request.
* @throws Will throw an error if the request fails or if the security state is insecure.
* @see {@link https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/webRequest/getSecurityInfo}
*/
async function process_request(details) {
try {
let securityInfo = await browser.webRequest.getSecurityInfo(details.requestId, { certificateChain: true, rawDER: true });
if (securityInfo.state !== "insecure") {
const fingerprint = securityInfo.certificates[0].fingerprint.sha256;
let fpData = localStorage.getItem(fingerprint);
const currentTime = Date.now();
if (fpData) {
fpData = JSON.parse(fpData);
// If the last request was less than 10 minutes ago, don't spam the API
if (fpData.lastCheck && currentTime - fpData.lastCheck < 10 * 60 * 1000) {
return;
}
// If the last response was less than 12 hours ago, don't check again
if (fpData.lastResponse && currentTime - fpData.lastResponse < 12 * 60 * 60 * 1000) {
return;
}
} else {
fpData = {};
}
fpData.lastCheck = currentTime;
localStorage.setItem(fingerprint, JSON.stringify(fpData));
await check_fingerprint(securityInfo.certificates);
}
} catch (error) {
console.error(error);
}
}
/**
* Checks the fingerprint and sends a REST GET request to the API.
*
* @async
* @function
* @param {Array} certificates - The list of certificates.
*/
async function check_fingerprint(certificates) {
try {
const fingerprints = certificates.map(cert => cert.fingerprint.sha256);
const response = await fetch(`${API_BASE}/check`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ fps: fingerprints }),
timeout: 5000
});
if (!response.ok) {
console.error(`Error: ${response.status}`);
return;
}
const data = await response.json();
if (data) {
if (data["send"] === true) {
send_certificate_chain(certificates);
}
}
}
catch (error) {
console.error(error);
}
}
/**
* Sends the certificate chain to the CrowdTLS service.
*
* @async
* @function
* @param {Array} certificates - The list of certificates.
* @throws Will log an error to the console if the request fails.
*/
async function send_certificate_chain(certificates) {
try {
let chain = {};
certificates.forEach(cert => {
chain[cert.fingerprint.sha256] = cert.rawDER;
});
console.log(JSON.stringify(chain));
const response = await fetch(`${API_BASE} /new`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(chain),
timeout: 10000
});
if (!response.ok) {
console.error(`Request returned with status ${response.status}`);
}
} catch (error) {
console.error(error);
}
}
/**
* @function
* @description Performs garbage collection on localStorage by removing objects older than 12 hours based on their "lastCheck" property.
* @returns {void}
*/
function garbage_collection() {
const now = new Date().getTime();
const twelveHoursInMillis = 12 * 60 * 60 * 1000;
for (let i = 0; i < localStorage.length; i++) {
const key = localStorage.key(i);
const value = localStorage.getItem(key);
if (value) {
const entry = JSON.parse(value);
if (entry.lastCheck && now - entry.lastCheck > twelveHoursInMillis) {
localStorage.removeItem(key);
}
}
}
}
setInterval(garbage_collection, 3600000);
/**
* The listener for HTTPS responses. Schedules the process_request() function for every response.
* Blocking is necessary to ensure that the response is not delivered before the function is completed.
*
* @see {@link https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/webRequest/onHeadersReceived}
*/
browser.webRequest.onHeadersReceived.addListener(
process_request,
{ urls: ["https://*/*"] },
["blocking"]
);