1. Passwort mehrstufiger Logins nicht mehr auf der Platte: Der Auftrag lag
als __pendingFill in chrome.storage.local, also im Klartext auf der
Festplatte. Die 30-Sekunden-Pruefung verhinderte nur die Verwendung,
nicht die Speicherung - wurde der zweite Schritt nie erreicht, blieb
das Passwort liegen. Er liegt jetzt ausschliesslich im Speicher des
Service Workers, je Tab, und wird beim Abholen verbraucht, nach 30 s
verworfen, beim Sperren geleert und beim Schliessen des Tabs entfernt.
Reste frueherer Versionen raeumt onInstalled ab.
2. Domain-Warnung: fillDomainMatches akzeptierte mit
eh.endsWith('.' + pageHost) auch die Gegenrichtung - ein Eintrag fuer
vpn.firma.de galt auf firma.de als passend und die Warnung blieb aus.
Diese Klausel entfaellt.
3. scripting und activeTab werden nicht mehr angefordert; beide waren
unbenutzt (das Content-Script laeuft ueber content_scripts, der
Tab-Zugriff ueber host_permissions). PERMISSIONS.md begruendete
scripting mit dem nativen Value-Setter, was nichts damit zu tun hat.
4. Passwort-Generator: buf lieferte dieselben Werte fuer Zeichenwahl und
Mischreihenfolge, wodurch die Permutation mit dem Inhalt korrelierte.
Beides zieht jetzt getrennt ueber randomBelow(), das den obersten,
unvollstaendigen Block verwirft (gleichverteilt statt Rest-Modulo).
Laenge (12-48) und Sonderzeichen sind waehlbar.
5. Notizen laufen ueber copySecret und werden damit ebenfalls aus der
Zwischenablage entfernt; sie enthalten in der Praxis oft
Wiederherstellungscodes. copyToClipboard entfaellt.
6. urlmatch.js buendelt die drei abweichenden matchUrl-Fassungen zu einer
Regel, geladen in Service Worker, Popup und Seiten. escAttr escapt jetzt
auch & < > und Apostroph, traegt also in jedem Attributkontext.
Eintraege lassen sich im Popup bearbeiten und loeschen; beim Bearbeiten
bedeutet ein leeres Passwortfeld unveraendert, sodass das Passwort das
Popup nicht verlaesst.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01G12DRMpe4UjYDwuRU1sjy1
63 lines
2.3 KiB
JavaScript
63 lines
2.3 KiB
JavaScript
'use strict';
|
||
|
||
/*
|
||
* Gemeinsame Zuordnung Eintrag ↔ Seite.
|
||
*
|
||
* Wird in allen drei Kontexten geladen (Service Worker via importScripts,
|
||
* Popup via <script>, Seiten via content_scripts) – damit Vorschlagsliste und
|
||
* Sicherheitswarnung dieselbe Regel anwenden.
|
||
*
|
||
* Regel: Ein Eintrag passt zu einer Seite, wenn deren Host dem hinterlegten Host
|
||
* entspricht oder eine Subdomain davon ist. Die Gegenrichtung gilt bewusst nicht –
|
||
* ein Eintrag für `vpn.firma.de` passt nicht zu `firma.de`.
|
||
*/
|
||
var VaultUrl = (function () {
|
||
/**
|
||
* Host einer Adresse in vergleichbarer Form (klein, ohne `www.`).
|
||
* @param {string} raw Adresse mit oder ohne Schema
|
||
* @return {string} Host oder '' wenn nicht bestimmbar
|
||
*/
|
||
function host(raw) {
|
||
const s = String(raw || '').trim();
|
||
if (!s) return '';
|
||
try {
|
||
return new URL(s.includes('://') ? s : 'https://' + s).hostname.replace(/^www\./, '').toLowerCase();
|
||
} catch {
|
||
return s.replace(/^www\./, '').toLowerCase();
|
||
}
|
||
}
|
||
|
||
/** Hinterlegte Adressen eines Eintrags (mehrzeilig) als Liste. */
|
||
function list(entryUrls) {
|
||
if (Array.isArray(entryUrls)) return entryUrls.map(u => String(u || '').trim()).filter(Boolean);
|
||
return String(entryUrls || '').split('\n').map(u => u.trim()).filter(Boolean);
|
||
}
|
||
|
||
/**
|
||
* Passt einer der hinterlegten Hosts zur Seite?
|
||
* @param {string|string[]} entryUrls Adressen des Eintrags
|
||
* @param {string} pageUrl Adresse der Seite
|
||
* @return {boolean}
|
||
*/
|
||
function matches(entryUrls, pageUrl) {
|
||
const pageHost = host(pageUrl);
|
||
if (!pageHost) return false;
|
||
return list(entryUrls).some(raw => {
|
||
let eh = host(raw);
|
||
if (eh.startsWith('*.')) eh = eh.slice(2);
|
||
if (!eh) return false;
|
||
return pageHost === eh || pageHost.endsWith('.' + eh);
|
||
});
|
||
}
|
||
|
||
/** Wie `matches`, wertet einen Eintrag ohne hinterlegte Adresse aber als passend. */
|
||
function matchesOrUnset(entryUrls, pageUrl) {
|
||
if (!list(entryUrls).length) return true;
|
||
return matches(entryUrls, pageUrl);
|
||
}
|
||
|
||
return { host, list, matches, matchesOrUnset };
|
||
})();
|
||
|
||
// Im Service Worker steht `self` zur Verfügung, im Popup/Content-Script `window`.
|
||
if (typeof self !== 'undefined') self.VaultUrl = VaultUrl;
|