Skip to content

Commit 2753b8b

Browse files
Merge pull request #1353 from r00tX-glitch:1Password-secrets-extractor
PiperOrigin-RevId: 817123715
2 parents 147c5fe + ac082a5 commit 2753b8b

File tree

8 files changed

+844
-28
lines changed

8 files changed

+844
-28
lines changed

binary/proto/scan_result.proto

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -688,6 +688,9 @@ message SecretData {
688688
AzureStorageAccountAccessKey azure_storage_account_access_key = 36;
689689
HashiCorpCloudPlatformCredentials hashicorp_cloud_platform_credentials = 37;
690690
HashiCorpCloudPlatformToken hashicorp_cloud_platform_token = 38;
691+
OnePasswordSecretKey onepassword_secret_key = 39;
692+
OnePasswordServiceToken onepassword_service_token = 40;
693+
OnePasswordRecoveryCode onepassword_recovery_code = 41;
691694
}
692695

693696
message GCPSAK {
@@ -880,6 +883,18 @@ message SecretData {
880883
// "ya29.[alphanumeric_string]"
881884
string token = 1;
882885
}
886+
887+
message OnePasswordSecretKey {
888+
string key = 1;
889+
}
890+
message OnePasswordServiceToken {
891+
string key = 1;
892+
}
893+
894+
message OnePasswordRecoveryCode {
895+
string key = 1;
896+
}
897+
883898
}
884899

885900
message SecretStatus {

binary/proto/scan_result_go_proto/scan_result.pb.go

Lines changed: 226 additions & 28 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

binary/proto/secret.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import (
3737
veleshashicorpvault "github.com/google/osv-scalibr/veles/secrets/hashicorpvault"
3838
veleshashicorpcloudplatform "github.com/google/osv-scalibr/veles/secrets/hcp"
3939
"github.com/google/osv-scalibr/veles/secrets/huggingfaceapikey"
40+
velesonepasswordkeys "github.com/google/osv-scalibr/veles/secrets/onepasswordkeys"
4041
velesopenai "github.com/google/osv-scalibr/veles/secrets/openai"
4142
velesperplexity "github.com/google/osv-scalibr/veles/secrets/perplexityapikey"
4243
velespostmanapikey "github.com/google/osv-scalibr/veles/secrets/postmanapikey"
@@ -174,6 +175,12 @@ func velesSecretToProto(s veles.Secret) (*spb.SecretData, error) {
174175
return gcpOAuth2ClientCredentialsToProto(t), nil
175176
case gcpoauth2access.Token:
176177
return gcpOAuth2AccessTokenToProto(t), nil
178+
case velesonepasswordkeys.OnePasswordSecretKey:
179+
return onepasswordSecretKeyToProto(t), nil
180+
case velesonepasswordkeys.OnePasswordServiceToken:
181+
return onepasswordServiceTokenToProto(t), nil
182+
case velesonepasswordkeys.OnePasswordRecoveryCode:
183+
return onepasswordRecoveryCodeToProto(t), nil
177184
case veleshashicorpcloudplatform.ClientCredentials:
178185
return hashicorpCloudPlatformCredentialsToProto(t), nil
179186
case veleshashicorpcloudplatform.AccessToken:
@@ -553,6 +560,36 @@ func gcpOAuth2AccessTokenToProto(s gcpoauth2access.Token) *spb.SecretData {
553560
}
554561
}
555562

563+
func onepasswordSecretKeyToProto(s velesonepasswordkeys.OnePasswordSecretKey) *spb.SecretData {
564+
return &spb.SecretData{
565+
Secret: &spb.SecretData_OnepasswordSecretKey{
566+
OnepasswordSecretKey: &spb.SecretData_OnePasswordSecretKey{
567+
Key: s.Key,
568+
},
569+
},
570+
}
571+
}
572+
573+
func onepasswordServiceTokenToProto(s velesonepasswordkeys.OnePasswordServiceToken) *spb.SecretData {
574+
return &spb.SecretData{
575+
Secret: &spb.SecretData_OnepasswordServiceToken{
576+
OnepasswordServiceToken: &spb.SecretData_OnePasswordServiceToken{
577+
Key: s.Key,
578+
},
579+
},
580+
}
581+
}
582+
583+
func onepasswordRecoveryCodeToProto(s velesonepasswordkeys.OnePasswordRecoveryCode) *spb.SecretData {
584+
return &spb.SecretData{
585+
Secret: &spb.SecretData_OnepasswordRecoveryCode{
586+
OnepasswordRecoveryCode: &spb.SecretData_OnePasswordRecoveryCode{
587+
Key: s.Key,
588+
},
589+
},
590+
}
591+
}
592+
556593
func validationResultToProto(r inventory.SecretValidationResult) (*spb.SecretStatus, error) {
557594
status, err := validationStatusToProto(r.Status)
558595
if err != nil {
@@ -713,6 +750,18 @@ func velesSecretToStruct(s *spb.SecretData) (veles.Secret, error) {
713750
return gcpOAuth2ClientCredentialsToStruct(s.GetGcpOauth2ClientCredentials()), nil
714751
case *spb.SecretData_GcpOauth2AccessToken:
715752
return gcpOAuth2AccessTokenToStruct(s.GetGcpOauth2AccessToken()), nil
753+
case *spb.SecretData_OnepasswordSecretKey:
754+
return velesonepasswordkeys.OnePasswordSecretKey{
755+
Key: s.GetOnepasswordSecretKey().GetKey(),
756+
}, nil
757+
case *spb.SecretData_OnepasswordServiceToken:
758+
return velesonepasswordkeys.OnePasswordServiceToken{
759+
Key: s.GetOnepasswordServiceToken().GetKey(),
760+
}, nil
761+
case *spb.SecretData_OnepasswordRecoveryCode:
762+
return velesonepasswordkeys.OnePasswordRecoveryCode{
763+
Key: s.GetOnepasswordRecoveryCode().GetKey(),
764+
}, nil
716765
case *spb.SecretData_HashicorpCloudPlatformCredentials:
717766
return veleshashicorpcloudplatform.ClientCredentials{
718767
ClientID: s.GetHashicorpCloudPlatformCredentials().GetClientId(),

docs/supported_inventory_types.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,9 @@ See the docs on [how to add a new Extractor](/docs/new_extractor.md).
128128
| Hashicorp Vault token | `secrets/hashicorpvaulttoken` |
129129
| Hashicorp Vault AppRole token | `secrets/hashicorpvaultapprole` |
130130
| Hugging Face API key | `secrets/huggingfaceapikey` |
131+
| 1Password Secret Key | `secrets/onepasswordsecretkey` |
132+
| 1Password Service Token | `secrets/onepasswordservicetoken` |
133+
| 1Password Recovery Code | `secrets/onepasswordrecoverycode` |
131134
| OpenAI API key | `secrets/openai` |
132135
| Perplexity API key | `secrets/perplexityapikey` |
133136
| Postman API key | `secrets/postmanapikey` |

extractor/filesystem/list/list.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ import (
107107
"github.com/google/osv-scalibr/veles/secrets/hashicorpvault"
108108
"github.com/google/osv-scalibr/veles/secrets/hcp"
109109
"github.com/google/osv-scalibr/veles/secrets/huggingfaceapikey"
110+
"github.com/google/osv-scalibr/veles/secrets/onepasswordkeys"
110111
"github.com/google/osv-scalibr/veles/secrets/openai"
111112
"github.com/google/osv-scalibr/veles/secrets/perplexityapikey"
112113
"github.com/google/osv-scalibr/veles/secrets/postmanapikey"
@@ -297,6 +298,9 @@ var (
297298
{stripeapikeys.NewWebhookSecretDetector(), "secrets/stripewebhooksecret", 0},
298299
{gcpoauth2client.NewDetector(), "secrets/gcpoauth2clientcredentials", 0},
299300
{gcpoauth2access.NewDetector(), "secrets/gcpoauth2accesstoken", 0},
301+
{onepasswordkeys.NewSecretKeyDetector(), "secrets/onepasswordsecretkey", 0},
302+
{onepasswordkeys.NewServiceTokenDetector(), "secrets/onepasswordservicetoken", 0},
303+
{onepasswordkeys.NewRecoveryTokenDetector(), "secrets/onepasswordrecoverycode", 0},
300304
})
301305

302306
// Misc artifact extractors.
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
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 onepasswordkeys
16+
17+
import (
18+
"regexp"
19+
20+
"github.com/google/osv-scalibr/veles"
21+
"github.com/google/osv-scalibr/veles/secrets/common/simpletoken"
22+
)
23+
24+
var (
25+
// Ensure constructors satisfy the interface at compile time.
26+
_ veles.Detector = NewSecretKeyDetector()
27+
_ veles.Detector = NewServiceTokenDetector()
28+
_ veles.Detector = NewRecoveryTokenDetector()
29+
)
30+
31+
const (
32+
secretKeyMaxLen = 64
33+
serviceTokenMaxLen = 300
34+
recoveryTokenMaxLen = 69
35+
)
36+
37+
// secretKeyRe matches 1Password Secret Keys in the format:
38+
// A3-<6 alphanum>-<11 alphanum OR 6 alphanum-5 alphanum>-<5 alphanum group x3>
39+
var secretKeyRe = regexp.MustCompile(`A3-[A-Z0-9]{6}-(?:(?:[A-Z0-9]{11})|(?:[A-Z0-9]{6}-[A-Z0-9]{5}))-[A-Z0-9]{5}-[A-Z0-9]{5}-[A-Z0-9]{5}`)
40+
41+
// serviceTokenRe matches 1Password Service Account Tokens, which:
42+
// - Start with "ops_eyJ"
43+
// - Followed by at least 250 base64 characters (a-zA-Z0-9+/)
44+
// - Optionally end with up to 3 '=' padding characters
45+
var serviceTokenRe = regexp.MustCompile(`ops_eyJ[a-zA-Z0-9+/]{250,}={0,3}`)
46+
47+
// recoveryTokenRe matches 1Password Recovery Keys in the format:
48+
// - Start with "1PRK"
49+
// - Followed by 13 groups of 4 alphanum characters, each separated by '-'
50+
var recoveryTokenRe = regexp.MustCompile(`1PRK(?:-[A-Z0-9]{4}){13}`)
51+
52+
// NewSecretKeyDetector returns a detector for 1Password Secret Keys.
53+
func NewSecretKeyDetector() veles.Detector {
54+
return simpletoken.Detector{
55+
MaxLen: secretKeyMaxLen,
56+
Re: secretKeyRe,
57+
FromMatch: func(b []byte) (veles.Secret, bool) {
58+
return OnePasswordSecretKey{Key: string(b)}, true
59+
},
60+
}
61+
}
62+
63+
// NewServiceTokenDetector returns a detector for 1Password Service Account Tokens.
64+
func NewServiceTokenDetector() veles.Detector {
65+
return simpletoken.Detector{
66+
MaxLen: serviceTokenMaxLen,
67+
Re: serviceTokenRe,
68+
FromMatch: func(b []byte) (veles.Secret, bool) {
69+
return OnePasswordServiceToken{Key: string(b)}, true
70+
},
71+
}
72+
}
73+
74+
// NewRecoveryTokenDetector returns a detector for 1Password Recovery Keys.
75+
func NewRecoveryTokenDetector() veles.Detector {
76+
return simpletoken.Detector{
77+
MaxLen: recoveryTokenMaxLen,
78+
Re: recoveryTokenRe,
79+
FromMatch: func(b []byte) (veles.Secret, bool) {
80+
return OnePasswordRecoveryCode{Key: string(b)}, true
81+
},
82+
}
83+
}

0 commit comments

Comments
 (0)