Sechs Review-Punkte: Speicherort, Domain-Pruefung, Rechte, Generator, Notizen, Bearbeiten
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
This commit is contained in:
parent
32cc4de8be
commit
65a07fbc18
10 changed files with 305 additions and 107 deletions
63
extension/urlmatch.js
Normal file
63
extension/urlmatch.js
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
'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;
|
||||
Loading…
Add table
Add a link
Reference in a new issue