github.com/google/osv-scalibr@v0.4.1/veles/secrets/gcshmackey/detector_test.go (about) 1 // Copyright 2025 Google LLC 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package gcshmackey_test 16 17 import ( 18 "fmt" 19 "strings" 20 "testing" 21 22 "github.com/google/go-cmp/cmp" 23 "github.com/google/go-cmp/cmp/cmpopts" 24 "github.com/google/osv-scalibr/veles" 25 "github.com/google/osv-scalibr/veles/secrets/gcshmackey" 26 ) 27 28 func TestDetector_Detect(t *testing.T) { 29 engine, err := veles.NewDetectionEngine([]veles.Detector{gcshmackey.NewDetector()}) 30 if err != nil { 31 t.Fatal(err) 32 } 33 34 tests := []struct { 35 name string 36 input string 37 want []veles.Secret 38 }{ 39 // --- Empty or invalid input --- 40 { 41 name: "empty input", 42 input: "", 43 want: nil, 44 }, 45 { 46 name: "invalid access id format - wrong prefix", 47 input: "WRONG984R439T439HTH439T403TJ430TK340TK43T430JT430TK430JT043JT:32r923jr023rk320rk2a3rkB34tj340r32Ckt433", 48 want: nil, 49 }, 50 { 51 name: "invalid secret format - too short", 52 input: "GOOG1984R439T439HTH439T403TJ430TK340TK43T430JT430TK430JT043JT:32r923jr023rk320rk2a3rkB34tj3", 53 want: nil, 54 }, 55 // --- Only access ID or Secret --- 56 { 57 name: "access ID but no secret", 58 input: `app_id: GOOG1984R439T439HTH439T403TJ430TK340TK43T430JT430TK430JT043JT`, 59 want: nil, 60 }, 61 { 62 name: "secret but no access ID", 63 input: `app_secret: 32r923jr023rk320rk2a3rkB34tj340r32Ckt433`, 64 want: nil, 65 }, 66 // -- Single access ID and Secret in close proximity (happy path) --- 67 { 68 name: "access_ID_and_secret_in_close_proximity", 69 input: `GOOG1984R439T439HTH439T403TJ430TK340TK43T430JT430TK430JT043JT 70 32r923jr023rk320rk2a3rkB34tj340r32Ckt433`, 71 want: []veles.Secret{ 72 gcshmackey.HMACKey{ 73 AccessID: "GOOG1984R439T439HTH439T403TJ430TK340TK43T430JT430TK430JT043JT", 74 Secret: "32r923jr023rk320rk2a3rkB34tj340r32Ckt433", 75 }, 76 }, 77 }, 78 { 79 name: "access ID and secret in close proximity - no space", 80 input: `GOOG1984R439T439HTH439T403TJ430TK340TK43T430JT430TK430JT043JT:32r923jr023rk320rk2a3rkB34tj340r32Ckt433`, 81 want: []veles.Secret{ 82 gcshmackey.HMACKey{ 83 AccessID: "GOOG1984R439T439HTH439T403TJ430TK340TK43T430JT430TK430JT043JT", 84 Secret: "32r923jr023rk320rk2a3rkB34tj340r32Ckt433", 85 }, 86 }, 87 }, 88 { 89 name: "access_ID_and_secret_in_close_proximity_in_json_format", 90 input: `{ 91 "access_id": "GOOG1984R439T439HTH439T403TJ430TK340TK43T430JT430TK430JT043JT", 92 "secret": "32r923jr023rk320rk2a3rkB34tj340r32Ckt433" 93 }`, 94 want: []veles.Secret{ 95 gcshmackey.HMACKey{ 96 AccessID: "GOOG1984R439T439HTH439T403TJ430TK340TK43T430JT430TK430JT043JT", 97 Secret: "32r923jr023rk320rk2a3rkB34tj340r32Ckt433", 98 }, 99 }, 100 }, 101 { 102 name: "valid_formats_mixed_with_invalid", 103 input: `valid_id: GOOG1984R439T439HTH439T403TJ430TK340TK43T430JT430TK430JT043JT 104 invalid_id: 123-invalid.apps.googleusercontent.com 105 valid_secret: 32r923jr023rk320rk2a3rkB34tj340r32Ckt433 106 invalid_secret: WRONG-InvalidSecret123456789012`, 107 want: []veles.Secret{ 108 gcshmackey.HMACKey{ 109 AccessID: "GOOG1984R439T439HTH439T403TJ430TK340TK43T430JT430TK430JT043JT", 110 Secret: "32r923jr023rk320rk2a3rkB34tj340r32Ckt433", 111 }, 112 }, 113 }, 114 // -- Multiple access ID and Secret in close proximity --- 115 { 116 name: "complex_file_with_multiple_access_ID_and_secret_-_test_proximity", 117 input: `config_app1: 118 GOOG1984R439T439HTH439T403TJ430TK340TK43T430JT430TK430JT043JT 119 32r923jr023rk320rk2a3rkB34tj340r32Ckt433 120 121 config_app2: 122 GOOG1984R439T439HTH439T403TJ430TK340TK43T430JT430TK430JT043JA 123 32r923jr023rk320rk2a3rkB34tj340r32Ckt432`, 124 want: []veles.Secret{ 125 gcshmackey.HMACKey{ 126 AccessID: "GOOG1984R439T439HTH439T403TJ430TK340TK43T430JT430TK430JT043JT", 127 Secret: "32r923jr023rk320rk2a3rkB34tj340r32Ckt433", 128 }, 129 gcshmackey.HMACKey{ 130 AccessID: "GOOG1984R439T439HTH439T403TJ430TK340TK43T430JT430TK430JT043JA", 131 Secret: "32r923jr023rk320rk2a3rkB34tj340r32Ckt432", 132 }, 133 }, 134 }, 135 // -- Multiple access ID and Secret in with varied proximity --- 136 { 137 name: "complex_file_with_access_ID_and_secret_-_far_apart_(no_pairing)", 138 input: `config_app1: 139 GOOG1984R439T439HTH439T403TJ430TK340TK43T430JT430TK430JT043JA` + strings.Repeat("\nfiller line with random data", 500) + ` 140 config_app2: 141 32r923jr023rk320rk2a3rkB34tj340r32Ckt432`, 142 want: nil, 143 }, 144 } 145 146 for _, tc := range tests { 147 t.Run(tc.name, func(t *testing.T) { 148 got, err := engine.Detect(t.Context(), strings.NewReader(tc.input)) 149 if err != nil { 150 t.Errorf("Detect() error: %v, want nil", err) 151 } 152 fmt.Printf("got = %+v\n", got) 153 if diff := cmp.Diff(tc.want, got, cmpopts.EquateEmpty()); diff != "" { 154 t.Errorf("Detect() diff (-want +got):\n%s", diff) 155 } 156 }) 157 } 158 }