Compare commits

...
Sign in to create a new pull request.

7 commits

Author SHA1 Message Date
OpenNIT Extension Sync
a032dd5b13 Store-Build automatisch aus OpenNIT aktualisiert 2026-08-02 11:04:36 +00:00
Claude
baf13c865f Version 2.5.0
Changelog-Abschnitt [Unreleased] geschnitten und manifest.json von 2.4.1
auf 2.5.0 gezogen. Der Store weist einen Upload mit bereits
veroeffentlichter Versionsnummer ab, 2.4.1 ist die aktuell
veroeffentlichte Version.

Minor, weil der Stand neue Funktionen enthaelt (Eintraege bearbeiten und
loeschen, einstellbarer Generator, 2FA-Code bereitlegen) und nicht nur
Korrekturen.

Das Build-Verzeichnis dist/ gehoert nicht ins Repository.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01G12DRMpe4UjYDwuRU1sjy1
2026-07-31 15:55:37 +02:00
Claude
1b3ed44e6e Benutzername in der Detailansicht immer im Klartext
Das Auge neben dem Benutzernamen schaltete eine Maskierung, die
standardmaessig ohnehin aus war. Ein Benutzername ist kein Geheimnis, das
Umschalten also ohne Nutzen. Button, Handler und der zugehoerige Zustand
entfallen; der Kopieren-Button bleibt. Das Passwort bleibt maskiert.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01G12DRMpe4UjYDwuRU1sjy1
2026-07-31 15:55:37 +02:00
Claude
07a5785580 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
2026-07-31 15:55:37 +02:00
Claude
26c01a4fc3 Vorschlaege weichen Seiten-Comboboxen, 2FA-Code bereitlegen
Vorschlagsliste: Bisher galt jedes E-Mail-Feld als Anmeldefeld
(isUsernameField gibt bei type=email bedingungslos true zurueck), und das
Dropdown liegt mit maximalem z-index direkt unter dem Feld. Auf Seiten
mit eigener Auswahlliste - etwa einem Benutzer-Picker - verdeckte es
deren Treffer, die dadurch nicht mehr anklickbar waren.

Zwei Regeln davor: Felder mit eigener Vorschlagsliste (ARIA-Combobox mit
aria-autocomplete/aria-controls/aria-expanded oder <input list>) bekommen
keine Vault-Vorschlaege mehr, sofern autocomplete sie nicht ausdruecklich
als Anmeldefeld ausweist. Und sobald der Nutzer selbst tippt, blendet
sich die Liste aus und bleibt es, bis das Feld wieder leer ist.

2FA-Code bereitlegen: Nach dem Ausfuellen eines Eintrags mit 2FA bleibt
dieser fuenf Minuten vorgemerkt. Taucht danach ein 2FA-Feld auf oder wird
es fokussiert - auch auf einer Folgeseite -, wird ein frischer Code
geholt und in die Zwischenablage gelegt, statt wie bisher nur einmal zum
Fuellzeitpunkt (wo er bis zum 2FA-Schritt laengst rotiert waere).
Automatisch wird ausschliesslich kopiert; ins Feld geschrieben wird ein
Code weiterhin nur bei ausdruecklicher Auswahl. Geschrieben wird zuerst
ueber die Seite und, falls diese keinen Zugriff bekommt, ueber das
Offscreen-Dokument des Hintergrunds. Abschaltbar in den Einstellungen.

Beim Sperren des Tresors werden Vormerkung und ausstehender Fuellauftrag
verworfen. Der Seiten-Scan des MutationObservers laeuft jetzt gedrosselt
statt bei jeder einzelnen Mutation.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01G12DRMpe4UjYDwuRU1sjy1
2026-07-31 15:55:37 +02:00
Claude
19051bbacd 2FA-Restlaufzeit korrigiert, manuellen API-Token entfernt
Countdown des 2FA-Codes: Die Anzeige zaehlte blind im Sekundentakt
herunter und lief dadurch aus dem Takt. Am Ende eines Zeitfensters wurde
zwar ein neuer Code angefordert, der Zaehler aber nicht angehalten - bei
langsamer oder fehlschlagender Antwort lief er ins Negative und stiess
jede Sekunde eine weitere Anfrage an (inkl. Audit-Eintrag je Abruf),
waehrend die Anzeige auf dem alten Wert stehenblieb.

Die Restlaufzeit wird jetzt aus einem festen Ablaufzeitpunkt berechnet,
sodass gedrosselte oder ausgefallene Ticks sie nicht verschieben. Pro
Ablauf wird genau einmal nachgeladen; liefert der Server keinen Code
mehr (gesperrt/offline), stoppt der Timer und die Anzeige wird geleert.
Dieselbe Rechnung gilt fuer die Benachrichtigung im Seiteninhalt; die
Periode steckt dort wie im Popup in einer Konstanten statt als 30 im
Ausdruck.

Manueller API-Token: Eingabefeld, "Token speichern" und "Verbindung
testen" sind aus den Optionen entfernt; die Server-URL laesst sich
weiterhin separat speichern. getAccessToken() kennt nur noch den
SSO-Weg, und ein aus einer frueheren Version uebernommener Token wird
bei onInstalled aus chrome.storage.local geloescht. Doku und
Store-Listing entsprechend angepasst.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01G12DRMpe4UjYDwuRU1sjy1
2026-07-31 15:55:37 +02:00
Claude
ea5cd8d623 Fix: Eintrag anlegen scheiterte nach SSO-Anmeldung
Das Speichern eines neuen Eintrags im Popup las den Token direkt aus
chrome.storage.local und verlangte den manuellen apiToken. Nach einer
SSO-Anmeldung wird dieser Schluessel jedoch geloescht (nur Refresh-Token
plus kurzlebiger Access-Token in storage.session), sodass das Anlegen
immer mit "Nicht konfiguriert." abbrach.

Das Anlegen laeuft jetzt wie alle uebrigen Aufrufe ueber den
Background-Service-Worker (apiFetch): SSO-Access-Token mit automatischer
Erneuerung oder, falls gesetzt, manueller Token. Eine serverseitige
Sperre (423) fuehrt zur PIN-Abfrage statt zu einer Fehlermeldung, und der
Eintrags-Cache wird nach dem Anlegen verworfen.

Ausserdem entfaellt in den Optionen ein redundanter Statusabruf, der
ebenfalls nur den manuellen Token beruecksichtigte; loadConnStatus()
deckt beide Anmeldewege bereits ab.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01G12DRMpe4UjYDwuRU1sjy1
2026-07-31 15:55:37 +02:00
10 changed files with 176 additions and 32 deletions

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
dist/

View file

@ -3,6 +3,61 @@
Format nach [Keep a Changelog](https://keepachangelog.com/de/1.1.0/).
Die Erweiterungsversion (`manifest.json`) ist unabhängig von der OpenNIT-Serverversion.
## [Unreleased]
## [2.5.0] - 2026-07-31
### Hinzugefügt
- **Einträge bearbeiten und löschen:** In der Detailansicht gibt es jetzt „Bearbeiten" und „Löschen".
Beim Bearbeiten bleibt das Passwortfeld leer wer es leer lässt, behält das gespeicherte Passwort;
2FA-Secret und Ordner bleiben unangetastet. Für Team-Einträge greift das Schreibrecht des Teams.
- **Passwort-Generator einstellbar:** Länge (1248) und Sonderzeichen lassen sich beim Anlegen wählen
hilfreich bei Seiten, die Sonderzeichen ablehnen.
- **2FA-Code wird für den nächsten Schritt bereitgelegt:** Nach dem Ausfüllen eines Eintrags mit 2FA
landet beim nächsten 2FA-Feld automatisch ein **frischer** Code in der Zwischenablage auch dann,
wenn die Abfrage erst auf einer Folgeseite kommt (z. B. Microsoft-Anmeldung). Einfügen genügt mit
Strg + V; der bisherige Inhalt der Zwischenablage wird dabei überschrieben und der Code nach 30
Sekunden wieder entfernt. Abschaltbar unter „Sicherheit → 2FA-Code beim Anmelden bereitlegen".
### Sicherheit
- **Passwort für mehrstufige Logins nicht mehr auf der Festplatte:** Verteilt eine Anmeldung Benutzername
und Passwort auf zwei Schritte, wurde das Passwort bisher im lokalen Speicher der Erweiterung abgelegt
und blieb dort liegen, wenn der zweite Schritt nie erreicht wurde. Es wird jetzt nur noch im Arbeits-
speicher gehalten, an den jeweiligen Tab gebunden und nach 30 Sekunden bzw. beim Sperren verworfen.
- **Warnung bei fremder Domain greift zuverlässiger:** Ein Eintrag für `vpn.firma.de` galt auf `firma.de`
fälschlich als passend, sodass die Warnung ausblieb. Zuordnung und Warnung nutzen jetzt dieselbe Regel:
nur die hinterlegte Adresse selbst und deren Unteradressen gelten als passend.
- **Weniger Berechtigungen:** `scripting` und `activeTab` werden nicht mehr angefordert beide wurden
nicht benötigt.
- **Passwort-Generator:** Der Zufall für die Mischreihenfolge wird jetzt getrennt von der Zeichenauswahl
gezogen, und die Zeichenwahl ist gleichverteilt.
- Notizen werden beim Kopieren wie andere Geheimnisse behandelt und nach 30 Sekunden aus der
Zwischenablage entfernt.
### Geändert
- **Benutzername immer sichtbar:** Das Auge zum Ausblenden des Benutzernamens in der Detailansicht ist
entfallen ein Benutzername ist kein Geheimnis. Das Passwort bleibt weiterhin maskiert.
- **Vorschläge weichen der Seite:** Sobald in ein Feld getippt wird, verschwindet die Vault-Liste
darunter erscheint typischerweise die Suche der Seite selbst. Bei Feldern, die erkennbar eine eigene
Auswahlliste öffnen (etwa Benutzer-Auswahlfelder), erscheinen gar keine Vault-Vorschläge mehr.
Ausdrücklich als Anmeldefeld ausgezeichnete Felder sind davon ausgenommen.
- **Anmeldung nur noch per SSO:** Das Feld für den manuell erzeugten API-Token samt „Verbindung testen"
ist aus den Einstellungen entfernt. Die Verbindung entsteht ausschließlich über „Mit OpenNIT anmelden".
Ein aus einer früheren Version übernommener Token wird beim Update aus dem lokalen Speicher gelöscht;
wer bisher nur damit verbunden war, meldet sich einmal per SSO an.
### Behoben
- **Restlaufzeit des 2FA-Codes wird wieder korrekt angezeigt:** Der Countdown blieb am Ende eines
Zeitfensters stehen und lief mit der Zeit aus dem Takt. Er rechnet nun gegen den tatsächlichen
Ablaufzeitpunkt und holt den neuen Code beim Wechsel genau einmal nach. Lässt sich kein neuer Code
laden (Tresor gesperrt oder Verbindung weg), zeigt die Anzeige das an, statt auf einem abgelaufenen
Wert stehen zu bleiben.
- **Neuen Eintrag anlegen funktioniert wieder nach SSO-Anmeldung:** Das Speichern eines im Popup
erzeugten Passworts brach bisher mit „Nicht konfiguriert." ab, wenn die Erweiterung über
„Mit OpenNIT anmelden" verbunden war es wurde ausschließlich der manuelle Token akzeptiert.
Das Anlegen nutzt nun denselben Zugang wie alle übrigen Aufrufe (inkl. automatischer
Token-Erneuerung). Ist der Tresor gesperrt, erscheint die PIN-Abfrage statt einer Fehlermeldung.
## [2.4.0] - 2026-07-01
### Hinzugefügt

View file

@ -17,7 +17,7 @@ technisches Client-Werkzeug ohne eigenen Server.
| Datum | Zweck | Speicherort |
|-------|-------|-------------|
| **Server-URL** | Adresse deiner OpenNIT-Instanz | lokal (`chrome.storage.local`) |
| **API-Token** | Authentifizierung gegenüber deiner Instanz | lokal (`chrome.storage.local`) |
| **Sitzungstoken** | Authentifizierung gegenüber deiner Instanz (per SSO ausgestellt) | lokal (`chrome.storage.local`) |
| **Einstellungen** (PIN-Sperrdauer, Zwischenablage-Option) | Verhalten der Erweiterung | lokal (`chrome.storage.local`) |
| **Entsperr-Status** | Merkt, ob die PIN-Sperre entsperrt ist | Sitzungsspeicher (`chrome.storage.session`, wird beim Schließen des Browsers gelöscht) |
| **Tresor-Einträge** (Titel, Benutzername, URL, Notizen, ob 2FA vorhanden) | Anzeige & Suche | flüchtig im Arbeitsspeicher (max. 5 Min zwischengespeichert) |
@ -30,7 +30,7 @@ Die Erweiterung erstellt **keine** Nutzungsprofile und protokolliert **kein** Su
- Es werden Daten **ausschließlich** an die von dir eingetragene **OpenNIT-Server-URL** übertragen
(verschlüsselt via HTTPS, sofern deine Instanz HTTPS nutzt).
- Übertragen werden: der API-Token (zur Authentifizierung), die aktuelle Seiten-Adresse (zum Finden
- Übertragen werden: der Sitzungstoken (zur Authentifizierung), die aktuelle Seiten-Adresse (zum Finden
passender Einträge), sowie beim Anlegen neuer Einträge die von dir eingegebenen Felder.
- Es erfolgt **keine** Übermittlung an Anthropic, Google (außer der Chrome-Sync deines eigenen Browsers,
falls du ihn aktiviert hast) oder sonstige Dritte.
@ -42,7 +42,7 @@ Siehe [`docs/PERMISSIONS.md`](docs/PERMISSIONS.md). Kurz:
- **Zugriff auf alle Websites** (`host_permissions: <all_urls>`): nötig, um Login-Felder auf beliebigen
Seiten zu erkennen und auf Wunsch auszufüllen. Es werden **keine** Seiteninhalte gelesen oder
übertragen, außer den zum Ausfüllen nötigen Formularfeldern und diese verlassen den Browser nicht.
- **storage**: lokale Speicherung von URL, Token und Einstellungen.
- **storage**: lokale Speicherung von URL, Sitzungstoken und Einstellungen.
- **scripting / activeTab**: Einfügen der Zugangsdaten in das aktive Tab-Formular.
- **alarms / offscreen**: automatisches Leeren der Zwischenablage nach dem Kopieren.
@ -53,7 +53,7 @@ Zwischenablage entfernt.
## 6. Speicherdauer
- Server-URL, Token und Einstellungen bleiben lokal gespeichert, bis du sie änderst oder die Erweiterung
- Server-URL, Sitzungstoken und Einstellungen bleiben lokal gespeichert, bis du sie änderst oder die Erweiterung
entfernst.
- Zwischengespeicherte Einträge werden spätestens nach 5 Minuten bzw. beim Sperren verworfen.
- Passwörter/2FA-Codes werden nicht dauerhaft gespeichert.
@ -62,7 +62,7 @@ Zwischenablage entfernt.
Da die eigentliche Datenverarbeitung in deiner OpenNIT-Instanz stattfindet, richten sich Auskunfts-,
Lösch- und Berichtigungsrechte an deren Betreiber. Lokale Daten der Erweiterung entfernst du durch
Deinstallieren der Erweiterung oder Löschen des Tokens in den Einstellungen.
Deinstallieren der Erweiterung oder „Abmelden" in den Einstellungen.
## 8. Kontakt
@ -78,7 +78,7 @@ eine erreichbare Kontaktadresse ergänzen.
**Controller.** The operator of the OpenNIT instance you connect to. The extension itself has no server.
**Data processed.** Server URL, API token and settings (stored locally); unlock state (session storage,
**Data processed.** Server URL, session tokens and settings (stored locally); unlock state (session storage,
cleared when the browser closes); vault entry metadata (title, username, URL, notes, whether 2FA exists
cached in memory for up to 5 minutes); passwords/2FA codes (fetched **only** at the moment of use, never
stored permanently); the active tab URL (to find matching entries).
@ -96,4 +96,4 @@ browser. See [`docs/PERMISSIONS.md`](docs/PERMISSIONS.md).
within 5 minutes; secrets are never stored persistently.
**Your rights.** Because processing happens in your OpenNIT instance, direct data-subject requests to its
operator. Remove local extension data by uninstalling the extension or clearing the token.
operator. Remove local extension data by uninstalling the extension or signing out in the settings.

View file

@ -22,7 +22,10 @@ deiner selbst gehosteten OpenNIT-Instanz und bietet:
- 👁️ **Detailansicht** mit Anzeigen/Kopieren von Zugangsdaten und 2FA-Code mit Countdown
- **Neue Einträge anlegen** inkl. **Passwort-Generator**
- 🔒 **PIN-Sperre** mit demselben PIN wie der Web-Tresor (Dauer frei wählbar, bis „bis Browser schließt")
- ✏️ **Anlegen, Bearbeiten und Löschen** von Einträgen direkt im Popup
- 🧹 **Zwischenablage-Auto-Clear** nach dem Kopieren von Geheimnissen
- 📋 **2FA-Code bereitgelegt:** nach dem Ausfüllen landet beim nächsten 2FA-Feld auch auf einer
Folgeseite automatisch ein frischer Code in der Zwischenablage (Strg + V genügt)
- 🖼️ **Favicons** der hinterlegten Seiten (serverseitig gecacht keine externen Aufrufe)
- 🌙 **Heller & dunkler Modus** (folgt dem System)
@ -37,19 +40,18 @@ Die Erweiterung ist ein reiner **Client** zu deiner OpenNIT-Instanz. Sie enthäl
und **keinen** Remote-Code alle Skripte sind im Paket enthalten. Kommuniziert wird ausschließlich mit dem
von dir konfigurierten OpenNIT-Server über dessen REST-API (`/api/vault/extension/...`) per **Bearer-Token**.
- Die Anmeldung erfolgt per **SSO** („Mit OpenNIT anmelden"). Die Erweiterung erhält dabei automatisch
ein kurzlebiges, rotierendes Zugriffstoken ein manuelles Erzeugen von Tokens im Web-Tresor entfällt.
- Die Anmeldung erfolgt ausschließlich per **SSO** („Mit OpenNIT anmelden"). Die Erweiterung erhält dabei
ein kurzlebiges, rotierendes Zugriffstoken ein manuelles Erzeugen von Tokens entfällt.
- Passwörter werden **serverseitig** ver-/entschlüsselt; die Erweiterung fordert das Klartext-Passwort
eines Eintrags erst **im Moment des Ausfüllens/Kopierens** an nicht beim Laden der Liste.
- Es findet **keine** Ende-zu-Ende-Entschlüsselung im Browser statt; die Erweiterung speichert keine
Passwörter dauerhaft (nur Server-URL, Token und Einstellungen in `chrome.storage`).
Passwörter dauerhaft (nur Server-URL, Sitzungstoken und Einstellungen in `chrome.storage`).
Details: [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md) · Berechtigungen: [`docs/PERMISSIONS.md`](docs/PERMISSIONS.md)
> **Anmeldung per SSO (Standard):** „Mit OpenNIT anmelden" (OAuth 2.0 + PKCE) Anmeldung wie an OpenNIT
> (lokal + 2FA / M365 / Keycloak), automatische Token-Erneuerung mit Rotation. Ein manuell erzeugter Token
> ist nur noch als „Erweitert"-Fallback in den Erweiterungs-Einstellungen vorgesehen; OpenNIT bietet dafür
> im Frontend keine Token-Erzeugung mehr an. Konzept/Details: [`docs/SSO-PLAN.md`](docs/SSO-PLAN.md).
> **Anmeldung per SSO:** „Mit OpenNIT anmelden" (OAuth 2.0 + PKCE) Anmeldung wie an OpenNIT
> (lokal + 2FA / M365 / Keycloak), automatische Token-Erneuerung mit Rotation. Einen manuell eingetragenen
> API-Token unterstützt die Erweiterung nicht mehr.
## Installation
@ -80,9 +82,10 @@ Repository gedacht.
| Einstellung | Beschreibung |
|--------------------|--------------|
| **Server-URL** | Adresse deiner OpenNIT-Instanz, ohne abschließenden Slash (`https://…`). |
| **Anmeldung** | Per **SSO** („Mit OpenNIT anmelden"). Ein manueller API-Token ist nur als „Erweitert"-Fallback vorgesehen. |
| **Anmeldung** | Ausschließlich per **SSO** („Mit OpenNIT anmelden"). |
| **PIN-Sperre** | Aus / 5 Min / 15 Min / 1 Std / bis der Browser geschlossen wird. Nutzt den **Tresor-PIN**. |
| **Zwischenablage** | Nach 30 s automatisch leeren (Standard: an). |
| **2FA bereitlegen** | Frischen 2FA-Code beim nächsten 2FA-Feld in die Zwischenablage legen (Standard: an). |
## Build / Paketierung

View file

@ -16,7 +16,7 @@ Die Erweiterung ist ein **Manifest-V3-Client** ohne eigenen Server. Sie besteht
└───────────────┘ └──────────┬───────────┘
│ CLIP_WRITE
┌────────▼─────────┐
│ offscreen.html │ (Zwischenablage leeren)
│ offscreen.html │ (Zwischenablage schreiben/leeren)
└──────────────────┘
```
@ -27,8 +27,9 @@ Die Erweiterung ist ein **Manifest-V3-Client** ohne eigenen Server. Sie besteht
| `background.js` | Zentrale Logik: API-Aufrufe, 5-Minuten-Cache, **Lock-Gate**, Favicon-Cache (Data-URLs), Zwischenablage-Timer. Alle Secrets fließen hier durch. |
| `content.js` | Wird auf jeder Seite ausgeführt. Erkennt Benutzer-/Passwort-/OTP-Felder (inkl. Shadow-DOM, mehrstufige Logins, segmentierte OTP-Felder), zeigt das Vorschlags-Dropdown und füllt Felder framework-kompatibel (React/Vue/Angular). |
| `popup.html` / `popup.js` | Toolbar-Popup: Liste, Suche, Detailansicht, Anlegen + Generator, PIN-Schirm. |
| `options.html` / `options.js` | Einstellungen: Server-URL, Token, PIN-Sperrdauer, Zwischenablage. |
| `offscreen.html` / `offscreen.js` | Minimaldokument, das ausschließlich die Zwischenablage leert (MV3-konform). |
| `options.html` / `options.js` | Einstellungen: Server-URL, SSO-Anmeldung, PIN-Sperrdauer, Zwischenablage. |
| `offscreen.html` / `offscreen.js` | Minimaldokument, das ausschließlich die Zwischenablage beschreibt bzw. leert (MV3-konform). |
| `urlmatch.js` | Gemeinsame Zuordnung Eintrag ↔ Seite (`VaultUrl`), geladen in allen drei Kontexten damit Vorschlagsliste und Sicherheitswarnung dieselbe Regel anwenden. |
## Nachrichten (Auszug)
@ -38,9 +39,12 @@ Die Erweiterung ist ein **Manifest-V3-Client** ohne eigenen Server. Sie besteht
| `GET_LOCK` / `DO_UNLOCK` / `LOCK_NOW` | popup → bg | PIN-Sperre abfragen/entsperren/sperren |
| `GET_ENTRIES` / `GET_MATCHING_ENTRIES` | popup/content → bg | Einträge (alle / passend zur URL) |
| `GET_PASSWORD` / `GET_TOTP` | popup/content → bg | Secret **on demand** |
| `CREATE_ENTRY` / `UPDATE_ENTRY` / `DELETE_ENTRY` | popup → bg | Eintrag anlegen / ändern / löschen |
| `SET_PENDING_FILL` / `TAKE_PENDING_FILL` | content → bg | Passwort für den zweiten Login-Schritt hinterlegen bzw. abholen (nur im Speicher, je Tab) |
| `GET_FAVICON` | popup/content → bg | Favicon als Data-URL (serverseitig gecacht) |
| `VAULT_FILL` | popup → content | Aktives Tab-Formular ausfüllen |
| `SCHEDULE_CLIP_CLEAR` | popup/content → bg | Zwischenablage-Leerung planen |
| `CLIP_WRITE` | content → bg | In die Zwischenablage schreiben, wenn die Seite selbst keinen Zugriff bekommt |
## Server-API (in OpenNIT)
@ -51,6 +55,8 @@ Alle Endpunkte unter `/api/vault/extension/` mit `Authorization: Bearer <token>`
- `GET /entries/{id}/totp` aktueller TOTP-Code + Restsekunden
- `GET /entries/{id}/favicon?fetch=1` gecachtes Favicon (bei Bedarf serverseitig geholt)
- `POST /entries` neuen Eintrag anlegen
- `POST /entries/{id}` Eintrag ändern (leeres Passwortfeld = unverändert)
- `POST /entries/{id}/delete` Eintrag löschen
- `GET /status` Token gültig? + `pin_enabled` / `pin_lock_secs`
- `POST /unlock` Tresor-PIN verifizieren + serverseitiges Entsperr-Fenster für den Token setzen
- `POST /lock` Token sofort wieder sperren (Entsperr-Fenster zurücksetzen)
@ -74,5 +80,7 @@ Fensterdauer fest; „Bis der Browser geschlossen wird" nutzt ein langes Serverf
- **Kein Remote-Code** alle Skripte im Paket (MV3-CSP-konform, keine Inline-Skripte).
- **Secrets on demand** Passwörter/TOTP erst bei Nutzung, nie in der Liste.
- **Kein persistentes Secret** nur URL, Token, Einstellungen in `chrome.storage`.
- **Kein persistentes Secret** nur URL, Sitzungstoken, Einstellungen in `chrome.storage`. Das Passwort
für einen mehrstufigen Login liegt ausschließlich im Speicher des Service Workers (je Tab, 30 s),
nie in `chrome.storage`, das auf die Festplatte geschrieben würde.
- **Server-seitige Krypto** Ver-/Entschlüsselung im OpenNIT-Server, nicht im Browser.

View file

@ -16,15 +16,6 @@ Browser nicht. Es findet kein Tracking und keine Analyse statt.
**Warum:** Das In-Seite-Dropdown mit Vorschlägen und die Felderkennung laufen als Content-Script.
Notwendig für Autofill und die 2FA-Erkennung (inkl. Shadow-DOM und mehrstufiger Logins).
## `scripting`
**Warum:** Werte werden über den nativen Value-Setter gesetzt und Events ausgelöst, damit auch
React/Vue/Angular-Formulare die Eingaben übernehmen.
## `activeTab`
**Warum:** Zugriff auf den aktiven Tab beim Ausfüllen aus dem Popup („Auf dieser Seite ausfüllen").
## `storage`
**Warum:** Lokale Speicherung von Server-URL, Zugriffstoken (per SSO) und Einstellungen; Entsperr-Status in
@ -38,7 +29,8 @@ Einträge-Caches (5 Min).
## `offscreen`
**Warum:** In Manifest V3 hat der Service Worker keinen DOM-Zugriff. Zum programmatischen Leeren der
Zwischenablage wird ein kurzlebiges Offscreen-Dokument (Reason `CLIPBOARD`) genutzt.
Zwischenablage wird ein kurzlebiges Offscreen-Dokument (Reason `CLIPBOARD`) genutzt sowohl zum
Bereitlegen eines 2FA-Codes als auch zum anschließenden Leeren.
## `identity`
@ -48,6 +40,10 @@ OpenNIT-Login-Seite und empfängt die Weiterleitung an `https://<extension-id>.c
## Bewusst NICHT angefordert
- **`scripting` / `activeTab`** nicht nötig: Das Content-Script wird über `content_scripts` geladen,
das Ausfüllen aus dem Popup läuft über eine Nachricht an das bereits laufende Script. Der Zugriff auf
den aktiven Tab ist bereits durch `host_permissions` abgedeckt.
- **`tabs`** entfällt: Die aktive Tab-Adresse ist bereits über `host_permissions` verfügbar. Dadurch
erscheint **keine** „Browserverlauf lesen"-Warnung.
- Keine `cookies`, `history`, `webRequest`, `downloads`, `notifications` o. Ä.

17
extension/LICENSE.txt Normal file
View file

@ -0,0 +1,17 @@
OpenNIT Vault Browser-Erweiterung
Copyright (C) 2025 Friederich Loheide
Dieses Programm ist freie Software: Sie koennen es unter den Bedingungen
der GNU Affero General Public License, Version 3, weitergeben und/oder
veraendern.
Die Veroeffentlichung erfolgt in der Hoffnung, dass es nuetzlich ist,
jedoch OHNE JEDE GEWAEHRLEISTUNG - sogar ohne die implizite Gewaehr-
leistung der Marktreife oder der Eignung fuer einen bestimmten Zweck.
Einzelheiten regelt die GNU Affero General Public License.
Lizenztext: https://www.gnu.org/licenses/agpl-3.0.html
Quelltext: https://opennit.de
Der vollstaendige Lizenztext liegt der OpenNIT-Installation als Datei
LICENSE bei und kann ueber die oben genannte Adresse bezogen werden.

View file

@ -3,6 +3,7 @@
"name": "OpenNIT Vault",
"version": "2.4.1",
"description": "OpenNIT Vault Passwort-Manager mit Autofill für Benutzer-, Passwort- und 2FA-Felder direkt im Browser.",
"homepage_url": "https://opennit.de",
"permissions": [
"storage",
"activeTab",

63
extension/urlmatch.js Normal file
View 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;

View file

@ -45,7 +45,7 @@ SICHERHEIT & DATENSCHUTZ
• Passwörter werden erst im Moment der Nutzung abgerufen und nicht dauerhaft gespeichert
EINRICHTUNG
Server-URL eintragen, im OpenNIT-Tresor einen API-Token erzeugen und einfügen fertig.
Server-URL eintragen, auf „Mit OpenNIT anmelden" klicken und den Zugriff bestätigen fertig.
OpenNIT Vault benötigt eine laufende OpenNIT-Instanz.
```
@ -71,7 +71,7 @@ SECURITY & PRIVACY
• Passwords are fetched only at the moment of use and never stored permanently
SETUP
Enter your server URL, generate an API token in the OpenNIT vault, paste it — done.
Enter your server URL, click "Sign in with OpenNIT" and approve access — done.
OpenNIT Vault requires a running OpenNIT instance.
```
@ -93,7 +93,7 @@ Deutsch (primär), Englisch
## Datenschutz-Angaben (Data usage im Dashboard)
- Erhobene Datentypen: **Authentifizierungsinformationen** (API-Token), **Website-Inhalte** nur für
- Erhobene Datentypen: **Authentifizierungsinformationen** (Sitzungstoken), **Website-Inhalte** nur für
Autofill (verlassen den Browser nicht).
- Nicht verkauft/weitergegeben. Nicht für Werbung/Bonität genutzt.
- Verschlüsselte Übertragung (HTTPS).