Ctrl K
ComunidadGuías…

internal/mcp/redact.go

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
package mcp

import (
	"regexp"
	"strings"

	"github.com/sophotechlabs/spinoza/internal/api"
	"go.yaml.in/yaml/v3"
)

const hidden = "[redacted by spinoza]"

const rawOutputWithheld = "raw output withheld; restart with -unsafe-raw-output only if credential exposure is acceptable"

var secretish = []string{
	"password", "passwd", "secret", "token", "apikey", "api_key", "accesskey",
	"access_key", "credential", "private_key", "privatekey", "auth", "session",
	"signature", "certificate", "connectionstring", "connection_string", "dsn",
}

var exactSecretish = map[string]struct{}{
	"code":    {},
	"cookie":  {},
	"key":     {},
	"license": {},
	"uri":     {},
	"url":     {},
}

var (
	bearer     = regexp.MustCompile(`(?i)\b(bearer|basic)\s+[A-Za-z0-9._~+/=-]{8,}`)
	marker     = `(?:` + strings.Join(secretish, "|") + `)`
	assignment = regexp.MustCompile(`(?i)\b([\w.-]*` + marker + `[\w.-]*)"?[ \t]*[:=][ \t]*("?)([^\s",}]{4,})("?)`)
	envPair    = regexp.MustCompile(`(?im)^(\s*-?\s*name:\s*["']?[\w.-]*` + marker + `[\w.-]*["']?\s*\r?\n\s*value:\s*)(\S.*)$`)
	github     = regexp.MustCompile(`\b(?:gh[pousr]_|github_pat_)[A-Za-z0-9_]{20,}\b`)
	prefixed   = regexp.MustCompile(`\b(?:xox[baprs]-[A-Za-z0-9-]{10,}|(?:sk|rk)_(?:live|test)_[A-Za-z0-9]{12,}|glpat-[A-Za-z0-9_-]{12,}|AIza[A-Za-z0-9_-]{20,}|(?:AKIA|ASIA)[A-Z0-9]{16}|SG\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,})\b`)
	jwt        = regexp.MustCompile(`\beyJ[A-Za-z0-9._-]{16,}`)
	pemBlock   = regexp.MustCompile(`(?s)-----BEGIN [A-Z ]*PRIVATE KEY-----.*?-----END [A-Z ]*PRIVATE KEY-----`)
	longBlob   = regexp.MustCompile(`\b[A-Za-z0-9+/]{40,}={0,2}\b`)
)

func looksSecret(name string) bool {
	lowered := strings.ToLower(strings.TrimSpace(name))
	if _, found := exactSecretish[lowered]; found {
		return true
	}
	for _, mark := range secretish {
		if strings.Contains(lowered, mark) {
			return true
		}
	}
	return false
}

func scrub(text string) string {
	if text == "" {
		return text
	}
	text = pemBlock.ReplaceAllString(text, hidden)
	text = bearer.ReplaceAllString(text, "$1 "+hidden)
	text = github.ReplaceAllString(text, hidden)
	text = prefixed.ReplaceAllString(text, hidden)
	text = jwt.ReplaceAllString(text, hidden)
	text = envPair.ReplaceAllString(text, "${1}"+hidden)
	text = assignment.ReplaceAllString(text, "$1: $2"+hidden+"$4")
	return longBlob.ReplaceAllString(text, hidden)
}

func scrubMap(pairs map[string]string) map[string]string {
	if len(pairs) == 0 {
		return nil
	}
	out := make(map[string]string, len(pairs))
	for key, value := range pairs {
		if looksSecret(key) {
			out[key] = hidden
			continue
		}
		out[key] = scrub(value)
	}
	return out
}

func scrubLines(lines []string) []string {
	out := make([]string, 0, len(lines))
	for _, line := range lines {
		out = append(out, scrub(line))
	}
	return out
}

type dataKey struct {
	Key    string `json:"key"`
	Bytes  int    `json:"bytes"`
	Binary bool   `json:"binary,omitempty"`
}

func keysOnly(entries []api.DataEntry) []dataKey {
	out := make([]dataKey, 0, len(entries))
	for _, entry := range entries {
		out = append(out, dataKey{Key: entry.Key, Bytes: entry.Bytes, Binary: entry.Binary})
	}
	return out
}

func carriesSecrets(kind string) bool {
	return kind == "Secret"
}

func safeYAML(kind, document string) string {
	if carriesSecrets(kind) {
		return ""
	}
	return scrubStructuredYAML(document)
}

func scrubStructuredYAML(document string) string {
	var root yaml.Node
	if err := yaml.Unmarshal([]byte(document), &root); err != nil {
		return scrub(document)
	}
	if !redactYAML(&root) {
		return scrub(document)
	}
	rendered, err := yaml.Marshal(&root)
	if err != nil {
		return scrub(document)
	}
	return scrub(string(rendered))
}

func redactYAML(node *yaml.Node) bool {
	changed := false
	if node.Kind == yaml.MappingNode {
		for at := 0; at+1 < len(node.Content); at += 2 {
			key := node.Content[at]
			value := node.Content[at+1]
			if looksSecret(key.Value) {
				value.Kind = yaml.ScalarNode
				value.Tag = "!!str"
				value.Value = hidden
				value.Content = nil
				value.Alias = nil
				changed = true
				continue
			}
			if redactYAML(value) {
				changed = true
			}
		}
		return changed
	}
	for _, child := range node.Content {
		if redactYAML(child) {
			changed = true
		}
	}
	return changed
}