e728c35adb
OS secure store per platform: macOS Keychain (/usr/bin/security), Windows Credential Manager (advapi32 P/Invoke), Linux secret-tool; AES-256-CBC+HMAC encrypt-then-MAC fallback (CI-safe, master secret + machine id via PBKDF2, ciphertext under user app-data, never in repo). Env override (MCPFORUNITY_<P>_API_KEY, read-only) layered on top; SecretRedactor scrubs auth tokens. Keys never touch EditorPrefs/bridge/logs/git. EditMode tests for fallback round-trip, encryption-at-rest, env override, redaction. Compiles clean on Unity 2021.3.45f2 (floor). Claude-Session: https://claude.ai/code/session_01Tjpb5gYgUe2AUJuRdXr7Lv
37 lines
1.3 KiB
C#
37 lines
1.3 KiB
C#
using System.Text.RegularExpressions;
|
|
|
|
namespace MCPForUnity.Editor.Security
|
|
{
|
|
/// <summary>
|
|
/// Scrubs secrets out of text before it is logged or returned. Use on every error/log
|
|
/// path that might contain an auth header or a key value.
|
|
/// </summary>
|
|
public static class SecretRedactor
|
|
{
|
|
private const string Mask = "***REDACTED***";
|
|
|
|
// Authorization-scheme tokens: "Bearer xxx", "Key xxx", "Token xxx".
|
|
private static readonly Regex SchemeToken = new Regex(
|
|
@"\b(Bearer|Key|Token)\s+\S{6,}",
|
|
RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
|
|
|
/// <summary>Redact auth-scheme tokens from arbitrary text (cheap; no store reads).</summary>
|
|
public static string Scrub(string text)
|
|
{
|
|
if (string.IsNullOrEmpty(text)) return text;
|
|
return SchemeToken.Replace(text, m => m.Groups[1].Value + " " + Mask);
|
|
}
|
|
|
|
/// <summary>Redact a specific known secret value as well as auth-scheme tokens.</summary>
|
|
public static string Scrub(string text, string secret)
|
|
{
|
|
if (string.IsNullOrEmpty(text)) return text;
|
|
if (!string.IsNullOrEmpty(secret) && secret.Length >= 4)
|
|
{
|
|
text = text.Replace(secret, Mask);
|
|
}
|
|
return Scrub(text);
|
|
}
|
|
}
|
|
}
|