github.com/google/osv-scalibr@v0.4.1/extractor/filesystem/secrets/onepasswordconnecttoken/onepasswordconnecttoken.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 onepasswordconnecttoken contains an extractor for OnePassword Connect Token files. 16 package onepasswordconnecttoken 17 18 import ( 19 "context" 20 "encoding/json" 21 "path" 22 "strings" 23 24 "github.com/google/osv-scalibr/extractor/filesystem" 25 "github.com/google/osv-scalibr/inventory" 26 "github.com/google/osv-scalibr/plugin" 27 ) 28 29 // OnePasswordConnectToken is a Veles Secret that holds a OnePassword Connect Token 30 // with all its encrypted credentials and metadata. 31 type OnePasswordConnectToken struct { 32 DeviceUUID string 33 Version string 34 EncryptedData string 35 EncryptionKeyID string 36 IV string 37 UniqueKeyID string 38 VerifierSalt string 39 VerifierLocalHash string 40 } 41 42 const ( 43 // Name is the unique name of this extractor. 44 Name = "secrets/onepasswordconnecttoken" 45 ) 46 47 // TokenData represents the structure of a OnePassword Connect Token JSON file. 48 type TokenData struct { 49 Verifier struct { 50 Salt string `json:"salt"` 51 LocalHash string `json:"localHash"` 52 } `json:"verifier"` 53 EncCredentials struct { 54 Kid string `json:"kid"` 55 Enc string `json:"enc"` 56 Cty string `json:"cty"` 57 IV string `json:"iv"` 58 Data string `json:"data"` 59 } `json:"encCredentials"` 60 Version string `json:"version"` 61 DeviceUUID string `json:"deviceUuid"` 62 UniqueKey struct { 63 Alg string `json:"alg"` 64 Ext bool `json:"ext"` 65 K string `json:"k"` 66 KeyOps []string `json:"key_ops"` 67 Kty string `json:"kty"` 68 Kid string `json:"kid"` 69 } `json:"uniqueKey"` 70 } 71 72 // Extractor extracts OnePassword Connect Token secrets. 73 type Extractor struct{} 74 75 // New returns a new instance of the extractor. 76 func New() filesystem.Extractor { return &Extractor{} } 77 78 // Name of the extractor. 79 func (e Extractor) Name() string { return Name } 80 81 // Version of the extractor. 82 func (e Extractor) Version() int { return 0 } 83 84 // Requirements of the extractor. 85 func (e Extractor) Requirements() *plugin.Capabilities { 86 return &plugin.Capabilities{} 87 } 88 89 // FileRequired returns true if the file is a JSON file with "onepassword" or "1password" in its name. 90 func (e Extractor) FileRequired(api filesystem.FileAPI) bool { 91 fileName := strings.ToLower(path.Base(api.Path())) 92 93 // Check if the filename contains "onepassword" or "1password" 94 if !strings.Contains(fileName, "onepassword") && !strings.Contains(fileName, "1password") { 95 return false 96 } 97 98 // Check if it's a JSON file 99 return strings.HasSuffix(fileName, ".json") 100 } 101 102 // Extract extracts OnePassword Connect Token information from JSON files. 103 func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) (inventory.Inventory, error) { 104 var data TokenData 105 106 decoder := json.NewDecoder(input.Reader) 107 if err := decoder.Decode(&data); err != nil { 108 // Not a valid JSON or not a OnePassword Connect Token file, return empty inventory 109 //nolint:nilerr 110 return inventory.Inventory{}, nil 111 } 112 113 // Check if this looks like a OnePassword Connect Token file by verifying required fields 114 if data.DeviceUUID == "" || data.Version == "" || data.EncCredentials.Data == "" { 115 // Not a OnePassword Connect Token file, return empty inventory 116 return inventory.Inventory{}, nil 117 } 118 119 var secrets []*inventory.Secret 120 121 secret := &inventory.Secret{ 122 Secret: OnePasswordConnectToken{ 123 DeviceUUID: data.DeviceUUID, 124 Version: data.Version, 125 EncryptedData: data.EncCredentials.Data, 126 EncryptionKeyID: data.EncCredentials.Kid, 127 IV: data.EncCredentials.IV, 128 UniqueKeyID: data.UniqueKey.Kid, 129 VerifierSalt: data.Verifier.Salt, 130 VerifierLocalHash: data.Verifier.LocalHash, 131 }, 132 Location: input.Path, 133 } 134 135 secrets = append(secrets, secret) 136 137 return inventory.Inventory{Secrets: secrets}, nil 138 }