Skip to content

feat(core): secret detection module for the privacy filter (#1464, part 1) - #1491

Merged
ajianaz merged 1 commit into
developfrom
feat/privacy-redaction-detector
Oct 16, 2026
Merged

ajianaz merged 1 commit into
developfrom
feat/privacy-redaction-detector

Conversation

@ajianaz

@ajianaz ajianaz commented Oct 16, 2026

Copy link
Copy Markdown
Collaborator

What

Part 1 of the privacy filter (#1464): the detection module only. uteke_core::privacy::redact(text, allowlist) finds common secret shapes and masks the secret part, keeping the shape, and reports what it removed (a kind and a count, never the value):

Kind Example result
github-token ghp_[REDACTED:github-token] (also github_pat_)
aws-access-key AKIA[REDACTED:aws-access-key]
api-key sk-[REDACTED:api-key]
bearer-token Bearer [REDACTED:bearer-token]
jwt [REDACTED:jwt]
private-key the whole PEM block becomes [REDACTED:private-key]
env-secret API_KEY=[REDACTED:env-secret], also "client_secret": "..." and auth_token: ...

The generic NAME=value rule needs a secret-like name (key, token, secret, password, pwd), a value of at least 16 characters with Shannon entropy of at least 3.0, and a terminator that is not ( or [. It ignores 40/64-digit hex hashes, UUIDs, paths, URLs, ${VAR} references, placeholders (your, example, changeme, ...), identifier-like values (config.embedding.api_key, VAULT_API_KEY_NAME) and already-masked text. compile_allowlist turns the [privacy] allowlist regexes into a filter that keeps a matching value. redact is idempotent. regex becomes a direct dependency of uteke-core; it was already in the graph through tokenizers (same 1.13.1).

Nothing calls it yet. Part 2 wires it into remember, room remember, import and update, behind [privacy] mode (default redact, strict, off), with metadata.redacted, the audit event and the redacted response field. Part 2 waits for the cloud contract answer (uteke-cloud#218); part 3 is config reference and safety docs.

Why

A secret pasted into one remember is persisted, embedded, indexed and returned by recall forever. Because the filter will run by default, this part is about precision: a pattern is only here when its shape rarely hits ordinary text.

Testing

  • 11 unit tests: true positives per pattern with exact output, 14 false-positive inputs that must stay untouched, allowlist, per-kind counts, idempotence, and a check that no secret value survives in the output. Fake secrets are assembled at run time, so the repository holds no string a secret scanner would flag.
  • Corpus check (throwaway test, not committed): run over the 212 text files of this repository, the first version produced dozens of false positives on Rust code (api_key: self.api_key.clone(), let key = self.make_key(...)), which is why a value must now end at a plain terminator and identifier-like values are ignored; the final version redacts nothing (the one hit was this file's own fixture, now built at run time).
  • Mutation checks, then reverted: removing the entropy gate fails the false-positive test (TOKEN=aaaaaaaaaaaaaaaaaaaaaaaa), and a GitHub pattern that never matches fails three tests.
  • cargo clippy --workspace --all-targets -D warnings is clean; the slim build --no-default-features --features "onnx,vecq" compiles.

@github-actions

Copy link
Copy Markdown

🔍 Cora AI Code Review

✅ No issues found. Code looks good!


Review powered by cora-code · BYOK · MIT

@ajianaz
ajianaz merged commit ded4dd3 into develop Oct 16, 2026
15 checks passed
@ajianaz
ajianaz deleted the feat/privacy-redaction-detector branch October 16, 2026 06:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant