trufflesecurity/trufflehog · error

%s is not a valid regex, error received: %v

Error message

%s is not a valid regex, error received: %v

What it means

TruffleHog's Postgres detector accepts WithIgnorePattern to suppress false-positive postgres:// connection URIs. Unlike stdlib regexp, this file imports regexp from github.com/wasilibs/go-re2, a WASM build of Google's RE2 engine, so the accepted syntax is strictly RE2: no lookaheads, no lookbehinds, no backreferences, no \C. Any string go-re2 cannot compile makes the option panic with this message while New(...) applies it, crashing the process at scanner construction. The panic text contains the offending pattern and the compile error, which is all you need to fix it.

Source

Thrown at pkg/detectors/postgres/postgres.go:83

func New(opts ...func(*Scanner)) *Scanner {
	scanner := &Scanner{
		ignorePatterns: []*regexp.Regexp{},
	}
	for _, opt := range opts {
		opt(scanner)
	}

	return scanner
}

func WithIgnorePattern(ignoreStrings []string) func(*Scanner) {
	return func(s *Scanner) {
		var ignorePatterns []*regexp.Regexp
		for _, ignoreString := range ignoreStrings {
			ignorePattern, err := regexp.Compile(ignoreString)
			if err != nil {
				panic(fmt.Sprintf("%s is not a valid regex, error received: %v", ignoreString, err))
			}
			ignorePatterns = append(ignorePatterns, ignorePattern)
		}

		s.ignorePatterns = ignorePatterns
	}
}

var _ detectors.Detector = (*Scanner)(nil)
var _ detectors.CustomFalsePositiveChecker = (*Scanner)(nil)

func (s Scanner) Keywords() []string {
	return []string{"postgres"}
}

func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) ([]detectors.Result, error) {
	var results []detectors.Result
	candidateURIs := findUriMatches(data, s.ignorePatterns)

View on GitHub (pinned to bcfcf73aaf)

Solutions

  1. Read the panic message: it shows the exact pattern and the RE2 error; fix or remove that pattern.
  2. Remove PCRE-only constructs: rewrite '(?=.*staging)' style lookaheads as plain '.*staging', drop lookbehinds and backreferences (repeat the literal group instead).
  3. Keep patterns in raw string literals (backticks) to avoid double-escaping: `postgres://.*\.staging` not "postgres://.*\\.staging".
  4. Compile-check every pattern with github.com/wasilibs/go-re2 (the same engine the detector uses) before calling New(), and return an error at the config layer rather than panicking at scan startup.
  5. If patterns arrive untrusted, guard New() with defer/recover and surface the panic as an error.

Example fix

// before
s := postgres.New(postgres.WithIgnorePattern([]string{"postgres://(?=.*staging).*"})) // panics: go-re2 has no lookahead

// after
s := postgres.New(postgres.WithIgnorePattern([]string{`postgres://.*staging`}))
Defensive patterns

Strategy: validation

Validate before calling

import (
	"fmt"
	regexp "github.com/wasilibs/go-re2"
)

// Run BEFORE postgres.New(postgres.WithIgnorePattern(...)). Uses
// go-re2, the exact engine this detector compiles with, so RE2-only
// rejections (lookahead, backreferences) are caught here, not in a panic.
func validateIgnorePatterns(patterns []string) error {
	for _, p := range patterns {
		if _, err := regexp.Compile(p); err != nil {
			return fmt.Errorf("invalid postgres ignore pattern %q: %w", p, err)
		}
	}
	return nil
}

if err := validateIgnorePatterns(cfg.PostgresIgnorePatterns); err != nil {
	return err // reject config before constructing the scanner
}

Type guard

// True when the string compiles under go-re2 (RE2), the engine the
// postgres detector uses. PCRE-only patterns return false.
func isValidRE2Pattern(pattern string) bool {
	_, err := regexp.Compile(pattern)
	return err == nil
}

Try / catch

// Last-resort conversion of the constructor panic into an error.
func newPostgresScanner(opts ...func(*postgres.Scanner)) (sc *postgres.Scanner, err error) {
	defer func() {
		if r := recover(); r != nil {
			err = fmt.Errorf("postgres scanner construction failed: %v", r)
		}
	}()
	return postgres.New(opts...), nil
}

Prevention

When it happens

Trigger: Calling postgres.New(postgres.WithIgnorePattern([]string{...})) with a pattern that is invalid under RE2: PCRE-isms like '(?=.*staging)', '(?!dev)', '(?<=user)', or backreferences like '\1', or plain syntax errors such as unbalanced parentheses, a dangling '\', or invalid repetition. Note that the same pattern may work fine in other tools (grep -P, ripgrep --pcre2, some config linters) and still panic here because go-re2 rejects the construct outright.

Common situations: Copying ignore patterns written for PCRE engines out of other scanners or regex cheat sheets; sourcing patterns from CI environment variables or YAML/JSON config that is never compile-checked before the run; escaping drift when the pattern passes through two layers (YAML single-quote plus Go string); a version where the detector moved from stdlib regexp to go-re2, suddenly rejecting previously accepted lookaround patterns.

Related errors


AI-assisted analysis of trufflesecurity/trufflehog@bcfcf73aaf (2026-08-15). Data as JSON: /api/errors/08445d5e069fe21a. Report an issue: GitHub.