redact

package
v0.2.0-rc.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 12, 2026 License: MIT Imports: 17 Imported by: 0

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

View Source
const EmailRuleID = "email-address"

EmailRuleID is the id the e-mail rule reports its findings under.

Variables

View Source
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

func Identities(text string) (string, bool)

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

func StripMentions(text string) (string, int)

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

func New() (*Engine, error)

New compiles the redaction rules. Most callers want Shared, which compiles them once for the process.

func Shared added in v0.2.0

func Shared() (*Engine, error)

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

func (e *Engine) FindContext(ctx context.Context, text string) ([]Span, error)

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) Profile

func (e *Engine) Profile() string

Profile describes the configuration for a document's generator notes.

func (*Engine) Redact

func (e *Engine) Redact(text string) (string, Summary, error)

Redact is RedactContext without cancellation.

func (*Engine) RedactContext

func (e *Engine) RedactContext(ctx context.Context, text string) (string, Summary, error)

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

func (e *Engine) RedactJSON(ctx context.Context, data []byte) ([]byte, Summary, error)

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

func (e *Engine) RedactReader(ctx context.Context, dst io.Writer, src io.Reader) (Summary, error)

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.

func NewMemo added in v0.2.0

func NewMemo(maxEntries, maxBytes int) *Memo

NewMemo returns an empty memo of at most maxEntries entries and maxBytes bytes of masked text.

func (*Memo) Len added in v0.2.0

func (m *Memo) Len() int

Len is the number of texts remembered.

func (*Memo) Redact added in v0.2.0

func (m *Memo) Redact(ctx context.Context, engine *Engine, text string) (string, error)

Redact returns text as engine.RedactContext masks it. On an error it returns "" with the error and remembers nothing.

type Span

type Span struct {
	Start, End int
	Email      bool
}

Span is the byte offsets [Start, End) of one secret or address the engine masks; Email marks an address.

type Summary

type Summary struct {
	// Findings is the number of spans masked, ByRule the same split by rule
	// id; e-mail addresses are under EmailRuleID.
	Findings int
	ByRule   map[string]int
}

Summary counts what one redaction masked.

func (*Summary) Add

func (s *Summary) Add(other Summary)

Add folds other into s.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL