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  }