Documentation
¶
Overview ¶
Package redact masks what this server prints for a person and must not survive being pasted somewhere else, and the secrets a job log can carry.
`status` and `doctor` print for a human, and the bug form asks for their output. An instance's host names an organization, a project path names its work, and a username or an address names a person. GitLab's error text and a request URL carry all of them by routes nobody chose. They are masked here, in one place, where the text is produced — not in a Writer, which could see an address split across two writes and miss it — so a print added later is safe without its author knowing the rule.
Index ¶
- Constants
- func Addresses(s string) string
- func ClientID(s string) string
- func Clip(s string, n int) string
- func Email(addr string) string
- func ID(id string) string
- func IsCertificateError(err error) bool
- func MaskSecrets(text string) (string, int)
- func NetError(err error) string
- func Text(s string) string
- func Tokens(s string) string
- func Truncate(s string, n int) string
- func URL(raw string) string
- func URLs(s string) string
- type Masker
Constants ¶
const ( // TokenPattern is every token shape GitLab documents, from the token // prefix table at https://docs.gitlab.com/security/tokens/ (read // 2026-09-26): personal, project, group and impersonation tokens // (glpat-), OAuth application secrets (gloas-), deploy tokens // (gldt-), runner authentication tokens (glrt-, glrtr-), CI/CD job // tokens (glcbt-), trigger tokens (glptt-), feed tokens (glft-), // incoming mail tokens (glimt-), agent for Kubernetes tokens // (glagent-), workspace tokens (glwt-), SCIM tokens (glsoat-), // feature flag client tokens (glffct-) and the session cookie // (_gitlab_session=). The legacy runner registration token prefix // GR1348941 is on GitLab's runner pages rather than that table. // // The body takes dots, because a routable token carries dotted // segments after the random part; a trailing sentence period is left // alone. An instance can change the personal access token prefix, // and a token with a custom prefix has no shape to find. TokenPattern = `\b(?:glpat|gloas|gldt|glrtr|glrt|glcbt|glptt|glft|glimt|glagent|glwt|glsoat|glffct)-[0-9A-Za-z_\-]{20,}(?:\.[0-9A-Za-z_\-]+)*` + `|\bGR1348941[0-9A-Za-z_\-]{20,}` + `|_gitlab_session=[0-9A-Za-z]+` // AddressPattern is an email address in free text. The local part // takes "…", so an address already masked here is matched whole and // masked to the same thing again rather than half of it surviving. AddressPattern = `[A-Za-z0-9._%+\-=…]+@[A-Za-z0-9.\-…]+\.[A-Za-z]{2,}` // ClientIDPattern is an OAuth application id as GitLab shows it: 64 // lowercase hex characters. A SHA-1 commit id is 40 and is left // alone; a SHA-256 one would be masked, which is the safe direction. ClientIDPattern = `\b[0-9a-f]{64}\b` // URLPattern is an http or https URL in free text. URLPattern = `https?://[^\s"'<>()\[\]{}]+` )
The shapes this package masks, as pattern text so the maintainer tooling under scripts/ matches the same ones.
const ( KindToken = "token" KindHost = "host" KindPath = "path" KindQuery = "query" KindUser = "user" KindEmail = "email" KindClientID = "client-id" // KindID is a numeric id; it is matched as a whole number, even // inside a longer name. KindID = "id" )
Kinds of value, as a Masker's placeholders name them.
Variables ¶
This section is empty.
Functions ¶
func Clip ¶
Clip masks s with Text and then truncates it with Truncate. In that order: truncating first can cut a value short of its shape, and the rest of it then survives.
func Email ¶
Email keeps enough of an address for its owner to recognize it and not enough for anyone else to use it. The domain goes too: for somebody else's address it names their organization.
func ID ¶
ID truncates an identifier to a correlation key that cannot be looked up or pasted into a URL: its first six characters. The logging rule (§9.2) allows that much and no more.
func IsCertificateError ¶
IsCertificateError reports a certificate the client refused: an unknown authority, a name that does not match, one expired or unfit.
func MaskSecrets ¶
MaskSecrets replaces every secret shape in a job log with [MASKED <kind>] and returns the masked text and how many it replaced. The count goes into the result, so a reader knows the log was altered and where to look.
func NetError ¶
NetError renders a transport error without the host names, addresses and URLs net, net/http and crypto/x509 put in it, which logs may not carry (§9.2): a lookup names the host it looked up, a dial the address, a request the URL, and a certificate for the wrong host names both hosts.
It is an allowlist. Only shapes whose text is known to be fixed are rendered, each in words of its own; anything else becomes a fixed phrase, because an error nobody has read may carry any of those.
func Text ¶
Text masks everything in s that has a shape: tokens, URLs, addresses and application ids. It is for text this server did not write, such as an error, whose values are not known in advance. Tokens go first, so nothing after them can split one and leave half behind.
func Truncate ¶
Truncate cuts s to at most n bytes, on a rune boundary, marking the cut with "…". It masks nothing.
Types ¶
type Masker ¶
type Masker struct {
// contains filtered or unexported fields
}
A Masker replaces what identifies an instance, a project or a person with stable placeholders, {host 1}, {user 1}, {path 2}, for the reports people paste into a bug form. The same value always gets the same placeholder, so a report still reads as a story, and Footer says how many of each were hidden.
Shapes are found as Text finds them. Values that have no shape — the username `doctor` read from /user, a project path the person typed — are registered with Known and matched as whole words, case insensitively.
func (*Masker) Footer ¶
Footer says what was hidden, one count per kind in name order, or that nothing was.