github.com/google/osv-scalibr@v0.4.1/veles/secrets/awsaccesskey/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 awsaccesskey_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/awsaccesskey"
    25  )
    26  
    27  func TestDetector_Detect(t *testing.T) {
    28  	engine, err := veles.NewDetectionEngine([]veles.Detector{awsaccesskey.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:  "invalid_access_id_format_-_wrong prefix",
    46  			input: "WRONG984R439T439HTH439T403TJ430TK340TK43T430JT430TK430JT043JT:32r923jr023rk320rk2a3rkB34tj340r32Ckt433",
    47  			want:  nil,
    48  		},
    49  		{
    50  			name:  "invalid_secret_format_-_too short",
    51  			input: "GOOG1984R439T439HTH439T403TJ430TK340TK43T430JT430TK430JT043JT:32r923jr023rk320rk2a3rkB34tj3",
    52  			want:  nil,
    53  		},
    54  		// --- Only access ID or Secret ---
    55  		{
    56  			name:  "access_ID_but_no_secret",
    57  			input: `app_id: AIKA1984R439T439HTH4`,
    58  			want:  nil,
    59  		},
    60  		{
    61  			name:  "secret_but_no_access_ID",
    62  			input: `app_secret: 32r923jr023rk320rk2a3rkB34tj340r32Ckt433`,
    63  			want:  nil,
    64  		},
    65  		// -- Single access ID and Secret in close proximity (happy path) ---
    66  		{
    67  			name: "aws credentials",
    68  			input: `[default]
    69  aws_access_key_id = AIKA1984R439T439HTH4
    70  aws_secret_access_key = 32r923jr023rk320rk2a3rkB34tj340r32Ckt433`,
    71  			want: []veles.Secret{
    72  				awsaccesskey.Credentials{
    73  					AccessID: "AIKA1984R439T439HTH4",
    74  					Secret:   "32r923jr023rk320rk2a3rkB34tj340r32Ckt433",
    75  				},
    76  			},
    77  		},
    78  		{
    79  			name:  "access_ID_and_secret_in_close_proximity_-_no_space",
    80  			input: `AIKA1984R439T439HTH4:32r923jr023rk320rk2a3rkB34tj340r32Ckt433`,
    81  			want: []veles.Secret{
    82  				awsaccesskey.Credentials{
    83  					AccessID: "AIKA1984R439T439HTH4",
    84  					Secret:   "32r923jr023rk320rk2a3rkB34tj340r32Ckt433",
    85  				},
    86  			},
    87  		},
    88  		{
    89  			name: "access_ID_and_secret_in_close_proximity_in_json_format",
    90  			input: `{
    91  				"access_id": "AIKA1984R439T439HTH4",
    92  				"secret": "32r923jr023rk320rk2a3rkB34tj340r32Ckt433"
    93  			}`,
    94  			want: []veles.Secret{
    95  				awsaccesskey.Credentials{
    96  					AccessID: "AIKA1984R439T439HTH4",
    97  					Secret:   "32r923jr023rk320rk2a3rkB34tj340r32Ckt433",
    98  				},
    99  			},
   100  		},
   101  		{
   102  			name: "valid_formats_mixed_with_invalid",
   103  			input: `valid_id: AIKA1984R439T439HTH4
   104  invalid_id: 123-invalid.apps.googleusercontent.com
   105  valid_secret: 32r923jr023rk320rk2a3rkB34tj340r32Ckt433
   106  invalid_secret: WRONG-InvalidSecret123456789012`,
   107  			want: []veles.Secret{
   108  				awsaccesskey.Credentials{
   109  					AccessID: "AIKA1984R439T439HTH4",
   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  			AIKA1984R439T439HTH4
   119  32r923jr023rk320rk2a3rkB34tj340r32Ckt433
   120  
   121  config_app2:
   122  AIKA1984R439T439HTH3
   123  32r923jr023rk320rk2a3rkB34tj340r32Ckt432`,
   124  			want: []veles.Secret{
   125  				awsaccesskey.Credentials{
   126  					AccessID: "AIKA1984R439T439HTH4",
   127  					Secret:   "32r923jr023rk320rk2a3rkB34tj340r32Ckt433",
   128  				},
   129  				awsaccesskey.Credentials{
   130  					AccessID: "AIKA1984R439T439HTH3",
   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  AIKA1984R439T439HTH4` + 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  			if diff := cmp.Diff(tc.want, got, cmpopts.EquateEmpty()); diff != "" {
   153  				t.Errorf("Detect() diff (-want +got):\n%s", diff)
   154  			}
   155  		})
   156  	}
   157  }