github.com/google/osv-scalibr@v0.4.1/veles/secrets/vapid/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 vapid_test 16 17 import ( 18 "strings" 19 "testing" 20 21 "github.com/google/go-cmp/cmp" 22 "github.com/google/go-cmp/cmp/cmpopts" 23 "github.com/google/osv-scalibr/veles" 24 "github.com/google/osv-scalibr/veles/secrets/vapid" 25 ) 26 27 func TestDetector_Detect(t *testing.T) { 28 engine, err := veles.NewDetectionEngine([]veles.Detector{vapid.NewDetector()}) 29 if err != nil { 30 t.Fatal(err) 31 } 32 33 tests := []struct { 34 name string 35 input string 36 want []veles.Secret 37 }{ 38 // --- Empty or invalid input --- 39 { 40 name: "empty_input", 41 input: "", 42 want: nil, 43 }, 44 { 45 name: "correct_syntax_-_bad_key", 46 input: ` 47 Not Vapid Private Key: LieO7JztGnRv11UxRNJlBkdoK97_PceW7rGXQh36c_4 48 Vapid Public Key: BFEuu_r7cd5hElHB6P9Z1bysARpVxRljjRZEmlrfMTPT2G_GRTGrCOid4WCk4PAnyaFXLPa0sOLMnMMS1sMrMRs 49 `, 50 want: nil, 51 }, 52 { 53 name: "correct_syntax_-_bad_key_-_choose_the_right one", 54 input: ` 55 Vapid Private Key: LieO7JztGnRv11UxRNJlBkdoK97ePceW7rGXQh36c_4 56 Not Vapid Private Key: LieO7JztGnRv11UxRNJlBkdoK97_PceW7rGXQh36c_4 57 Vapid Public Key: BFEuu_r7cd5hElHB6P9Z1bysARpVxRljjRZEmlrfMTPT2G_GRTGrCOid4WCk4PAnyaFXLPa0sOLMnMMS1sMrMRs 58 `, 59 want: []veles.Secret{ 60 vapid.Key{ 61 PrivateB64: "LieO7JztGnRv11UxRNJlBkdoK97ePceW7rGXQh36c_4", 62 PublicB64: "BFEuu_r7cd5hElHB6P9Z1bysARpVxRljjRZEmlrfMTPT2G_GRTGrCOid4WCk4PAnyaFXLPa0sOLMnMMS1sMrMRs", 63 }, 64 }, 65 }, 66 { 67 name: "correct", 68 input: ` 69 Vapid Private Key: LieO7JztGnRv11UxRNJlBkdoK97ePceW7rGXQh36c_4 70 Vapid Public Key: BFEuu_r7cd5hElHB6P9Z1bysARpVxRljjRZEmlrfMTPT2G_GRTGrCOid4WCk4PAnyaFXLPa0sOLMnMMS1sMrMRs 71 `, 72 want: []veles.Secret{ 73 vapid.Key{ 74 PrivateB64: "LieO7JztGnRv11UxRNJlBkdoK97ePceW7rGXQh36c_4", 75 PublicB64: "BFEuu_r7cd5hElHB6P9Z1bysARpVxRljjRZEmlrfMTPT2G_GRTGrCOid4WCk4PAnyaFXLPa0sOLMnMMS1sMrMRs", 76 }, 77 }, 78 }, 79 { 80 name: "correct_-_tuple", 81 input: `LieO7JztGnRv11UxRNJlBkdoK97ePceW7rGXQh36c_4:BFEuu_r7cd5hElHB6P9Z1bysARpVxRljjRZEmlrfMTPT2G_GRTGrCOid4WCk4PAnyaFXLPa0sOLMnMMS1sMrMRs`, 82 want: []veles.Secret{ 83 vapid.Key{ 84 PrivateB64: "LieO7JztGnRv11UxRNJlBkdoK97ePceW7rGXQh36c_4", 85 PublicB64: "BFEuu_r7cd5hElHB6P9Z1bysARpVxRljjRZEmlrfMTPT2G_GRTGrCOid4WCk4PAnyaFXLPa0sOLMnMMS1sMrMRs", 86 }, 87 }, 88 }, 89 { 90 name: "only_public", 91 input: `VapidPublicKey: BFEuu_r7cd5hElHB6P9Z1bysARpVxRljjRZEmlrfMTPT2G_GRTGrCOid4WCk4PAnyaFXLPa0sOLMnMMS1sMrMRs`, 92 want: nil, 93 }, 94 { 95 name: "only_private_-_no_context", 96 input: `Lu7AeLYdEUws2iLm97LcwAbQCI1YA8NpLEe485kmO5s`, 97 want: nil, 98 }, 99 { 100 name: "only_private_-_context", 101 input: `VapidPrivateKey: LieO7JztGnRv11UxRNJlBkdoK97ePceW7rGXQh36c_4`, 102 want: nil, 103 }, 104 { 105 name: "complex_multiline_-_private_key_omitted,_should_not_match", 106 input: ` 107 VapidPrivateKey: **** 108 VapidPublicKey: BE7cFYQ2l4kASZ_7iKwAy6L2hztWwTKrwd41SkRJuGyo6J5vR9ATeUufONHzoaseSpKtcJbm5xLTkmo--IWpEt8 109 `, 110 want: []veles.Secret{}, 111 }, 112 { 113 name: "complex_multiline_-_no_multiline_context_match", 114 input: ` 115 VapidPrivateKey: 116 LieO7JztGnRv11UxRNJlBkdoK97ePceW7rGXQh36c_4 117 `, 118 want: []veles.Secret{}, 119 }, 120 { 121 name: "complex_javascript_-_match", 122 input: ` 123 function setup() { 124 webpush.setVapidDetails( 125 'mailto:email@email.com', 126 'BFKSGCtM-gouDaPSNYwDRmCTCSEelTpujQ6mHG2KIXaaJI9WLReodcS00QE4ck8P5uPHLSkNKZ7ZAWjpgITwrNI', 127 'rrvzfePgU7wc8RP7fcSMR-8ur2nDzqissXT5ovojK6Q' 128 ); 129 return Promise.resolve(); 130 } 131 `, 132 want: []veles.Secret{ 133 vapid.Key{ 134 PrivateB64: "rrvzfePgU7wc8RP7fcSMR-8ur2nDzqissXT5ovojK6Q", 135 PublicB64: "BFKSGCtM-gouDaPSNYwDRmCTCSEelTpujQ6mHG2KIXaaJI9WLReodcS00QE4ck8P5uPHLSkNKZ7ZAWjpgITwrNI", 136 }, 137 }, 138 }, 139 { 140 name: "complex_golang_-_no_match", 141 input: ` 142 resp, err := webpush.SendNotification([]byte("Test"), s, &webpush.Options{ 143 Subscriber: "example@example.com", // Do not include "mailto:" 144 VAPIDPublicKey: vapidPublicKey, 145 VAPIDPrivateKey: vapidPrivateKey, 146 TTL: 30, 147 }) 148 `, 149 want: []veles.Secret{}, 150 }, 151 { 152 name: "complex_golang_-_match", 153 input: ` 154 resp, err := webpush.SendNotification([]byte("Test"), s, &webpush.Options{ 155 Subscriber: "example@example.com", // Do not include "mailto:" 156 VAPIDPublicKey: "rrvzfePgU7wc8RP7fcSMR-8ur2nDzqissXT5ovojK6Q", 157 VAPIDPrivateKey: "BFKSGCtM-gouDaPSNYwDRmCTCSEelTpujQ6mHG2KIXaaJI9WLReodcS00QE4ck8P5uPHLSkNKZ7ZAWjpgITwrNI", 158 TTL: 30, 159 }) 160 `, 161 want: []veles.Secret{ 162 vapid.Key{ 163 PrivateB64: "rrvzfePgU7wc8RP7fcSMR-8ur2nDzqissXT5ovojK6Q", 164 PublicB64: "BFKSGCtM-gouDaPSNYwDRmCTCSEelTpujQ6mHG2KIXaaJI9WLReodcS00QE4ck8P5uPHLSkNKZ7ZAWjpgITwrNI", 165 }, 166 }, 167 }, 168 { 169 name: "json_match", 170 input: ` 171 "webPush": { 172 "subject": "http://example.com", 173 "vapidPublicKey": "BKC9CAak3PFu0nhmVbEFs0HG0o6T1bMb-q_iSAtiYHv2zdQM_IPkz1A9gzVd_-4cNYMeLwq1i8gA83-U0pc4aOk", 174 "vapidPrivateKey": "CSOfcDX5bADZupzLZFoIwvqfyPMEz-vZtJORwHTLPR0" 175 }, 176 `, 177 want: []veles.Secret{ 178 vapid.Key{ 179 PrivateB64: "CSOfcDX5bADZupzLZFoIwvqfyPMEz-vZtJORwHTLPR0", 180 PublicB64: "BKC9CAak3PFu0nhmVbEFs0HG0o6T1bMb-q_iSAtiYHv2zdQM_IPkz1A9gzVd_-4cNYMeLwq1i8gA83-U0pc4aOk", 181 }, 182 }, 183 }, 184 { 185 name: "json_match_-_context_only", 186 input: ` 187 "webPush": { 188 "subject": "http://example.com", 189 "vapidPrivateKey": "CSOfcDX5bADZupzLZFoIwvqfyPMEz-vZtJORwHTLPR0" 190 }, 191 `, 192 want: nil, 193 }, 194 { 195 name: "json_match_-_no_context", 196 input: ` 197 { 198 "Vapid": { 199 "Subject": "mailto:email@outlook.com", 200 "PublicKey": "BEEDPFMgrB5MObgTsdiIh9fQ9Ug5wrLQyk4sDxSYctvqEzFHa9wLGE0-ZDs0A8jXzJHsFVSXshYzDDoLw2YxWGw", 201 "PrivateKey": "gIe4zn7y8cgAyxLVk-6NX_mpR-1R_aPx_8CZ1VI0oYg" 202 }, 203 ... 204 } 205 `, 206 want: []veles.Secret{ 207 vapid.Key{ 208 PrivateB64: "gIe4zn7y8cgAyxLVk-6NX_mpR-1R_aPx_8CZ1VI0oYg", 209 PublicB64: "BEEDPFMgrB5MObgTsdiIh9fQ9Ug5wrLQyk4sDxSYctvqEzFHa9wLGE0-ZDs0A8jXzJHsFVSXshYzDDoLw2YxWGw", 210 }, 211 }, 212 }, 213 } 214 215 for _, tc := range tests { 216 t.Run(tc.name, func(t *testing.T) { 217 got, err := engine.Detect(t.Context(), strings.NewReader(tc.input)) 218 if err != nil { 219 t.Errorf("Detect() error: %v, want nil", err) 220 } 221 if diff := cmp.Diff(tc.want, got, cmpopts.EquateEmpty()); diff != "" { 222 t.Errorf("Detect() diff (-want +got):\n%s", diff) 223 } 224 }) 225 } 226 }