Journal J'ai failli le faire

18
25
nov.
2025

Mais ouf, sauvé, je me suis abstenu d'être pris à l'insu de mon plein gré.

Donc, l'histoire c'est: j'installe un Linux (nickel, no problemo), ajoute uBlock sur FireFox et là je me dis "tiens y'a quoi dans le store ?" et je tombe sur

Grammar and Spell Checker (en 30 langues, c'est louche quand même).

Bon, j'y vais, je clique sur installer ("on verra bien", et puis ça peu franchement servir).

Une image, le temps que ça charge

AI powered

Il y a 14 Mo dans /tmp à présent car il y a eu un message au sujet du super pouvoir de cette app:

Access your data for all websites

The extension could read the content of any web page you visit, as well as data you enter into those web pages, such as usernames and passwords. This is used for password managers, shopping tools, ad blockers, etc.Mais je ne vois pas

Extensions requesting this permission might:

  • Read product and price information from a page to help find you the best price on items
  • Offer a password manager that reads and writes details of your username and password
  • Provide an ad blocker by reading the content of each web page you open to find and remove ad code

Bon, que les frontières entre OS/smartphone/applis/pc/cloud/office365 soient floues, c'est entendu
Pareil pour ces services "AI powered" (ou autres) dits "gratuits", on sait qu'en fait on leur offre tout notre vie privée digitale en contrepartie.

Mais qu'ils s’occupent de mots de passe ou même d'add-blocker , c'est pas un peu pousser mémé dans les orties ?


Extensions requesting this permission might:

  • Update the look of some or all pages within the domain (<= ils vont mettre une feuille de vigne devant les zizis ?)
  • Block content, such as advertising or content using certain tags, from a domain’s content feed

procédure avortée donc, ces 14 Mo auront bientôt disparus de /tmp

  • # DOM

    Posté par  (site web personnel) . Évalué à 1 (+1/-2).

    Ou alors, peut-être le plugin a juste besoin d'accéder au DOM pour faire la traduction directement dans la page, tout comme le gestionnaire de mot de passe a besoin d'accéder au DOM pour remplir les formulaires de connexion ?

    J'en sais rien, j'ai pas encore lu le code source pour savoir si oui ou non ils pompaient de la donnée privée.

    • [^] # Re: DOM

      Posté par  . Évalué à 1 (+0/-0).

      Update the look of some or all pages within the domain

      J’imagine que ça c’est pour mettre le widget dans le coin en bas à droite du champ de texte, plus la popup avec les suggestions.

    • [^] # Re: DOM

      Posté par  (site web personnel) . Évalué à -9 (+2/-13).

      Par manque de temps, j'ai délégué l'analyse au stagiaire transistoré :

      Vue Générale

      • Type d’extension: Correcteur / réécriture linguistique injecté sur toutes les pages (http(s):///, file:///*), via extension-loader.js et CSS associés.
      • Permissions clés: activeTab, storage, contextMenus, scripting, alarms. Portée très large du matching d’URL (toute navigation + fichiers locaux).

      Surface D’Injection

      • Content scripts globaux: Injection sur toutes les pages, y compris documents locaux (), Google Docs/Slides (scripts dédiés), site LanguageTool, et éditeurs riches détectés dynamiquement.
      • Détection d’éditeurs: Analyse d’éléments contentEditable, textarea, certains input (types texte/recherche). Les mots de passe sont exclus (type password non inclus dans la condition).
      • Executor / loader: executor.js permet d’injecter et relier propriétés (value, selectionStart/End…) de wrappers aux vrais champs → accès direct au texte saisi.

      Données Textuelles Collectées / Envoyées

      • Texte complet soumis: Chaînes envoyées aux endpoints de vérification / réécriture: https://api.languagetool.org/v2, fallback, serveurs premium (api.languagetoolplus.com, rewriting server).
      • Modes: Vérification paragraphe / texte, réécriture (paraphrasing), recommandations; envoi de segments + contexte (phrases, offsets).
      • Métadonnées de contexte: textSessionId, instanceId, parfois motherTongue, variantes préférées, niveau (level), règles cachées activées.
      • Email / destinataire: Si disponible recipientInfo.address / recipientInfo.fullName → inclus dans metaData (donc adresses et noms de destinataires peuvent partir aux serveurs). Réécriture: Corps JSON inclut text, userID, language, éventuellement email, token, indicateur premium.
      • Ajout dictionnaire: Endpoint /words/add envoie word + identifiants (username, password ou tokenV2).
      • Feedback / geoIP: Requête init récupère pays & langues probables (IP implicite côté serveur). Campagne / source marketing (cookie _ad_ref, ref_source, user.sessionInfo).
      • Statistiques internes: Tracking performance (durées, nombre d’erreurs), erreurs filtrées, comptage d’erreurs masquées, activité utilisateur (ping intervals), potentiellement santé de l’extension.

      Identifiants et Auth

      • Credentials transmis: username (email), password ou tokenV2 pour fonctions premium / dictionnaire.
      • Tokens / premium flags: En-têtes X-LT-p, X-LT-checksum.
      • UserID explicite dans requêtes de réécriture.

      Stockage Local / Persisté

      • localStorage: Clés génériques ___host_storage (jusqu’à ~1MB). Contient paires {key,value}; absence de chiffrement; possible conservation de textes (ex: validator-text).
      • Session info: user.sessionInfo (source campagne). Cache de préférences langue, état onboarding, textes temporaires.
      • Aucune preuve ici de cryptage ou cycle d’effacement automatisé.

      Limites / Protection Observées

      • Exclusion champs sensibles: Password non traité (condition ne prend que text / search). Pas d’indication explicite d’exclusion pour input[type=email], données financières, formulaires médicaux.
      • Scoping partiel: Focalisation sur zones éditables; pas de balayage global DOM non textuel, mais injection universelle permet lecture potentielle si heuristiques élargies. Minimisation partielle: Découpage par phrases / paragraphes mais texte intégral peut être assemblé par serveur (offsets + segments).
      • Politique externe: Liens vers privacy/terms; aucune validation côté code sur classification sensible du contenu avant envoi.

      Risques de Données Privées

      • Ampleur: Toute rédaction sur le web (emails, documents internes, messagerie web, intranets chargés dans navigateur) peut être transmise.
      • Destinataires Email: Adresse & nom → risques de corrélation sociale / mapping relationnel.
      • Documents locaux (): Texte de fichiers ouverts localement (ex: brouillons html) potentiellement envoyé.
      • Credential leakage surface: Password exclus, mais mots de passe accidentellement tapés dans champs texte normaux (ex: erreurs utilisateur) pourraient être envoyés. PII implicite: Noms propres, adresses, numéros présents dans le texte non filtrés.
      • Rewriting server: Texte envoyé à domaine distinct (rewriting.languagetoolplus.com) – surface supplémentaire.
      • Transport: Usage fetch avec mode:"cors"; dépendance TLS serveur; pas d’indication de redaction locale.

      Ce Qui Ne Semble PAS Être Collecté

      • Historique de navigation complet: Pas de permission history dans manifest.
      • Cookies tiers: Pas d’utilisation explicite pour exfiltration (seulement login flows).
      • Clair stockage systématique des pages entières: Focalisé sur inputs / segments linguistiques.

      Points de Vigilance Technique

      • executor.js injection code: Capacité d’exécuter scripts – s’assurer qu’aucune escalade via événements custom.
      • Shadow DOM / iframes: Large surface; vérifier que détection n’inclut pas champs masqués / scripts de sécurité.
      • Campaign tracking: Documenter clairement finalité (statistiques vs profil marketing). Conclusion

      L’extension collecte et transmet principalement du texte saisi et des métadonnées linguistiques / de compte (email, userID, token, langue maternelle, variantes). Les limites actuelles protègent les champs password mais pas d’autres formes de PII textuelles.
      La combinaison injection universelle + réécriture + destinataire email introduit un risque élevé de fuite de données privées si l’utilisateur rédige du contenu sensible.
      Des mesures de minimisation, filtrage PII, transparence d’envoi, et restriction de portée devraient être priorisées pour réduire l’exposition.

      • [^] # Re: DOM

        Posté par  (site web personnel, Mastodon) . Évalué à 10 (+10/-2). Dernière modification le 26 novembre 2025 à 00:51.

        Par manque de temps, gépalu.

        Si tu fait écrire à une IA parce que t’as pas le temps d’écrire, je ne lirai pas (car c’est le même résultat que de faire lire par une IA).

        ce commentaire est sous licence cc by 4 et précédentes

        • [^] # Re: DOM

          Posté par  . Évalué à 10 (+15/-0).

          Ca ouvre un champ de possibilités immenses. Un article trop long: L'IA le résume. On veut pas lire le résumé? Bah on a qu'a demander à l'IA d'en faire la synthèse. C'est une IA qui a fait la synthèse et on veut pas le lire? On a qu'a demander à l'IA de répondre à notre place. et on veut pas lire la réponse? haha! mais l'IA de notre interlocuteur l'a déjà résumé, synthétisé et commenté. Super!

          Et BAM! place aux nouveaux sites WEB 6.0 (*) ou l'IA est omniprésente, on a même plus besoin de s'y connecter \o/ Gain de temps phénoménal, on aura du coup le temps de discuter avec nos proches. On pourrait faire des plateformes web ou on s'échangerait des messages. Mmmmmh, je sens que tiens un truc là. C'est quand même fantastique ce qu'on fait avec l'IA \o/
          /s

          (*) ou web5.0? je sais plus trop j'ai arrêté de compter à un moment

  • # Mauvaise nouvelle et j'ai l'air c*n

    Posté par  . Évalué à 4 (+4/-0).

    Merci pour la vigilance.

    Mauvaise nouvelle : ça fait très longtemps que j'utilise cette extension. Très pratique, en particulier pour ceux, comme moi, qui écrivent moult fautes et erreurs d'inattention. Et à force de lire, écrire et écouter pas mal d'anglais, sans être véritablement "fluent", il y a un paquet de mots dont l'orthographe est mélangée (exemple : connection …).

    J'ai l'air c*n : dans ma liste de plugins, cet outil est dénommé "AI Grammar Checker & Paraphraser – LanguageTool". Et la plupart du temps, quand je vois "AI" ou "IA", je m'éloigne en courant …

    Je vais essayer de suivre ce journal pour savoir si le risque détecté est bien avéré.

  • # Politiques de confidentialités

    Posté par  . Évalué à 3 (+3/-1).

    Je l’ai installé aussi voyant que c’est suggéré par Mozilla.

    Point positif pour moi, ça support l’espéranto!

    Et puis LanguageTooler GmbH ça a l’air allemand, données en Europe quoi…
    Mais dans les politiques de confidentialités on voit que languagetool.org c’est qu’un nom de domaine utilisé par Learneo, une société basé à San Fransisco, donc toutes les données doivent être envoyées là-bas.

    C’est rigolo le paragraphe pour la Confidentialité des enfants, en gros je lis ça comme si vous avez 13 ans ou moins — voire 16 ans dans l’Espace Économique Européen — merci de ne pas utiliser nos services ou au moins ne pas nous envoyer d’info perso parce qu’on a pas trop le droit enfin voilà quoi.

  • # Extensions requesting this permission **might**

    Posté par  . Évalué à 9 (+7/-0).

    Mais qu'ils s’occupent de mots de passe ou même d'add-blocker , c'est pas un peu pousser mémé dans les orties ?

    C'est une phrase générique qui explique que "les extensions" qui demandent ce type de permissions sont généralement "capable de" faire l'un des exemple cité. En gros de la pédagogie sur l'autorisation que tu es en train de donner (ou non).

    Ça ne veut pas du tout dire que "cette extension" s'occupe de ce type de fonctionnalité, mais que les autorisations qu'on lui donne pourraient servir à ce type de service.

    Il tient ensuite à l'utilisateur de vérifier:

    • que ces permissions sont cohérentes avec le but de l'extension: ici une extension de correction a en effet besoin de lire et écrire sur les pages web où tu comptes l'utiliser.
    • que tu fais confiance aux développeurs pour ne pas entreprendre, avec cette autorisation (plutôt large), d'autres actions moins légitimes.
    • si tu n'as pas une confiance aveugle (sans jugement) dans les développeurs ou le cycle de déploiement de cette extension, que tu aies validé le code avant de le déployer/mettre-à-jour etc. (ce qui n'est pas donné à tout le monde j'en conviens).

    Malheureusement, une fois que tu donnés un accès à la lecture ou la modification du contenu des pages à une extension de ton navigateur, il est ensuite difficile de savoir si celle-ci utilise le contenu pour le but légitime de ses fonctionnalités annoncées. La demande est malgré tout légitime on dirait.

    Et il ne semble pas y avoir d'autorisation plus granulaire non plus permettant de limiter la surface d'exposition.

  • # audit

    Posté par  (site web personnel, Mastodon) . Évalué à 10 (+13/-1).

    C'est un sujet que j’essaye de traiter/implémenter en ce moment en utilisant un script Python.

    A la fin, j'obtiens une note de 0 à 100.

    0 est fiable selon mes critères, non zéro, il faut se poser des questions.

    Le script:

    #!/usr/bin/env python3
    
    import zipfile
    import json
    import re
    import os
    import sys
    from collections import defaultdict
    
    # -----------------------------------------
    # YARA-like malicious patterns
    # -----------------------------------------
    yara_rules = {
        "eval_obfuscation": r"eval\s*\(",
        "function_constructor": r"new Function\s*\(",
        "xhr_suspicious": r"XMLHttpRequest\s*\(",
        "websocket": r"new WebSocket\s*\(",
        "crypto_mining": r"(CoinHive|cryptonight|miner)",
        "tracking_fingerprinting": r"(canvas\.toDataURL|audioContext|mediaDevices\.enumerateDevices)",
        "url_beacon": r"(navigator\.sendBeacon)",
        "shadow_dom_injection": r"(attachShadow)",
        "encoded_payload": r"(atob\(|btoa\()",
        "exfiltration_fetch": r"fetch\s*\([^)]*(http|https):\/\/",
        "suspicious_iframe": r"<iframe[^>]+src="
    }
    
    # -----------------------------------------
    # Sensitive Firefox permissions → explanations
    # -----------------------------------------
    permission_explanations = {
        "tabs": "Access to all browser tabs (privacy sensitive).",
        "cookies": "Can read/write cookies across sites.",
        "webRequest": "Can monitor/modify all network requests.",
        "webRequestBlocking": "Can block and alter network requests (highly sensitive).",
        "history": "Can read browsing history.",
        "downloads": "Full access to all downloads.",
        "nativeMessaging": "Can communicate with external apps (critical).",
        "management": "Can manage extensions (dangerous).",
        "proxy": "Can alter browser network proxy settings.",
        "storage": "Can store arbitrary data (may include tracking identifiers)."
    }
    
    # -----------------------------------------
    # Known tracker domains for filtering endpoints
    # -----------------------------------------
    TRACKERS = ["google-analytics", "doubleclick", "facebook", "fbcdn",
                "hotjar", "mixpanel", "matomo", "segment.io",
                "sentry", "amplitude", "snowplow"]
    
    # -----------------------------------------
    # Utility functions
    # -----------------------------------------
    def detect_minification(content):
        line_lengths = [len(line) for line in content.split("\n")]
        long_lines = sum(1 for l in line_lengths if l > 300)
        ratio = long_lines / max(1, len(line_lengths))
        return ratio > 0.30  # heuristic
    
    def detect_obfuscation(content):
        suspicious = 0
        if re.search(r"[A-Za-z_$]{1,2}\d{3,}", content):
            suspicious += 1
        if re.search(r"function\(\w,\w,\w\)\{", content):
            suspicious += 1
        if re.search(r"while\s*\(\!\!\[\]\)", content):
            suspicious += 1
        return suspicious >= 2
    
    def yara_scan(content):
        matches = []
        for name, pattern in yara_rules.items():
            if re.search(pattern, content, re.IGNORECASE):
                matches.append(name)
        return matches
    
    def extract_urls(content):
        pattern = r"https?://[A-Za-z0-9\.\-_/~\?#=%]+(?=[\s\"\'\)\]\}<>]|$)"
        return re.findall(pattern, content)
    
    def classify_urls(urls):
        classified = {"trackers": [], "api": [], "other": []}
        for u in urls:
            if any(t in u for t in TRACKERS):
                classified["trackers"].append(u)
            elif re.search(r"/api/|/v\d+/|token|auth", u):
                classified["api"].append(u)
            else:
                classified["other"].append(u)
        return classified
    
    # -----------------------------------------
    # Compute global risk score
    # -----------------------------------------
    def compute_risk_score(permissions, minified_files, obfuscated_files, yara_hits, urls):
        score = 0
    
        # Permissions
        if "<all_urls>" in permissions:
            score += 25
        if "webRequest" in permissions:
            score += 10
        if "cookies" in permissions:
            score += 10
        if "history" in permissions:
            score += 10
        if "nativeMessaging" in permissions:
            score += 20
    
        # File metrics
        score += len(minified_files) * 5
        score += len(obfuscated_files) * 10
    
        # YARA hits
        for hits in yara_hits.values():
            score += len(hits) * 10
    
        # URLs
        score += min(len(urls), 10)  # up to 10 points
    
        # Cap at 100
        return min(score, 100)
    
    # -----------------------------------------
    # Main analysis
    # -----------------------------------------
    def analyze_xpi(file_path):
        report = []
        js_files = {}
        urls_found = set()
        yara_hits = defaultdict(list)
        minified_files = []
        obfuscated_files = []
    
        with zipfile.ZipFile(file_path, 'r') as z:
            # -------------------------
            # 1. MANIFEST EXTRACTION
            # -------------------------
            manifest_data = None
            for name in z.namelist():
                if name.endswith("manifest.json"):
                    manifest_data = json.loads(z.read(name).decode("utf-8", errors="ignore"))
                    break
    
            if manifest_data is None:
                report.append("No manifest.json found → invalid extension.")
                return "\n".join(report)
    
            # -------------------------
            # 2. Inspect manifest.json
            # -------------------------
            report.append("=== MANIFEST ANALYSIS ===\n")
    
            # Permissions
            permissions = manifest_data.get("permissions", [])
            host_permissions = manifest_data.get("host_permissions", [])
    
            report.append("Permissions declared:")
            if not permissions:
                report.append("  None")
            else:
                for perm in permissions:
                    explanation = permission_explanations.get(perm, "No specific risk info.")
                    report.append(f"  - {perm}: {explanation}")
    
            report.append("\nHost permissions:")
            if not host_permissions:
                report.append("  None")
            else:
                for host in host_permissions:
                    report.append(f"  - {host}")
    
            # Data collection declaration
            dcp = manifest_data.get("data_collection_permissions", {})
            report.append("\nData collection permissions:")
    
            if dcp:
                report.append(f"  Raw: {json.dumps(dcp, indent=4)}")
                if dcp.get("required") == ["none"]:
                    report.append("  → The extension claims to collect NO DATA.")
            else:
                report.append("  No data collection declaration found.")
    
            report.append("\n")
    
            # -------------------------
            # 3. FILE CONTENT ANALYSIS
            # -------------------------
            report.append("=== FILE ANALYSIS ===\n")
    
            for name in z.namelist():
                if not name.endswith((".js", ".html", ".css")):
                    continue
    
                content = z.read(name).decode("utf-8", errors="ignore")
    
                # JS only
                if name.endswith(".js"):
                    js_files[name] = content
    
                    # Minification detection
                    if detect_minification(content):
                        minified_files.append(name)
    
                    # Obfuscation detection
                    if detect_obfuscation(content):
                        obfuscated_files.append(name)
    
                    # YARA-like scan
                    for hit in yara_scan(content):
                        yara_hits[name].append(hit)
    
                # URL extraction (JS/HTML/CSS)
                for url in extract_urls(content):
                    urls_found.add(url)
    
            # Minified
            report.append("Potentially minified files:")
            if minified_files:
                for f in minified_files:
                    report.append(f"  - {f}")
            else:
                report.append("  None")
            report.append("")
    
            # Obfuscated
            report.append("Potentially obfuscated files:")
            if obfuscated_files:
                for f in obfuscated_files:
                    report.append(f"  - {f}")
            else:
                report.append("  None")
            report.append("")
    
            # YARA hits
            report.append("YARA-like detection results:")
            if yara_hits:
                for f, hits in yara_hits.items():
                    report.append(f"  {f}: {', '.join(hits)}")
            else:
                report.append("  No suspicious patterns detected.")
            report.append("")
    
            # URLs
            classified = classify_urls(urls_found)
            report.append("External endpoints found:")
            for cat, urls in classified.items():
                report.append(f"  {cat.capitalize()}:")
                if urls:
                    for u in urls:
                        report.append(f"    - {u}")
                else:
                    report.append("    None")
            report.append("")
    
            # -------------------------
            # 4. Global risk score
            # -------------------------
            risk_score = compute_risk_score(permissions, minified_files, obfuscated_files, yara_hits, urls_found)
            report.append(f"=== GLOBAL RISK SCORE: {risk_score}/100 ===\n")
    
            # -------------------------
            # 5. Final Privacy Warning
            # -------------------------
            report.append("=== PRIVACY RECOMMENDATION ===")
            report.append(
                "Always disable automatic updates for extensions when conducting security reviews. "
                "Updates may replace safe code with unsafe content without user confirmation."
            )
    
            return "\n".join(report)
    
    if __name__ == "__main__":
        if len(sys.argv) != 2:
            print("Usage: python3 audit_xpi.py extension.xpi")
            sys.exit(1)
    
        filePath = sys.argv[1]
        print(analyze_xpi(filePath))

    Le report me donne pour tampermonkey:

    === MANIFEST ANALYSIS ===
    
    Permissions declared:
      - alarms: No specific risk info.
      - notifications: No specific risk info.
      - tabs: Access to all browser tabs (privacy sensitive).
      - idle: No specific risk info.
      - webNavigation: No specific risk info.
      - webRequest: Can monitor/modify all network requests.
      - webRequestBlocking: Can block and alter network requests (highly sensitive).
      - unlimitedStorage: No specific risk info.
      - storage: Can store arbitrary data (may include tracking identifiers).
      - contextMenus: No specific risk info.
      - clipboardWrite: No specific risk info.
      - cookies: Can read/write cookies across sites.
      - downloads: Full access to all downloads.
      - <all_urls>: No specific risk info.
    
    Host permissions:
      None
    
    Data collection permissions:
      No data collection declaration found.
    
    
    === FILE ANALYSIS ===
    
    Potentially minified files:
      - content.js
      - extension.js
      - page.js
      - editor.js
      - lint.js
      - cache.js
      - background.js
      - vendor/saveas/filesaver.js
      - vendor/eslint/eslint.js
      - vendor/jsdiff/diff.js
    
    Potentially obfuscated files:
      - content.js
      - extension.js
      - editor.js
      - background.js
      - vendor/eslint/eslint.js
    
    YARA-like detection results:
      content.js: shadow_dom_injection, encoded_payload
      extension.js: function_constructor, crypto_mining, suspicious_iframe
      background.js: eval_obfuscation, function_constructor, crypto_mining, encoded_payload
      vendor/eslint/eslint.js: eval_obfuscation, function_constructor, tracking_fingerprinting
    
    External endpoints found:
      Trackers:
        - https://www.facebook.com/tampermonkey
        - https://a.tampermonkey.net/matomo.php
        - https://www.facebook.com/groups/SocialFixerUsersSupport/
        - https://www.facebook.com/fluffbustingpurity
      Api:
        - https://api.dropboxapi.com/2/auth/token/revoke
        - https://cloud-api.yandex.net/v1/disk/
        - https://www.googleapis.com/drive/v3/changes/startPageToken
        - https://www.googleapis.com/auth/drive.appdata
        - https://oauth.yandex.com/authorize
        - https://login.live.com/oauth20_authorize.srf
        - https://www.googleapis.com/drive/v3/files?
        - https://www.googleapis.com/drive/v3/changes/?
        - https://accounts.google.com/o/oauth2/v2/auth
        - https://www.googleapis.com/drive/v3/files/
        - https://www.dropbox.com/oauth2/authorize
        - https://accounts.tampermonkey.net/e/oauth2/v1
      Other:
        - https://eslint.org/docs/rules/no-process-env
        [...] filtered tons of eslint URLs
        - http://coffeescript.org/browser-compiler/coffeescript.js
        - https://eslint.org/docs/rules/no-new-native-nonconstructor
        - https://www.tampermonkey.net/faq#Q406
        - https://github.com/ajv-validator/ajv/blob/master/lib/definition_schema.js
        - https://greasyfork.org/scripts/
        - https://eslint.org/docs/rules/prefer-spread
        - https://eslint.org/docs/rules/no-undef-init
        - http://xkcd.com/970/
        - https://api.dropboxapi.com/2/files/delete
        - https://api.onedrive.com/v1.0/drive/special
        - https://forum.userstyles.org/post/discussion?Discussion/StyleID=
        - http://json-schema.org/draft-07/schema#
        - https://eslint.org/docs/rules/no-negated-condition
        - https://www.tampermonkey.net/privacy.php#extension
        - https://bitbucket.org/
        - https://content.dropboxapi.com/2/files/upload
        - https://github.com/openstyles/stylus
        - http://feross.org
        - https://userstyles.org/styles/
        - http://userscripts.com/
        - https://eslint.org/docs/rules/indent
        - https://eslint.org/docs/rules/require-unicode-regexp
        - http://socialfixer.com
        - http://contactbyweb.com/userscripts-mirror
        - https://github.com/zloirock/core-js/blob/v3.27.2/LICENSE
        - https://github.com/mysticatea
        - https://github.com/zloirock/core-js
        - http://www.w3.org/1999/xhtml
        - http://userscripts-mirror.org/scripts/review/
        - http://www.w3.org/1999/xlink
        - https://raw.githubusercontent.com/ajv-validator/ajv/master/lib/refs/data.json#
        - https://eslint.org/docs/rules/space-before-function-paren
        - https://github.com/eslint/doctrine
        - http://www.w3.org/2000/svg
        - http://tampermonkey.net/
        - https://www.tampermonkey.net/bug
        - https://opencollective.com/eslint
        - https://github.com/narcolepticinsomniac
        - https://www.tampermonkey.net/faq.php#Q204
        - https://www.instagram.com/der_jan_b/
        - http://userscripts-mirror.org/scripts/show/
        - https://www.googleapis.com/
        - https://github.com/estools/esrecurse
        - https://www.google.com/s2/favicons
        - http://json-schema.org/draft-04/schema#
        - https://blacklist.tampermonkey.net/get.php
        - https://www.fbpurity.com/
        - https://www.tampermonkey.net/faq.php#Q500
        - http://tmnk.net/faq#Q208
        - https://api.dropboxapi.com/2/files/list_folder
        - https://www.tampermonkey.net/privacy.php
        - https://www.tampermonkey.net/scripts.php
        - https://www.nczonline.net
        - https://eslint.org/docs/rules/no-multiple-empty-lines
        - https://cdnjs.cloudflare.com/ajax/libs/babel-polyfill/6.16.0/polyfill.js
        - https://www.tampermonkey.net/faq.php?
        - http://userscripts.org/
        - https://icons.duckduckgo.com/ip2/
        - https://github.com/estools/esrecurse.git
        - https://www.tampermonkey.net
        - http://json-schema.org/draft-07/schema
        - https://github.com/Constellation
        - https://gitlab.com/
        - https://vscode.dev/?connectTo=tampermonkey
        - https://api.onedrive.com/v1.0/drive/items/
        - https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.18.2/babel.js
        - http://github.com/garycourt/uri-js
        - https://github.com/derjanb
        - https://notify.dropboxapi.com/2/files/list_folder/longpoll
        - https://www.tampermonkey.net/documentation.php#_connect
        - https://sleazyfork.org/scripts/
        - https://www.tampermonkey.net/qr/
        - https://content.dropboxapi.com/2/files/download
        - https://www.tampermonkey.net/changelog.php?
        - https://openuserjs.org/scripts/
        - https://webdav.yandex.ru
        - https://stuk.github.io/jszip/documentation/howto/read_zip.html
        - https://www.tampermonkey.net/contrib.php?embedded=2
        - http://json-schema.org/schema
        - https://www.tampermonkey.net/installed.php?
        - https://www.tampermonkey.net/faq.php#Q207
    
    === GLOBAL RISK SCORE: 100/100 ===
    
    === PRIVACY RECOMMENDATION ===
    Always disable automatic updates for extensions when conducting security reviews. Updates may replace safe code with unsafe content without user confirmation.
    
    

    On ne peut pas mettre d'array dans le string...

  • # La correction grammaticale fonctionne bien ?

    Posté par  (site web personnel, Mastodon) . Évalué à 10 (+24/-0).

    Je suis en train de voir avec Olivier (dev de Grammalecte) pour reprendre la maintenance de Grammalecte avec Algoo et je suis donc intéressé d'un retour de "performance" de language tool.

    #tracim pour la collaboration d'équipe __ #galae pour la messagerie email __ dirigeant @ algoo

    • [^] # Re: La correction grammaticale fonctionne bien ?

      Posté par  (site web personnel, Mastodon) . Évalué à 10 (+10/-0).

      Language Tools a deux énormes défauts de mon point de vue :

      1. il ne s'occupe pas de l'orthotypographie, qui est pourtant quelque chose de capital,
      2. il est en ligne et ça peut sacrément ralentir ton LibreOffice. C'est pour ça que j'ai laissé tomber.

      Je pense qu'au niveau de la correction orthographique et grammaticales ils sont à peu près au même niveau.

      Quand tu parles de reprendre la maintenance (ce qui serait déjà formidable sachant qu'à chaque mise à jour de LibreOffice, je me demande si Grammalecte va continuer à fonctionner), tu ne parles pas de nouveaux développement j'imagine. Ou bien tu penses pouvoir faire évoluer le logiciel ?

      Je n’ai aucun avis sur systemd

      • [^] # Re: La correction grammaticale fonctionne bien ?

        Posté par  (site web personnel, Mastodon) . Évalué à 10 (+15/-0).

        Quand tu parles de reprendre la maintenance (ce qui serait déjà formidable sachant qu'à chaque mise à jour de LibreOffice, je me demande si Grammalecte va continuer à fonctionner), tu ne parles pas de nouveaux développement j'imagine. Ou bien tu penses pouvoir faire évoluer le logiciel ?

        C'est la question : un client nous a sollicité pour faire des travaux sur Grammalecte. Ce sont des technologies que l'on connait donc on sait faire techniquement.

        Ce que j'envisage, c'est soi "simple maintenance" (correction de bugs, faire en sorte que ça continue de tourner " soit aller plus loin - ajout de fonctionnalités ou autre.

        J'envisage une campagne de financement participatif pour relancer le projet et nous permettre de nous y plonger sérieusement (professionnellement parlant) mais ça dépend aussi de ce qui est attendu de ses utilisateurs, de ce qui pourrait être intéressant comme développements, etc.

        Je suis intéressé par tout retour sur le sujet.

        #tracim pour la collaboration d'équipe __ #galae pour la messagerie email __ dirigeant @ algoo

        • [^] # Re: La correction grammaticale fonctionne bien ?

          Posté par  (site web personnel, Mastodon) . Évalué à 10 (+8/-0).

          Seulement ma façon de voir les choses. Il est possible que je dise des âneries, que j’enfonce des portes ouvertes ou que tu aies pensé à tout ça.

          Précision de vocabulaire : pour moi ici un bug est un problème technique qui impacte le fonctionnement du logiciel, pas quelque chose lié à son dictionnaire par exemple.

          Un logiciel comme Grammalecte ça évolue à plusieurs niveaux :

          • le fonctionnement « technique », donc corrections de bugs du logiciel et vérifications pour qu’il s’intègre toujours bien aux outils pour lesquels il est développé, ça, je comprends que c’est ce que tu envisages de faire,
          • l’ajout de mots nouveaux, c’est important et on ne peut pas faire l’impasse dessus même si Grammalecte a un éditeur lexical qui te permet de faire ton propre lexique ou d’en importer un (termes professionnels par exemple),
          • l’ajout de règles ou la modification de règles de correction, par exemple si j’écris « métre », dans Writer, Grammalecte ne me propose que « maître » quand, dans Firefox, il me propose notamment « mètre », là il y a un truc à corriger, clairement,
          • l’ajout ou la modification de fonctionnalités.

          Je verrais bien mettre à la disposition, sur le site de l’application, une collection de dictionnaires et lexiques professionnels qui rendrait ainsi plus visible la fonctionnalité d’éditeur lexical.

          Mais ça veut dire aussi qu’il faut un endroit où on peut déposer nos remarques qui devront se classer dans un des types de signalement que je viens d’évoquer et en rappelant en ce qui concerne l’ajout ou la modification de règles qu’on doit donner des précisions (en gros la solution, à charge côté développement de l’intégrer).

          Olivier nous avait dit avoir eu une idée qu’il projetait de développer, avant que rien que l’idée de Grammalecte lui donne des boutons. Peut-être pourra-t-il t’en dire un peu plus.

          Pour ma part, dans la mesure de mes moyens, je participerai au financement sans hésiter. Mais si tu as besoin de quelqu’un pour rédiger deux-trois trucs pour Grammalecte, n’hésite pas, je peux offrir du temps et des capacités rédactionnelles.

          Il faudra aussi voir comment modifier la page Grammalecte sur le site des extensions de LibreOffice. Au besoin je peux demander à la personne qui s’occupe de la validation des extensions sur le site.

          Ah, autre chose, je ne sais pas (plus?) comment Grammalecte gère les marques de trucs à corriger. Mais il faudrait sans doute des retours de personnes daltoniennes si c’est Grammalecte qui s’en occupe.

          Et, là c’est une demande de fonctionnalité ou d’amélioration ! Grammalecte propose une fonctionnalité de modification du champ «Auteur». Il faudrait que ça modifie de façon à ce quand on exporte le fichier en EPUB avec l’extension Writer2xhtml cette modification soit bien conservée, ce qui n’est pas le cas. Et l’extension fait un bien meilleur travail que l’export en EPUB de LibreOffice qui a toujours le même vieux bug non corrigé sur les images SVG en prime.

          Je n’ai aucun avis sur systemd

          • [^] # Re: La correction grammaticale fonctionne bien ?

            Posté par  (site web personnel, Mastodon) . Évalué à 2 (+0/-0).

            Merci pour ce long message !

            Effectivement il y a bien une distinction (complémentarité) entre la maintenance « technique » (bugs, fonctionnalités) et la maintenance « linguistique » (je ne sais pas si c'est le terme approprié, mais dans tous les cas, je te rejoins sur ces deux aspects

            Je verrais bien mettre à la disposition, sur le site de l’application, une collection de dictionnaires et lexiques professionnels qui rendrait ainsi plus visible la fonctionnalité d’éditeur lexical.

            Mais ça veut dire aussi qu’il faut un endroit où on peut déposer nos remarques qui devront se classer dans un des types de signalement que je viens d’évoquer et en rappelant en ce qui concerne l’ajout ou la modification de règles qu’on doit donner des précisions (en gros la solution, à charge côté développement de l’intégrer).

            Olivier nous avait dit avoir eu une idée qu’il projetait de développer, avant que rien que l’idée de Grammalecte lui donne des boutons. Peut-être pourra-t-il t’en dire un peu plus.

            Si je reformule le sujet, l'idée est d'avoir une interface de constitution collaborative de dictionnaires/lexiques, c'est bien ça ?

            Il faudra aussi voir comment modifier la page Grammalecte sur le site des extensions de LibreOffice. Au besoin je peux demander à la personne qui s’occupe de la validation des extensions sur le site.

            Je pense qu'Olivier va nous donner l'accès (c'est bien lui qui le gère jusqu'à présent ?)

            Grammalecte propose une fonctionnalité de modification du champ «Auteur». Il faudrait que ça modifie de façon à ce quand on exporte le fichier en EPUB avec l’extension Writer2xhtml cette modification soit bien conservée, ce qui n’est pas le cas.

            Intéressant. Je viens de découvrir la fonctionnalité, j'aurais imaginé qu'elle soit intégrée dans les propriétés du document (ou dit autrement : que sa modification soit proposée dans l'écran d'édition des propriétés du document intégré dans Libreoffice, mais manifestement ça n'y est pas)

            Ah, autre chose, je ne sais pas (plus?) comment Grammalecte gère les marques de trucs à corriger. Mais il faudrait sans doute des retours de personnes daltoniennes si c’est Grammalecte qui s’en occupe.

            Je crois que dans Libreoffice ça reprend l'interface classique (soulignement rouge et vert ondulé selon que c'est une erreur d'orthographe ou de grammaire)

            #tracim pour la collaboration d'équipe __ #galae pour la messagerie email __ dirigeant @ algoo

            • [^] # Re: La correction grammaticale fonctionne bien ?

              Posté par  (Mastodon) . Évalué à 4 (+3/-0).

              'Si je reformule le sujet, l'idée est d'avoir une interface de constitution collaborative de dictionnaires/lexiques, c'est bien ça ?'

              Pour info, avant Grammalecte (dont j'utilise essentiellement l'extension pour LibreOffice), une interface de ce type en ligne (mise en place et animée par Olivier) a existé : Dicollecte. Elle était vraiment super. Sauf erreur de ma part, les données lexicales (ou terminologiques pour la langue spécialisée) qui y étaient ajoutées par les contributeurices (et validées ensuite, d'où une liste de lexies en attente de validation longue comme le bras) ont fourni une partie du matériel 'linguistique' des dictionnaires embarqués avec l'extension Grammalecte (Dictionnaire “Classique”, Dictionnaire “Réforme 1990” et Dictionnaire “Toutes variantes”). Grammalecte a ensuite pris le relais de Dicollecte pour proposer un vérificateur à la fois orthographique et grammatical. Dicollecte a continué d'exister en parallèle, mais Olivier a consacré l'essentiel de son énergie au développement de Grammalecte. L'éditeur lexical de ce dernier reprend peu ou prou les données qu'il fallait saisir dans Dicollecte. À la différence de Dicollecte, l'éditeur lexical n'est pas partagé (c'est l'équivalent d'un dictionnaire utilisateur), même s'il existe la possibilité de l'exporter en .json. Par contre, Olivier prévoyait bien de proposer un 'dictionnaire communautaire' (la boîte de dialogue des options orthographiques de l'extension Grammalecte contient une option 'dictionnaire communautaire' désactivée et décrite comme 'fonctionnalité à venir'). Je crois que sous l'étiquette de 'dictionnaire communautaire', l'objectif d'Olivier était d'intégrer la dimension 'collective' qu'offrait Dicollecte. Par ailleurs, l'idée d'Ysabeau d'intégrer des jargons ou lexiques professionnels est excellente car elle ajouterait une possibilité de filtrage fin que ne permettait pas vraiment Dicollecte (qui, à mon avis, a été conçu à l'origine comme un dictionnaire de langue générale et non de langue spécialisée, mais qui permettait malgré tout de saisir des termes spécialisés vu sa souplesse).

              En tout cas, comme d'autres ici, je suis partant pour une reprise de développement, au-delà de la maintenance nécessaire pour assurer la compatibilité avec LibreOffice (ou autre application utilisant Grammalecte) et prêt à y contribuer (n'étant pas développeur, ce ne serait qu'une contribution financière - à la mesure de mes modestes moyens ;-)

        • [^] # Re: La correction grammaticale fonctionne bien ?

          Posté par  (site web personnel, Mastodon) . Évalué à 5 (+3/-0).

          Je suis super intéressé de soutenir un projet de reprise de Gramalecte.

          Je suis dépendant d’Antidote 8 qui :

          • n’est plus maintenu car la 9 ne fonctionne plus sous Linux
          • est très lourd
          • est propriétaire

          Si je parvenais un jour à remplacer antidote, ne fut-ce que pour la correction, je serais prêt à payer plusieurs dizaines d’euros par an !

          Mes livres CC By-SA : https://ploum.net/livres.html

          • [^] # Re: La correction grammaticale fonctionne bien ?

            Posté par  (site web personnel, Mastodon) . Évalué à 4 (+2/-0).

            Merci pour ce retour !

            Si je parvenais un jour à remplacer antidote, ne fut-ce que pour la correction, je serais prêt à payer plusieurs dizaines d’euros par an !

            Qu'est-ce qui fait que tu pourras utiliser Grammalecte à la place d'Antidot (ou ne pourra pas) ?S'agit-il de qualité des corrections ? De la qualité du dictionnaire ? de Fonctionnalités bugguées ou manquantes ?

            #tracim pour la collaboration d'équipe __ #galae pour la messagerie email __ dirigeant @ algoo

            • [^] # Re: La correction grammaticale fonctionne bien ?

              Posté par  (site web personnel, Mastodon) . Évalué à 3 (+1/-0).

              Tout d’abord, il faut savoir que mon workflow, c’est de travailler sans corrections dans Vim.

              Les corrections ne doivent venir qu’en relecture finale, d’un fichier markdown/gemtext.

              Une fois que je suis prêt à publier un texte, je le lance avec :

              Antidote -f monfichier.md

              J’ai donc une vue nouvelle de mon fichier, avec toutes les fautes possibles. L’interface d’Antidote est pas top mais je m’y suis fait. J’ai tenté avec la ligne de commande de Grammalecte mais j’ai perdu trop de temps à valider mille fois des corrections suggérées avant de me rendre compte que ce n’était pas sauvé dans le fichier.

              Ce qu’Antidote me permet :

              1. Voir toutes les fautes identifiées avec une suggestion de correction accessible en un clic.

              2. Corrections orthographiques, grammaticales et typographiques.

              3. Corrections automatiques en Anglais ou en Français (les deux langues que j’utilise)

              Accessoirement, j’utilise beaucoup les fonctions dictionnaire/synonyme/antonyme parce qu’accessible hors-ligne mais ce n’est clairement pas le focus de Grammalecte.

              Que les choses soient claires : je ne demande pas de remplacer totalement Antidote. Je suis prêt à payer pour soutenir le projet juste si je me rends compte que je peux l’intégrer dans mon workflow. Et il ne manque pas grand chose je crois. Une ligne de commande qui vérifie un texte, me propose des suggestions à appliquer ou non (en retenant que j’ai dit non si je repasse sur le texte), je crois que ce serait déjà un super chouette outil.

              Je suis de tout cœur avec cette reprise du projet.

              Mes livres CC By-SA : https://ploum.net/livres.html

  • # A noter que le serveur distant peut être auto-hébergé

    Posté par  (Mastodon) . Évalué à 10 (+13/-0).

    Juste pour ajouter que, oui, par défaut le texte est envoyé à un site distant pour analyse.

    MAIS, fait notable, cette extension est l'une des rares à permettre d'auto-héberger le serveur d'analyse et de configurer l'extension pour utiliser l'endpoint de son choix. C'est ce que je fais depuis des années, avec donc tout le texte envoyé sur mon serveur perso qui fait tourner LanguageTool dans un container docker.

    Configuration

Envoyer un commentaire

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.