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  }