Documentation
¶
Overview ¶
Package redact removes secrets and e-mail addresses from text before it is shown, stored or sent to a model provider.
Everything goes through one goredact engine: the balanced built-in rule set plus a custom rule for e-mail addresses. Spans are masked in place with a format-preserving mask, so a masked value keeps its length and shape and the text around it stays valid. Newlines a mask would overwrite are put back, so line numbers in a patch survive a secret that spans lines.
Index ¶
- Constants
- Variables
- func Identities(text string) (string, bool)
- func StripMentions(text string) (string, int)
- type Engine
- func (e *Engine) FindContext(ctx context.Context, text string) ([]Span, error)
- func (e *Engine) Profile() string
- func (e *Engine) Redact(text string) (string, Summary, error)
- func (e *Engine) RedactContext(ctx context.Context, text string) (string, Summary, error)
- func (e *Engine) RedactJSON(ctx context.Context, data []byte) ([]byte, Summary, error)
- func (e *Engine) RedactReader(ctx context.Context, dst io.Writer, src io.Reader) (Summary, error)
- type Memo
- type Span
- type Summary
Constants ¶
const EmailRuleID = "email-address"
EmailRuleID is the id the e-mail rule reports its findings under.
Variables ¶
var Config = goredact.Config{ Profile: goredact.ProfileBalanced, MaskStrategy: goredact.MaskFormatPreserving, RecordAligned: true, CustomRules: []goredact.CustomRule{emailRule}, }
Config is how every byte baum redacts is redacted. RecordAligned keeps emitted output on newline boundaries so JSONL streams stay whole records.
Functions ¶
func Identities ¶
Identities removes what must never be published in text sent to a code host: an email address, replaced with "[redacted]", and an @mention, which would notify someone on every edit. The mention keeps its text and loses only the "@", which reads naturally and cannot ping. It reports whether anything was changed.
func StripMentions ¶
StripMentions turns @-mentions into plain names and returns how many it rewrote. It cannot tell a person from an annotation such as @Override, so apply it only to text known to be conversation, never to anything that may hold code.
Types ¶
type Engine ¶
type Engine struct {
// contains filtered or unexported fields
}
Engine redacts with Config as it was when the engine was made. It is immutable and safe for concurrent use, so one engine serves the whole process (Shared).
func New ¶
New compiles the redaction rules. Most callers want Shared, which compiles them once for the process.
func Shared ¶ added in v0.2.0
Shared returns the process-wide engine, compiling it on first use and again only once Config has changed: an engine compiles up to one finder per CPU, far more work than masking most texts.
func (*Engine) FindContext ¶
FindContext returns, in input order, the spans RedactContext masks in text, one per finding: two secrets side by side are two spans however little lies between them. An e-mail address is reported in full, and may also be reported as the rule's window saw it. A value that is already masked, behind "Bearer", "--password=" or "user:", is no finding. It stops with ctx's error if ctx ends first.
func (*Engine) RedactContext ¶
RedactContext masks every secret and e-mail address in text, stopping with ctx's error if ctx ends first. The result has the same length and the same lines as the input: secrets are found over the whole text, so a key spanning several lines is caught, and the newlines the mask overwrote are put back. An e-mail address is masked in full however long it is.
func (*Engine) RedactJSON ¶
RedactJSON masks the secrets and e-mail addresses in data, a JSON text, and returns valid JSON of the same shape whenever data is valid.
It finds them two ways and masks the union:
- over the encoded text as a whole, as RedactContext would, so a key and its value in separate strings ("password": "…") are caught together;
- over every string value and object key as decoded, so a rule anchored at the start of a line still fires after an escaped newline or tab (a tool's output holding an env file). These are scanned together, one string per line, in one pass.
Only the characters of strings are ever masked: never a quote, an escape's backslash, or anything between strings. A string with something masked is written again as JSON, with no HTML escaping; any other is left byte for byte as it was. The Summary adds up the findings of both passes, so a secret may be counted twice.
func (*Engine) RedactReader ¶
RedactReader streams src to dst with every secret and e-mail address masked. The stream is otherwise byte for byte the input. An address with more than 254 bytes on one side of its @ is masked only within those 254 bytes; Redact and RedactContext mask it in full. A stream is not held, so its Summary also counts a value that was already masked, which Redact leaves out.
type Memo ¶ added in v0.2.0
type Memo struct {
// contains filtered or unexported fields
}
Memo remembers what texts masked to, so a text masked again unchanged, such as a running session's title every second, is not scanned again. It holds masked text only: an entry is found by a salted SHA-256 of its input, never by the input itself. It keeps at most maxEntries entries and maxBytes bytes of masked text, dropping the least recently used, and does not keep a text over a quarter of maxBytes. It forgets everything when it is asked with an engine of other rules, so a change of rules takes effect on the next call. It is safe for concurrent use; a nil Memo remembers nothing.
type Span ¶
Span is the byte offsets [Start, End) of one secret or address the engine masks; Email marks an address.