feat(browser): clean_chrome_profile_extensions + fix policy backup en managed/

Rediseño de apply_chromium_extension_policy y nueva función de purga in-place,
tras resolver por qué las extensiones bloqueadas reaparecían en Chromium 148.

- apply_chromium_extension_policy: añade --block (ExtensionInstallBlocklist).
  Reemplaza el modo ExtensionSettings "*": blocked (que rompía las extensiones
  unpacked vía --load-extension, p.ej. la de captura de web_proxy con el error
  'Loading of unpacked extensions is disabled by the administrator') por una
  blocklist específica. FIX RAÍZ: los backups se guardan fuera de policies/managed/
  (en policy-backups/), porque Chromium lee TODOS los archivos del directorio
  managed/ sin filtrar extensión de nombre — un extensions.json.bak ahí se mergea
  con la policy y reinyecta las extensiones del backup (location=7).
- clean_chrome_profile_extensions (nueva): purga in-place de un perfil existente
  (borra carpetas de Extensions/ + refs en Preferences/Secure Preferences) dejando
  solo la whitelist. Complementa la policy: la policy evita reinstalación, esta
  desinstala lo ya presente. Requiere chromium cerrado.

Ambas: dominio browser, grupo navegator, guard de auto-ejecución, dry-run.
This commit is contained in:
Egutierrez
2026-06-05 17:13:49 +02:00
parent 830f2d34de
commit e0fad0e82f
4 changed files with 450 additions and 50 deletions
@@ -0,0 +1,84 @@
---
name: clean_chrome_profile_extensions
kind: function
lang: bash
domain: browser
version: "1.0.0"
purity: impure
signature: "clean_chrome_profile_extensions [--user-data-dir <dir>] [--profile-directory <name>] [--keep <ext_id>]... [--dry-run]"
description: "Purga in-place las extensiones de un perfil Chrome/Chromium existente que no estén en la whitelist --keep: borra sus carpetas de disco y elimina sus referencias de Preferences y Secure Preferences para que Chromium no las reinstale. Complementaria a apply_chromium_extension_policy_bash_browser que evita reinstalación pero no desinstala lo ya instalado en Chromium 148."
tags: [navegator, chromium, extensions, profile, cleanup, browser, scraping]
uses_functions: [apply_chromium_extension_policy_bash_browser]
uses_types: []
returns: []
returns_optional: false
error_type: "error_go_core"
imports: []
tested: false
tests: []
test_file_path: ""
file_path: "bash/functions/browser/clean_chrome_profile_extensions.sh"
params:
- name: --user-data-dir
desc: "Ruta raíz del user-data-dir de Chrome/Chromium. Default: ~/.config/chromium"
- name: --profile-directory
desc: "Nombre del subperfil dentro de user-data-dir. Default: Default"
- name: --keep
desc: "ID de extensión Chrome a conservar (repetible, 32 chars minúsculas). Si no se pasa ninguno el default es ddkjiahejlhfcafbddmgiahcphecmpfh (uBlock Origin Lite)"
- name: --dry-run
desc: "Muestra qué IDs se conservarían y cuáles se borrarían sin tocar disco ni archivos de preferencias"
output: "JSON en stdout: {profile: \"<path>\", kept: [id...], removed: [id...]}. Exit 0 en éxito o dry-run. Errores a stderr con exit != 0."
---
## Ejemplo
```bash
# Cerrar Chromium primero (OBLIGATORIO en modo real)
pkill -TERM chromium
# Purgar perfil Default dejando solo uBlock Origin Lite
source $HOME/fn_registry/bash/functions/browser/clean_chrome_profile_extensions.sh
clean_chrome_profile_extensions --keep ddkjiahejlhfcafbddmgiahcphecmpfh
# Previsualizar antes de tocar nada
clean_chrome_profile_extensions --keep ddkjiahejlhfcafbddmgiahcphecmpfh --dry-run
# Perfil no-default con whitelist de dos extensiones
clean_chrome_profile_extensions \
--user-data-dir "$HOME/.config/chromium" \
--profile-directory "Profile 1" \
--keep ddkjiahejlhfcafbddmgiahcphecmpfh \
--keep cjpalhdlnbpafiamejdnhcphjbkeiagm
# Salida esperada (ejemplo):
# {"profile":"/home/enmanuel/.config/chromium/Default","kept":["ddkjiahejlhfcafbddmgiahcphecmpfh"],"removed":["dark-reader-id","another-ext-id"]}
```
También ejecutable directamente con `fn run`:
```bash
cd $HOME/fn_registry
./fn run clean_chrome_profile_extensions_bash_browser -- --dry-run
```
## Cuando usarla
Úsala después de reducir la whitelist de extensiones con `apply_chromium_extension_policy_bash_browser` (modo `blocked`), para quitar del disco las que ya estaban instaladas en el perfil: la policy evita que Chromium reinstale extensiones nuevas, pero en Chromium 148 no desinstala las que ya estaban force-instaladas. Esta función hace la purga determinista del estado existente. También útil antes de una sesión de scraping para dejar el perfil con solo las extensiones necesarias.
## Gotchas
- **Chromium DEBE estar cerrado** antes de ejecutar en modo real. Chromium reescribe `Preferences` desde memoria al cerrar y desharía toda la purga. La función lo comprueba con `pgrep -x chromium` y aborta con exit 2 si hay procesos vivos. En `--dry-run` no se hace este check.
- **Combínala con `apply_chromium_extension_policy_bash_browser` (blocked)** para que las extensiones no vuelvan a instalarse la próxima vez que arranques Chromium. Esta función purga el estado actual; la policy evita la reinstalación futura.
- **Backup automático de prefs**: antes de editar `Preferences` y `Secure Preferences` la función crea `<archivo>.bak.YYYYMMDD`. Si ya existe un backup del día no lo sobreescribe. En caso de problemas: `cp Preferences.bak.YYYYMMDD Preferences`.
- **Opera por perfil**: actúa sobre `--user-data-dir`/`--profile-directory`/Extensions. Si tienes varios perfiles (`Default`, `Profile 1`, etc.) debes invocarla una vez por cada uno.
- **python3 > jq > warn**: para editar el JSON de Preferences usa python3 si está disponible, jq como fallback, y emite un warning a stderr (sin abortar) si ninguno está. En ese caso las carpetas sí se borran pero las referencias en Preferences quedan — Chromium podría intentar reinstalar desde Web Store.
- **Secure Preferences HMAC**: la tabla `protection.macs.extensions.settings` también se limpia para evitar que Chromium detecte inconsistencia entre el HMAC y la entrada eliminada y resetee configuraciones. Si la HMAC falla de todas formas, Chromium lo trata como perfil potencialmente corrupto y puede resetear algunas prefs — comportamiento esperado de Chromium, no un bug de esta función.
## Exit codes
| Código | Significado |
|--------|------------|
| 0 | Éxito o dry-run completado |
| 1 | Argumento inválido o perfil no encontrado |
| 2 | Chromium está corriendo (solo en modo real) |
| 3 | Directorio Extensions no encontrado |