From 007599e5f90df1d838a8ba16013bb1430a5f5571 Mon Sep 17 00:00:00 2001 From: Leonardo Candiani Date: Fri, 16 Oct 2026 15:26:54 -0300 Subject: [PATCH] fix(forms): id de evento do monitor com hash do contrato deixa de ser candidato a segredo --- src/forms.js | 6 ++++++ test/travas.test.js | 11 +++++++++++ 2 files changed, 17 insertions(+) diff --git a/src/forms.js b/src/forms.js index a3aa8ab..9e7f6ff 100644 --- a/src/forms.js +++ b/src/forms.js @@ -79,6 +79,11 @@ const isMessageId = (w) => /^3EB0[0-9A-F]{16,28}$/.test(w); // prefix that sessions quote to name a value without showing it. Too short to be a key. const isShortHash = (w) => /^(?=[a-f]*\d)(?=\d*[a-f])[0-9a-f]{7,12}$/.test(w); +// The reference a monitor event carries after `ref:`: an id of 6 to 12 lowercase letters and +// digits, a hyphen and the 64-hex hash of the event contract (`hn9abcdefg-<64 hex>`). It names +// an event; it opens nothing. A provider prefix (`sk-`, `ghp_`...) is judged before this form. +const isEventRef = (w) => /^[a-z0-9]{6,12}-[0-9a-f]{64}$/.test(w) && /[a-z]/.test(w.split('-')[0]); + // A reference to a variable, not its value: `$NOME`, `${NOME}`, a grep anchor `^NOME=`, // an assignment with nothing after the sign `NOME=`. Only when the name is made of words // UPPER_SNAKE or lower_snake words (the way variables are named), so a password that @@ -102,6 +107,7 @@ function commonForm(w) { if (FORMATTED(s)) return 'formatted'; if (isEmail(s)) return 'email'; if (isMessageId(s)) return 'id'; + if (isEventRef(s)) return 'eventref'; if (isShortHash(s)) return 'hash'; if (isFileName(s)) return 'file'; if (isPath(s)) return 'path'; diff --git a/test/travas.test.js b/test/travas.test.js index 09c8852..566baa3 100644 --- a/test/travas.test.js +++ b/test/travas.test.js @@ -63,6 +63,17 @@ const cfgWrite = (jev) => fs.writeFileSync(cfgFile, JSON.stringify({ promptMode: (async () => { cfgWrite({ enabled: false }); + // ref: do monitor (id do evento + hash de 64 hex do contrato) não é segredo + const H64 = 'a1b2c3d4e5f60718293a4b5c6d7e8f90a1b2c3d4e5f60718293a4b5c6d7e8f90'; + for (const ref of [`hn9abcdefg-${H64}`, `hn0xqrstuv-${H64}`, `evt12345ab-${H64}`]) { + check(`id de evento com hash do contrato é forma comum (${ref.slice(0, 12)}...)`, commonForm(ref), 'eventref'); + check(`id de evento com hash do contrato não é forma forte (${ref.slice(0, 12)}...)`, strongShape(ref), false); + check(`id de evento não vai ao classificador (${ref.slice(0, 12)}...)`, candidatesOf(`resumo do monitor ref: ${ref} fim`).length, 0); + } + check('prefixo de provedor com 64 hex continua forte', strongShape(`sk-${H64}`), true); + check('64 hex puro continua forte', strongShape(H64), true); + check('prefixo curto demais com 64 hex continua forte', strongShape(`ab-${H64}`), true); + // referência a variável e âncora de grep não são valor for (const ref of ['$OUTRO_SEGREDO_X', '${OUTRO_SEGREDO_X}', '^MINHA_CHAVE_API=', 'MINHA_CHAVE_API=', '$HOME', '^app_secret_key=']) { check(`referência a variável é forma comum (${ref})`, commonForm(ref), 'varref');