feat(episode): TRAZA_checkpoint-antes-de-tocar-el-hook-paso_S20260518.R31_XX.ops.2.hot_inf.in.cc.es.000.MGQ_J.PMCFK_E.SGNFD
Skill: AEGIS | Type: troubleshooting Summary: EPISODIO 31 — HANDOFF_PROMPT.md: Checkpoint — antes de tocar el hook (paso 6)
This commit is contained in:
parent
f5741e88a4
commit
b222c896b3
1 changed files with 46 additions and 0 deletions
|
|
@ -0,0 +1,46 @@
|
|||
---
|
||||
episode_id: "59b5a5cf-9efe-41f0-a911-e9c4b8ddf0a2"
|
||||
puente_flat: "TRAZA_checkpoint-antes-de-tocar-el-hook-paso_S20260518.R31_XX.ops.2.hot_inf.in.cc.es.000.MGQ_J.PMCFK_E.SGNFD"
|
||||
session_code: "S20260518.PIPELINE_FIXES"
|
||||
acto_dialogico: "informar"
|
||||
actor_flujo: "multi_actor"
|
||||
criticidad_aegis: "low"
|
||||
skill_dominante: "AEGIS"
|
||||
fase_proyecto: "operations"
|
||||
tipo_semantico: "troubleshooting"
|
||||
summary_one_line: "EPISODIO 31 — HANDOFF_PROMPT.md: Checkpoint — antes de tocar el hook (paso 6)"
|
||||
source_type: "claude_code"
|
||||
trust_boundary: "internal"
|
||||
created_at: "2026-05-20T01:03:11.643827+00:00"
|
||||
relectura_tagged: false
|
||||
forgejo_commit_sha: "pending"
|
||||
---
|
||||
|
||||
Paso 5 — **verde**. Fase 5 pasos 1-5 completos.
|
||||
|
||||
## Checkpoint — antes de tocar el hook (paso 6)
|
||||
|
||||
**Lo que está construido y probado** (todo aislado — `mega-hook-ssh.py` sigue intacto):
|
||||
|
||||
| Artefacto | Estado |
|
||||
|---|---|
|
||||
| `docs/HALLAZGO_SSH_HOOK_QUOTE_BYPASS_S20260518.md` | spec del fix |
|
||||
| `policies/` — modelo + 2 CSV | constitución declarativa (13 patrones) |
|
||||
| `casbin-poc/casbin_ssh_authz.py` | motor corregido — extrae el payload, decide vía Casbin |
|
||||
| `casbin-poc/test_casbin_ssh_authz.py` | 217 verificaciones + 7 tests pytest, todos verdes |
|
||||
|
||||
Los tests prueban contra el comportamiento **correcto**: los 3 casos que el hook roto permite hoy (`rm -rf`, `git push --force`, `docker prune` en forma `ssh "..."`) ahora dan `deny`; el caso#4 (`sed` que menciona `rm`) da `warn`, sin over-trigger.
|
||||
|
||||
**Lo que hace el paso 6** — la integración al hook vivo:
|
||||
- Mover `casbin_ssh_authz.py` a su hogar de producción `.claude/hooks/lib/`.
|
||||
- En `mega-hook-ssh.py`: reemplazar las secciones DESTRUCTIVE + MODIFY (L133-191) y la función `_is_inside_quotes` por una llamada a `evaluate(command, enabled_rules)`.
|
||||
- **Conservar** todo lo demás del hook: SSH-scope gate, override flag, `ssh_mode` (BLOCK/WARN/OFF), toggles de config (pasados como `enabled_rules`), logging, formato de salida JSON.
|
||||
- Backup `.bak` previo. Paso 7: re-correr el sondeo sobre el hook integrado para verificar in-vivo.
|
||||
|
||||
**Disclosures honestas (PROCEDENCIA):**
|
||||
- El hueco de seguridad **sigue abierto en el hook vivo** hasta que el paso 6 integre el fix. La lógica está probada; la integración se verifica en el paso 7.
|
||||
- Limitación residual 1: `psql -c 'DROP TABLE'` — destructivo dentro de una comilla que ejecuta — sigue `allow` (pre-existente, no regresión, documentado).
|
||||
- Limitación residual 2 (la hallé al escribir los tests): la forma **sin comillas** `ssh cx43 sed -i 's/rm -rf/x/' f` da `deny` (falso positivo) — el shell local quita las comillas y deja `rm -rf` suelto. Es fail-closed (molesto, no peligroso); la forma con comillas funciona bien. La añado a la sec. 6 del doc.
|
||||
- Capa C (mutation testing con mutmut) — declarada pendiente; no ejecutada.
|
||||
|
||||
**Reframe:** la lógica del fix está probada en aislamiento; lo que resta es el cableado al hook vivo. El riesgo pasa de "¿es correcta la lógica?" (resuelto: verde) a "¿la integración preserva las demás responsabilidades del hook?" — y eso lo verifica el paso 7. Es reversible (backup + `git checkout`).
|
||||
Loading…
Reference in a new issue