Skip to content

Releases: leonardocandiani/keyfence

v0.8.4

Choose a tag to compare

@leonardocandiani leonardocandiani released this 29 Sep 14:16

Chave UUID colada sob título ou nome de serviço ("### Moskit Proteauto") passa a ser capturada. Hash hex e linhas que falam de id, pedido, trace ou commit seguem de fora.

v0.8.3 · NOME=valor guarda só o valor

Choose a tag to compare

@leonardocandiani leonardocandiani released this 29 Sep 14:05

Correção: quando o nome da variável continua depois da palavra de credencial (ex.: MOSKIT_API_KEY_PROTEAUTO=), o keyfence guardava a linha inteira. Agora guarda só o valor. Teste novo em test/assign.test.js (26 casos).

v0.8.2 · Sessão já contaminada destrava

Choose a tag to compare

@leonardocandiani leonardocandiani released this 28 Sep 17:03
4bd5854

Complemento da 0.8.1 para sessões que já tinham data pendente: a checagem ignora palavra pendente que seja data, hora ou número formatado, e o registro de cópia de arquivo pendente só vale enquanto o arquivo ainda tem palavra pendente de verdade. Segredo confirmado continua bloqueando em qualquer formato. PR #5.

v0.8.1 · Data não é segredo

Choose a tag to compare

@leonardocandiani leonardocandiani released this 28 Sep 16:56
98590ac

Data, hora, data ISO, porcentagem e número formatado (milhar e decimal) deixam de ser candidatos a segredo. Antes, uma mensagem com janela de dados e a palavra "senha" deixava essas datas presas como pendentes a sessão inteira quando o classificador estava fora do ar, bloqueando git e comandos de rede de qualquer arquivo que as contivesse. O classificador passa a aproveitar resposta parcial, e o job em segundo plano tenta de novo uma vez antes de desistir. PIN só de dígitos e senha com data dentro continuam protegidos. PR #4.

v0.8.0

Choose a tag to compare

@leonardocandiani leonardocandiani released this 28 Sep 12:36
00268c2

Credencial sem rótulo pega pela posição na mensagem (título com o token embaixo, mensagem só com o token, bloco de código, crase, nome: token, palavra de credencial antes). Opção capture.unlabeled (agent|save). Fallback aponta o arquivo que o keyfence usaria. PR #3.

v0.7.1 · Windows and PowerShell

Choose a tag to compare

@leonardocandiani leonardocandiani released this 25 Sep 15:24

keyfence runs on Windows, including sessions where Claude Code uses the PowerShell tool. Thanks to @acosta240182-afk for the work in #1.

Fixed

  • Vault rules match Windows paths (C:\proj\.env, C:/proj/.env), without case sensitivity on Windows. Read and Grep on a .env or an SSH key were allowed there.
  • The PowerShell tool is checked for vault reads: Get-Content, gc, type, cat, Select-String, [IO.File]::ReadAllText and the other readers are denied on a vault file.
  • Copy tracking recognizes Windows paths, so a secret written to a scratch file and sent with curl -d @file is caught there too.
  • Secret files (env files, the registry, the vault and its key file) are restricted to the current user through their NTFS ACL, since Windows ignores the 0600 mode.
  • Atomic file replacement retries briefly when another process holds the file open, which happens on Windows when the hook and a background job touch the same file.

Nothing changes on macOS or Linux.

Not yet on Windows

  • Loading the env file automatically into PowerShell commands (it works for the Bash tool).
  • The vault key in a system store (Windows uses KEYFENCE_VAULT_KEY_FILE).
  • keyfence maintain --install through Task Scheduler.

v0.7.0 · Named by context

Choose a tag to compare

@leonardocandiani leonardocandiani released this 25 Sep 13:38

Credentials are named by what the message says about them, not by a loose word from the sentence.

Added

  • Named by context. When nothing in the value names it (no provider format, no name you wrote, no link), the credential is saved at once under a provisional code, kf/7f3a and KF_7F3A_PASSWORD, and the session goes on. In the background the classifier reads the message with every value masked and answers, for each secret and each word, whether that word names the service it is for. The credential is renamed in the vault, the env file, the registry and the session, and the agent gets the new names with its next tool result. There is no list of words to skip. Measured live on 12 message styles (node test/naming-eval.js): 12 of 12 named right, three runs in a row.
  • The provisional names keep working until the daily maintenance removes them, so a command running during the rename still finds its variable.
  • Without the classifier the name comes from the message's structure (a domain in it) or the project, never from a loose word. A word that is an account the vault already knows for that service makes the capture a rotation of that record.
  • keyfence maintain renames, once each, credentials an older version named from a loose word, when their message is still in the session logs. Only names keyfence generated are renamed; a name you chose is never touched, and an existing name changes only when the context names the service.
  • keyfence maintain repairs credentials an older version saved in pieces (a password cut at a ]): the whole value comes back from the original message, in one field.
  • vault.move gives a credential a new alias, sealing its values again under it; one record can split in two when a message carried credentials of two services.

Fixed

  • .env values are read the way the shell reads them: single quotes with '\'', double quotes with escapes, \$, and inline comments. A password with a single quote came back wrong to the maintenance job, and a key written as \$aact_... was synced to the vault with the backslash.
  • A heredoc body is data in copy tracking: >= and s = ... in a Python heredoc next to a secret no longer turned into a file named = or a variable s, which blocked every later network command. X=$(cat <<EOF) with the value in the body is now tracked as a copy.
  • Commands using ${#NAME} or ${NAME:-x} get the env file loaded like $NAME.
  • An env variable's name in capitals (SIS_ROBSON_PASSWORD) is not read as a secret value.
  • Words with a digit and anything the session protects never go to the classifier in clear when it is asked for a name.

Upgrade

Nothing to do. The next daily keyfence maintain --apply renames and repairs old captures; run keyfence maintain first to see the plan.

v0.6.2 · Code is code again

Choose a tag to compare

@leonardocandiani leonardocandiani released this 25 Sep 12:40

Fixes a regression in 0.6.1: code in files and tool output could be read as a password and hidden from the agent.

Fixed

  • The value boundaries made for typed messages (a password can hold any character) were also applied to code, where quotes, brackets and commas are the language's own syntax. A ternary like 'password' : /TOKEN$/.test(n) or a template literal was flagged and replaced in tool output. Messages and code now have separate grammars: messages keep the 0.6.1 behavior, code is back to the 0.6.0 rule.
  • In code, a password label no longer skips judging the value.

Tests

  • keyfence scans its own source in the test suite and must find nothing.

v0.6.1 · Passwords captured whole

Choose a tag to compare

@leonardocandiani leonardocandiani released this 25 Sep 12:29

A password is captured whole, whatever characters it holds. Before this, a password with ], #, (, ,, ; or a quote in it could be saved in pieces (PASSWORD and PASSWORD_2), and you had to send it again.

Fixed

  • Where a value ends now comes from the message's syntax, never from what the value contains: the closing quote, the end of the line or the next space. On a Label: value line the value is taken exactly as written.
  • Under a password label, any characters are accepted. Only a value that is wholly something else (a $VAR reference, <your-password>, changeme) is left out.
  • The rules and the background classifier use the same boundary, so a password no rule recognizes also reaches the classifier as one word.
  • Placeholder, CLI flag and path checks look at the whole value, not its first characters: my_Dog2024! is a password, my_api_key is an example.
  • What a person types and what a code file contains are judged separately: Senha: joao.silva99 in a message is a password, password: config.db in a file is a reference.

Tests

  • New property test: random passwords with any printable character in any position, in 12 message layouts, must be captured whole; each one is also saved by the hook and loaded back by bash unchanged. The layouts where a reader could not tell either (a ? glued to a value mid-sentence, a value that is wholly a file path) are listed in the test with the reason.

v0.6.0 · Discover credentials on disk

Choose a tag to compare

@leonardocandiani leonardocandiani released this 25 Sep 11:36

Find the credentials already on your disk and bring them under the vault.

Added

  • keyfence discover walks project .env files and export lines in shell rc files, and registers each credential in the vault with every place it lives. One record per service and project, with all its fields. Sources are only read; values are never printed.
  • Values that appear in recent Claude Code session logs are marked exposed and land on the rotation list.
  • A value the vault already holds is attached to its existing record; discover never overwrites a credential.
  • keyfence maintain now runs discover over discover.roots (default ~).
  • keyfence secret show lists found_in, the files and variables each credential came from.

Fixed

  • Piping output to head no longer crashes the CLI, and a closed pipe no longer interrupts an --apply halfway.

Docs

  • README rewritten around the vault, credential records, discover and maintain.