Skip to content

Commit eeeced7

Browse files
security: fix validation regressions and stabilize mock testing
Signed-off-by: SurbhiAgarwal1 <agarwalsurbhi1807@gmail.com>
1 parent 492201d commit eeeced7

6 files changed

Lines changed: 67 additions & 55 deletions

File tree

token/config.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,17 @@ func NewConfiguration(cm driver.Configuration) *Configuration {
2222

2323
// IsSet checks to see if the key has been set in any of the data locations
2424
func (m *Configuration) IsSet(key string) bool {
25+
if m.cm == nil {
26+
return false
27+
}
2528
return m.cm.IsSet(key)
2629
}
2730

2831
// UnmarshalKey takes a single key and unmarshals it into a Struct
2932
func (m *Configuration) UnmarshalKey(key string, rawVal interface{}) error {
33+
if m.cm == nil {
34+
return nil
35+
}
3036
return m.cm.UnmarshalKey(key, rawVal)
3137
}
3238

@@ -42,7 +48,7 @@ func (m *Configuration) GetValidationConfig() (driver.ValidationConfig, error) {
4248
MaxTokenRequestSize: 2 * 1024 * 1024,
4349
MaxActionCount: 1000,
4450
}
45-
if m.cm.IsSet("validation") {
51+
if m.cm != nil && m.cm.IsSet("validation") {
4652
if err := m.cm.UnmarshalKey("validation", &config); err != nil {
4753
return config, err
4854
}

token/core/common/validator.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ func (v *Validator[P, T, TA, IA, DS]) VerifyTokenRequestFromRaw(ctx context.Cont
142142

143143
// Validate protocol version
144144
if tr.Version == 0 {
145-
return nil, nil, driver.ErrInvalidVersion
145+
tr.Version = uint32(driver.ProtocolV1)
146146
}
147147

148148
// Enforce minimum protocol version if configured

token/core/common/validator_version_test.go

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,10 @@ func TestMinProtocolVersionEnforcement(t *testing.T) {
2323
expectedError string
2424
}{
2525
{
26-
name: "Version 0 is always invalid",
26+
name: "Version 0 is treated as V1",
2727
minProtocolVersion: 0,
2828
requestVersion: 0,
29-
shouldFail: true,
30-
expectedError: "invalid token request: protocol version cannot be 0",
29+
shouldFail: false,
3130
},
3231
{
3332
name: "No minimum version set - accepts V1",
@@ -42,11 +41,10 @@ func TestMinProtocolVersionEnforcement(t *testing.T) {
4241
shouldFail: false,
4342
},
4443
{
45-
name: "Minimum V1 - rejects version 0",
44+
name: "Minimum V1 - accepts version 0 (as V1)",
4645
minProtocolVersion: driver.ProtocolV1,
4746
requestVersion: 0,
48-
shouldFail: true,
49-
expectedError: "invalid token request: protocol version cannot be 0",
47+
shouldFail: false,
5048
},
5149
{
5250
name: "Minimum V1 - accepts V1",
@@ -61,11 +59,11 @@ func TestMinProtocolVersionEnforcement(t *testing.T) {
6159
shouldFail: false,
6260
},
6361
{
64-
name: "Minimum V2 - rejects version 0",
62+
name: "Minimum V2 - rejects version 0 (as V1)",
6563
minProtocolVersion: driver.ProtocolV2,
6664
requestVersion: 0,
6765
shouldFail: true,
68-
expectedError: "invalid token request: protocol version cannot be 0",
66+
expectedError: "token request protocol version [1] is below minimum required version [2]",
6967
},
7068
{
7169
name: "Minimum V2 - rejects V1",
@@ -87,11 +85,13 @@ func TestMinProtocolVersionEnforcement(t *testing.T) {
8785
// Test the version check logic directly
8886
var err error
8987

90-
// First check: version 0 is always invalid
91-
if tt.requestVersion == 0 {
92-
err = assert.AnError // Simulate the error that would be returned
93-
} else if tt.minProtocolVersion > 0 && tt.requestVersion < tt.minProtocolVersion {
94-
// Second check: enforce minimum version if configured
88+
reqVersion := tt.requestVersion
89+
if reqVersion == 0 {
90+
reqVersion = 1
91+
}
92+
93+
if tt.minProtocolVersion > 0 && reqVersion < tt.minProtocolVersion {
94+
// Enforce minimum version if configured
9595
err = assert.AnError
9696
}
9797

@@ -113,13 +113,13 @@ func TestMinProtocolVersionLogic(t *testing.T) {
113113
shouldPass bool
114114
reason string
115115
}{
116-
{"V0 always invalid", 0, 0, false, "version 0 is invalid"},
116+
{"V0 treated as V1", 0, 0, true, ""},
117117
{"No min, V1 request", 0, driver.ProtocolV1, true, ""},
118118
{"No min, V2 request", 0, driver.ProtocolV2, true, ""},
119-
{"Min V1, V0 request", driver.ProtocolV1, 0, false, "version 0 is invalid"},
119+
{"Min V1, V0 request (as V1)", driver.ProtocolV1, 0, true, ""},
120120
{"Min V1, V1 request", driver.ProtocolV1, driver.ProtocolV1, true, ""},
121121
{"Min V1, V2 request", driver.ProtocolV1, driver.ProtocolV2, true, ""},
122-
{"Min V2, V0 request", driver.ProtocolV2, 0, false, "version 0 is invalid"},
122+
{"Min V2, V0 request (as V1)", driver.ProtocolV2, 0, false, "below minimum"},
123123
{"Min V2, V1 request", driver.ProtocolV2, driver.ProtocolV1, false, "below minimum"},
124124
{"Min V2, V2 request", driver.ProtocolV2, driver.ProtocolV2, true, ""},
125125
}
@@ -129,14 +129,14 @@ func TestMinProtocolVersionLogic(t *testing.T) {
129129
// Simulate the version check logic
130130
var passes bool
131131

132-
// First check: version 0 is always invalid
133-
if tt.requestVersion == 0 {
134-
passes = false
135-
} else {
136-
// Second check: enforce minimum version if configured
137-
passes = tt.minVersion == 0 || tt.requestVersion >= tt.minVersion
132+
reqVersion := tt.requestVersion
133+
if reqVersion == 0 {
134+
reqVersion = 1
138135
}
139136

137+
// Enforce minimum version if configured
138+
passes = tt.minVersion == 0 || reqVersion >= tt.minVersion
139+
140140
assert.Equal(t, tt.shouldPass, passes,
141141
"Version check logic mismatch: min=%d, request=%d, reason=%s",
142142
tt.minVersion, tt.requestVersion, tt.reason)

token/core/zkatdlog/nogh/v1/validator/regression/regression_test.go

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import (
1111
"encoding/base64"
1212
"encoding/json"
1313
"fmt"
14-
"path/filepath"
14+
"path"
1515
"testing"
1616

1717
"github.com/hyperledger-labs/fabric-token-sdk/token"
@@ -45,25 +45,25 @@ func TestRegression(t *testing.T) {
4545
t.Parallel()
4646
for _, root := range []string{"testdata", "testdata2", "testdata3"} {
4747
for _, action := range []string{"transfers", "issues", "redeems", "swaps"} {
48-
testRegressionParallel(t, filepath.Join(root, "32-BLS12_381_BBS_GURVY"), action+"_i1_o1")
49-
testRegressionParallel(t, filepath.Join(root, "32-BLS12_381_BBS_GURVY"), action+"_i1_o2")
50-
testRegressionParallel(t, filepath.Join(root, "32-BLS12_381_BBS_GURVY"), action+"_i2_o1")
51-
testRegressionParallel(t, filepath.Join(root, "32-BLS12_381_BBS_GURVY"), action+"_i2_o2")
52-
53-
testRegressionParallel(t, filepath.Join(root, "64-BLS12_381_BBS_GURVY"), action+"_i1_o1")
54-
testRegressionParallel(t, filepath.Join(root, "64-BLS12_381_BBS_GURVY"), action+"_i1_o2")
55-
testRegressionParallel(t, filepath.Join(root, "64-BLS12_381_BBS_GURVY"), action+"_i2_o1")
56-
testRegressionParallel(t, filepath.Join(root, "64-BLS12_381_BBS_GURVY"), action+"_i2_o2")
57-
58-
testRegressionParallel(t, filepath.Join(root, "32-BN254"), action+"_i1_o1")
59-
testRegressionParallel(t, filepath.Join(root, "32-BN254"), action+"_i1_o2")
60-
testRegressionParallel(t, filepath.Join(root, "32-BN254"), action+"_i2_o1")
61-
testRegressionParallel(t, filepath.Join(root, "32-BN254"), action+"_i2_o2")
62-
63-
testRegressionParallel(t, filepath.Join(root, "64-BN254"), action+"_i1_o1")
64-
testRegressionParallel(t, filepath.Join(root, "64-BN254"), action+"_i1_o2")
65-
testRegressionParallel(t, filepath.Join(root, "64-BN254"), action+"_i2_o1")
66-
testRegressionParallel(t, filepath.Join(root, "64-BN254"), action+"_i2_o2")
48+
testRegressionParallel(t, path.Join(root, "32-BLS12_381_BBS_GURVY"), action+"_i1_o1")
49+
testRegressionParallel(t, path.Join(root, "32-BLS12_381_BBS_GURVY"), action+"_i1_o2")
50+
testRegressionParallel(t, path.Join(root, "32-BLS12_381_BBS_GURVY"), action+"_i2_o1")
51+
testRegressionParallel(t, path.Join(root, "32-BLS12_381_BBS_GURVY"), action+"_i2_o2")
52+
53+
testRegressionParallel(t, path.Join(root, "64-BLS12_381_BBS_GURVY"), action+"_i1_o1")
54+
testRegressionParallel(t, path.Join(root, "64-BLS12_381_BBS_GURVY"), action+"_i1_o2")
55+
testRegressionParallel(t, path.Join(root, "64-BLS12_381_BBS_GURVY"), action+"_i2_o1")
56+
testRegressionParallel(t, path.Join(root, "64-BLS12_381_BBS_GURVY"), action+"_i2_o2")
57+
58+
testRegressionParallel(t, path.Join(root, "32-BN254"), action+"_i1_o1")
59+
testRegressionParallel(t, path.Join(root, "32-BN254"), action+"_i1_o2")
60+
testRegressionParallel(t, path.Join(root, "32-BN254"), action+"_i2_o1")
61+
testRegressionParallel(t, path.Join(root, "32-BN254"), action+"_i2_o2")
62+
63+
testRegressionParallel(t, path.Join(root, "64-BN254"), action+"_i1_o1")
64+
testRegressionParallel(t, path.Join(root, "64-BN254"), action+"_i1_o2")
65+
testRegressionParallel(t, path.Join(root, "64-BN254"), action+"_i2_o1")
66+
testRegressionParallel(t, path.Join(root, "64-BN254"), action+"_i2_o2")
6767
}
6868
}
6969
}
@@ -79,7 +79,7 @@ func testRegressionParallel(t *testing.T, rootDir, subFolder string) {
7979
func testRegression(t *testing.T, rootDir, subFolder string) {
8080
t.Helper()
8181
t.Logf("regression test for [%s:%s]", rootDir, subFolder)
82-
paramsData, err := testDataFS.ReadFile(filepath.Join(rootDir, "params.txt"))
82+
paramsData, err := testDataFS.ReadFile(path.Join(rootDir, "params.txt"))
8383
require.NoError(t, err)
8484

8585
ppRaw, err := base64.StdEncoding.DecodeString(string(paramsData))
@@ -93,7 +93,7 @@ func testRegression(t *testing.T, rootDir, subFolder string) {
9393
TXID string `json:"txid"`
9494
}
9595
for i := range 64 {
96-
filePath := filepath.Join(
96+
filePath := path.Join(
9797
rootDir,
9898
subFolder,
9999
fmt.Sprintf("output.%d.json", i),
@@ -144,7 +144,7 @@ func TestRegressionWithMinProtocolVersionV2(t *testing.T) {
144144
// Test with one representative sample from each testdata directory
145145
for _, root := range []string{"testdata", "testdata2", "testdata3"} {
146146
for _, variant := range []string{"32-BLS12_381_BBS_GURVY", "64-BLS12_381_BBS_GURVY", "32-BN254", "64-BN254"} {
147-
testRegressionWithMinVersionParallel(t, filepath.Join(root, variant), "transfers_i1_o1")
147+
testRegressionWithMinVersionParallel(t, path.Join(root, variant), "transfers_i1_o1")
148148
}
149149
}
150150
}
@@ -161,7 +161,7 @@ func testRegressionWithMinVersion(t *testing.T, rootDir, subFolder string) {
161161
t.Helper()
162162
t.Logf("regression test with MinProtocolVersion=V2 for [%s:%s]", rootDir, subFolder)
163163

164-
paramsData, err := testDataFS.ReadFile(filepath.Join(rootDir, "params.txt"))
164+
paramsData, err := testDataFS.ReadFile(path.Join(rootDir, "params.txt"))
165165
require.NoError(t, err)
166166

167167
ppRaw, err := base64.StdEncoding.DecodeString(string(paramsData))
@@ -177,7 +177,7 @@ func testRegressionWithMinVersion(t *testing.T, rootDir, subFolder string) {
177177
}
178178

179179
// Test just the first vector - all vectors in testdata are V1
180-
filePath := filepath.Join(rootDir, subFolder, "output.0.json")
180+
filePath := path.Join(rootDir, subFolder, "output.0.json")
181181
jsonData, err := testDataFS.ReadFile(filePath)
182182
require.NoError(t, err)
183183

token/driver/request.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,11 @@ func (r *TokenRequest) ToProtos() (*request.TokenRequest, error) {
141141
}
142142

143143
func (r *TokenRequest) FromProtos(tr *request.TokenRequest) error {
144+
// Default to ProtocolV1 if version is 0 (legacy requests)
145+
if tr.Version == 0 {
146+
tr.Version = uint32(ProtocolV1)
147+
}
148+
144149
// Validate version
145150
if tr.Version != uint32(ProtocolV1) && tr.Version != uint32(ProtocolV2) {
146151
return errors.Wrapf(ErrUnsupportedVersion, "expected [%d] or [%d], got [%d]", ProtocolV1, ProtocolV2, tr.Version)

token/tms.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -241,15 +241,16 @@ func (t *ManagementService) init() error {
241241
if err != nil {
242242
return errors.WithMessagef(err, "failed to get validator")
243243
}
244-
t.validator = &Validator{backend: validator}
245244
t.auth = &Authorization{Authorization: t.tms.Authorization()}
246245
t.conf = NewConfiguration(t.tms.Configuration())
247-
248-
vConfig, err := t.conf.GetValidationConfig()
249-
if err != nil {
250-
return errors.WithMessagef(err, "failed to get validation config")
246+
if validator != nil {
247+
t.validator = &Validator{backend: validator}
248+
vConfig, err := t.conf.GetValidationConfig()
249+
if err != nil {
250+
return errors.WithMessagef(err, "failed to get validation config")
251+
}
252+
t.validator.SetValidationConfig(vConfig)
251253
}
252-
t.validator.SetValidationConfig(vConfig)
253254

254255
t.tokensService = &TokensService{ts: t.tms.TokensService(), tus: t.tms.TokensUpgradeService()}
255256
t.publicParametersManager = &PublicParametersManager{

0 commit comments

Comments
 (0)