@@ -535,9 +535,9 @@ func TestSanitizeArgs(t *testing.T) {
535535 },
536536 expected : []string {
537537 "run" ,
538- "-e" , "GITHUB_PERSONAL_ACCESS_TOKEN=ghp_..." ,
539- "-e" , "API_KEY=sk_t..." ,
540- "-e" , "SHORT=..." ,
538+ "-e" , "GITHUB_PERSONAL_ACCESS_TOKEN=ghp_..." , // Secret detected by pattern
539+ "-e" , "API_KEY=sk_t..." , // Secret detected by name and pattern
540+ "-e" , "SHORT=abc" , // Non-sensitive: short value
541541 "--rm" ,
542542 "-i" ,
543543 "image:latest" ,
@@ -560,11 +560,11 @@ func TestSanitizeArgs(t *testing.T) {
560560 "run" ,
561561 "--rm" ,
562562 "-i" ,
563- "-e" , "NO_COLOR=..." ,
564- "-e" , "TERM=..." ,
565- "-e" , "PYTHONUNBUFFERED=..." ,
566- "-e" , "GITHUB_PERSONAL_ACCESS_TOKEN=ghp_..." ,
567- "-e" , "GITHUB_READ_ONLY=..." ,
563+ "-e" , "NO_COLOR=1" , // Non-sensitive: unchanged
564+ "-e" , "TERM=dumb" , // Non-sensitive: unchanged
565+ "-e" , "PYTHONUNBUFFERED=1" , // Non-sensitive: unchanged
566+ "-e" , "GITHUB_PERSONAL_ACCESS_TOKEN=ghp_..." , // Secret: truncated
567+ "-e" , "GITHUB_READ_ONLY=1" , // Non-sensitive: unchanged
568568 "ghcr.io/github/github-mcp-server:v0.29.0" ,
569569 },
570570 },
@@ -579,14 +579,14 @@ func TestSanitizeArgs(t *testing.T) {
579579 expected : []string {"run" , "-e" , "EMPTY=" , "image:latest" },
580580 },
581581 {
582- name : "env var with equals in value" ,
582+ name : "env var with equals in value (non-sensitive config) " ,
583583 input : []string {
584584 "run" ,
585- "-e" , "CONFIG=key=value=extra " ,
585+ "-e" , "LOG_FORMAT=json=pretty " ,
586586 },
587587 expected : []string {
588588 "run" ,
589- "-e" , "CONFIG=key=..." ,
589+ "-e" , "LOG_FORMAT=json=pretty" , // Non-sensitive: short value, no secret indicators
590590 },
591591 },
592592 {
@@ -607,9 +607,49 @@ func TestSanitizeArgs(t *testing.T) {
607607 expected : []string {
608608 "run" ,
609609 "--name" , "test-container" ,
610- "-e" , "API_KEY=secr..." ,
610+ "-e" , "API_KEY=secr..." , // Secret: detected by name "API_KEY"
611611 "--network" , "host" ,
612- "-e" , "TOKEN=myto..." ,
612+ "-e" , "TOKEN=myto..." , // Secret: detected by name "TOKEN"
613+ "image:latest" ,
614+ },
615+ },
616+ {
617+ name : "non-sensitive configuration values" ,
618+ input : []string {
619+ "run" ,
620+ "-e" , "DEBUG=true" ,
621+ "-e" , "LOG_LEVEL=info" ,
622+ "-e" , "ENABLE_FEATURE=yes" ,
623+ "-e" , "PORT=8080" ,
624+ "image:latest" ,
625+ },
626+ expected : []string {
627+ "run" ,
628+ "-e" , "DEBUG=true" , // Non-sensitive: common config value
629+ "-e" , "LOG_LEVEL=info" , // Non-sensitive: common config value
630+ "-e" , "ENABLE_FEATURE=yes" , // Non-sensitive: common config value
631+ "-e" , "PORT=8080" , // Non-sensitive: port number
632+ "image:latest" ,
633+ },
634+ },
635+ {
636+ name : "mixed sensitive and non-sensitive values" ,
637+ input : []string {
638+ "run" ,
639+ "-e" , "NO_COLOR=1" ,
640+ "-e" , "GITHUB_TOKEN=ghp_abcdefghijklmnopqrstuvwxyz1234567890" ,
641+ "-e" , "TERM=xterm" ,
642+ "-e" , "DATABASE_PASSWORD=my_secret_db_pass_123" ,
643+ "-e" , "TIMEOUT=30" ,
644+ "image:latest" ,
645+ },
646+ expected : []string {
647+ "run" ,
648+ "-e" , "NO_COLOR=1" , // Non-sensitive
649+ "-e" , "GITHUB_TOKEN=ghp_..." , // Secret: matches pattern
650+ "-e" , "TERM=xterm" , // Non-sensitive
651+ "-e" , "DATABASE_PASSWORD=my_s..." , // Secret: detected by name
652+ "-e" , "TIMEOUT=30" , // Non-sensitive
613653 "image:latest" ,
614654 },
615655 },
@@ -623,6 +663,51 @@ func TestSanitizeArgs(t *testing.T) {
623663 }
624664}
625665
666+ func TestLooksLikeSecret (t * testing.T ) {
667+ tests := []struct {
668+ name string
669+ varName string
670+ value string
671+ expected bool
672+ }{
673+ // Secret detection by name
674+ {name : "token in name" , varName : "GITHUB_TOKEN" , value : "abc123" , expected : true },
675+ {name : "secret in name" , varName : "API_SECRET" , value : "xyz789" , expected : true },
676+ {name : "key in name" , varName : "DATABASE_KEY" , value : "test123" , expected : true },
677+ {name : "password in name" , varName : "DB_PASSWORD" , value : "pass123" , expected : true },
678+ {name : "apikey in name" , varName : "SERVICE_APIKEY" , value : "key123" , expected : true },
679+
680+ // Non-sensitive names
681+ {name : "color setting" , varName : "NO_COLOR" , value : "1" , expected : false },
682+ {name : "term setting" , varName : "TERM" , value : "dumb" , expected : false },
683+ {name : "debug flag" , varName : "DEBUG" , value : "true" , expected : false },
684+ {name : "port number" , varName : "PORT" , value : "8080" , expected : false },
685+
686+ // Secret detection by value pattern
687+ {name : "github pat" , varName : "VAR" , value : "ghp_1234567890123456789012345678901234567890" , expected : true },
688+ {name : "long hex string" , varName : "VAR" , value : "abcdef1234567890abcdef1234567890abcdef12" , expected : true },
689+ {name : "jwt token" , varName : "VAR" , value : "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.payload.signature" , expected : true },
690+
691+ // Short non-sensitive values
692+ {name : "single digit" , varName : "VAR" , value : "1" , expected : false },
693+ {name : "boolean true" , varName : "VAR" , value : "true" , expected : false },
694+ {name : "boolean false" , varName : "VAR" , value : "false" , expected : false },
695+ {name : "yes value" , varName : "VAR" , value : "yes" , expected : false },
696+
697+ // Edge cases
698+ {name : "empty value" , varName : "VAR" , value : "" , expected : false },
699+ {name : "long non-alphanumeric" , varName : "VAR" , value : "====================" , expected : false },
700+ {name : "long config path" , varName : "CONFIG_PATH" , value : "/usr/local/etc/app/config.json" , expected : false },
701+ }
702+
703+ for _ , tt := range tests {
704+ t .Run (tt .name , func (t * testing.T ) {
705+ result := looksLikeSecret (tt .varName , tt .value )
706+ assert .Equal (t , tt .expected , result , "looksLikeSecret(%q, %q) should return %v" , tt .varName , tt .value , tt .expected )
707+ })
708+ }
709+ }
710+
626711func TestSanitizeArgsDoesNotLeakSecrets (t * testing.T ) {
627712 // Test that actual secrets are not present in sanitized output
628713 secretToken := "ghp_verysecrettokenthatshouldbehidden1234567890"
0 commit comments