Skip to content

Commit c00c925

Browse files
authored
Merge pull request #348 from splitio/FME-16083
[FME-16083] Fixed vulnerabilities and issue using snapshot
2 parents 09e6e87 + c4dec41 commit c00c925

8 files changed

Lines changed: 180 additions & 16 deletions

File tree

CHANGES.txt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,16 @@
1+
5.12.5 (May 29, 2026)
2+
- Fixed vulnerabilities (8 Critical, 3 High, 5 Medium, 3 Low):
3+
- C: CVE-2026-39830, CVE-2026-39831, CVE-2026-39832, CVE-2026-39833, CVE-2026-39834, CVE-2026-42508, CVE-2026-39821
4+
- H: CVE-2026-4878, CVE-2026-4046, CVE-2026-4437
5+
- M: CVE-2026-4105, CVE-2026-40225, CVE-2026-40226, CVE-2026-4438, CVE-2026-29111
6+
- L: 3 low-severity vulnerabilities from debian base image update
7+
- Updated golang.org/x/crypto to v0.52.0
8+
- Updated golang.org/x/net to v0.55.0
9+
- Updated golang.org/x/sys to v0.45.0
10+
- Updated golang.org/x/text to v0.37.0
11+
- Updated debian base image to debian:13
12+
- Fixed segment initialization issue where segments were fetched from -1 when starting proxy with snapshot file
13+
114
5.12.4 (May 15, 2026)
215
- Fixed vulnerabilities:
316
- H: CVE-2026-39820, CVE-2026-42499, CVE-2026-33811, CVE-2026-33814, CVE-2026-39836

docker/Dockerfile.proxy

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ RUN bash -c 'if [[ "${FIPS_MODE}" = "enabled" ]]; \
1818
fi'
1919

2020
# Runner stage
21-
FROM debian:13.4 AS runner
21+
FROM debian:13 AS runner
2222

2323
RUN apt update -y && \
2424
apt upgrade -y && \

docker/Dockerfile.synchronizer

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ RUN bash -c 'if [[ "${FIPS_MODE}" = "enabled" ]]; \
1818
fi'
1919

2020
# Runner stage
21-
FROM debian:13.4 AS runner
21+
FROM debian:13 AS runner
2222

2323
RUN apt update -y && \
2424
apt upgrade -y && \

go.mod

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,11 @@ require (
4545
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
4646
github.com/ugorji/go/codec v1.3.0 // indirect
4747
golang.org/x/arch v0.26.0 // indirect
48-
golang.org/x/crypto v0.50.0 // indirect
49-
golang.org/x/net v0.53.0 // indirect
48+
golang.org/x/crypto v0.52.0 // indirect
49+
golang.org/x/net v0.55.0 // indirect
5050
golang.org/x/sync v0.20.0 // indirect
51-
golang.org/x/sys v0.43.0 // indirect
52-
golang.org/x/text v0.36.0 // indirect
51+
golang.org/x/sys v0.45.0 // indirect
52+
golang.org/x/text v0.37.0 // indirect
5353
google.golang.org/protobuf v1.36.8 // indirect
5454
gopkg.in/yaml.v3 v3.0.1 // indirect
5555
)

go.sum

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -99,20 +99,20 @@ go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU=
9999
go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4=
100100
golang.org/x/arch v0.26.0 h1:jZ6dpec5haP/fUv1kLCbuJy6dnRrfX6iVK08lZBFpk4=
101101
golang.org/x/arch v0.26.0/go.mod h1:0X+GdSIP+kL5wPmpK7sdkEVTt2XoYP0cSjQSbZBwOi8=
102-
golang.org/x/crypto v0.50.0 h1:zO47/JPrL6vsNkINmLoo/PH1gcxpls50DNogFvB5ZGI=
103-
golang.org/x/crypto v0.50.0/go.mod h1:3muZ7vA7PBCE6xgPX7nkzzjiUq87kRItoJQM1Yo8S+Q=
102+
golang.org/x/crypto v0.52.0 h1:RMs7fP2rXdep0CftQlK8Uf+kibLm7qkCcradZWYz988=
103+
golang.org/x/crypto v0.52.0/go.mod h1:1QgfPxDqh0T2M/elOJtp9RvuR95kVjir0e6/BvEmGbc=
104104
golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI=
105105
golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo=
106-
golang.org/x/net v0.53.0 h1:d+qAbo5L0orcWAr0a9JweQpjXF19LMXJE8Ey7hwOdUA=
107-
golang.org/x/net v0.53.0/go.mod h1:JvMuJH7rrdiCfbeHoo3fCQU24Lf5JJwT9W3sJFulfgs=
106+
golang.org/x/net v0.55.0 h1:bcvxaJn3e1U6InsFWt1JUq1aSjnRxLzT2rtD2KfkDF8=
107+
golang.org/x/net v0.55.0/go.mod h1:L5U2KuzuOe1lY7Z+aWVIKK6qEeJXnXV9yzGA+WCHJww=
108108
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
109109
golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
110110
golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
111111
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
112-
golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI=
113-
golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
114-
golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg=
115-
golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164=
112+
golang.org/x/sys v0.45.0 h1:dO4czNzziLiiXplLQgBCEpCvXQ3dnkn0SdaZSYdQ+FY=
113+
golang.org/x/sys v0.45.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
114+
golang.org/x/text v0.37.0 h1:Cqjiwd9eSg8e0QAkyCaQTNHFIIzWtidPahFWR83rTrc=
115+
golang.org/x/text v0.37.0/go.mod h1:a5sjxXGs9hsn/AJVwuElvCAo9v8QYLzvavO5z2PiM38=
116116
google.golang.org/protobuf v1.36.8 h1:xHScyCOEuuwZEc6UtSOvPbAT4zRh0xcNRYekJwfqyMc=
117117
google.golang.org/protobuf v1.36.8/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
118118
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

splitio/proxy/storage/persistent/segments.go

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,37 @@ type SegmentChangesCollectionImpl struct {
4040
mutex sync.RWMutex
4141
}
4242

43+
func (c *SegmentChangesCollectionImpl) initialize() error {
44+
all, err := c.FetchAll()
45+
if err != nil {
46+
// TODO
47+
return err
48+
}
49+
50+
tills := make(map[string]int64)
51+
for _, segment := range all {
52+
var cn int64 // 0
53+
for _, key := range segment.Keys {
54+
if key.ChangeNumber > cn {
55+
cn = key.ChangeNumber
56+
}
57+
}
58+
tills[segment.Name] = cn
59+
}
60+
61+
c.segmentsTill = tills
62+
return nil
63+
}
64+
4365
// NewSegmentChangesCollection returns an instance of SegmentChangesCollection
4466
func NewSegmentChangesCollection(db DBWrapper, logger logging.LoggerInterface) *SegmentChangesCollectionImpl {
45-
return &SegmentChangesCollectionImpl{
67+
collection := &SegmentChangesCollectionImpl{
4668
collection: &BoltDBCollectionWrapper{db: db, name: segmentChangesCollectionName, logger: logger},
4769
segmentsTill: make(map[string]int64, 0),
4870
logger: logger,
4971
}
72+
collection.initialize()
73+
return collection
5074
}
5175

5276
// Update persists a segmentChanges update

splitio/proxy/storage/persistent/segments_test.go

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,3 +56,130 @@ func TestSegmentPersistentStorage(t *testing.T) {
5656
t.Error("k1 should be removed")
5757
}
5858
}
59+
60+
func TestNewSegmentChangesCollectionInitializesChangeNumbers(t *testing.T) {
61+
dbw, err := NewBoltWrapper(BoltInMemoryMode, nil)
62+
if err != nil {
63+
t.Error("error creating bolt wrapper: ", err)
64+
}
65+
66+
logger := logging.NewLogger(nil)
67+
68+
// First, create a collection and add some segments with different change numbers
69+
segmentC := NewSegmentChangesCollection(dbw, logger)
70+
71+
// Add segment s1 with keys at change number 10
72+
segmentC.Update("s1", set.NewSet("k1", "k2"), set.NewSet(), 10)
73+
74+
// Add more keys to s1 at change number 20
75+
segmentC.Update("s1", set.NewSet("k3"), set.NewSet(), 20)
76+
77+
// Add segment s2 with keys at change number 15
78+
segmentC.Update("s2", set.NewSet("k4", "k5"), set.NewSet(), 15)
79+
80+
// Verify change numbers are set correctly after updates
81+
if cn := segmentC.ChangeNumber("s1"); cn != 20 {
82+
t.Errorf("s1 change number should be 20, got %d", cn)
83+
}
84+
85+
if cn := segmentC.ChangeNumber("s2"); cn != 15 {
86+
t.Errorf("s2 change number should be 15, got %d", cn)
87+
}
88+
89+
// Now create a NEW collection from the same database (simulating a restart with snapshot)
90+
segmentC2 := NewSegmentChangesCollection(dbw, logger)
91+
92+
// Verify that the change numbers were initialized correctly from the stored data
93+
if cn := segmentC2.ChangeNumber("s1"); cn != 20 {
94+
t.Errorf("After initialization, s1 change number should be 20, got %d", cn)
95+
}
96+
97+
if cn := segmentC2.ChangeNumber("s2"); cn != 15 {
98+
t.Errorf("After initialization, s2 change number should be 15, got %d", cn)
99+
}
100+
101+
// Verify non-existent segment returns -1
102+
if cn := segmentC2.ChangeNumber("nonexistent"); cn != -1 {
103+
t.Errorf("Non-existent segment should return -1, got %d", cn)
104+
}
105+
}
106+
107+
func TestInitializeWithEmptyDatabase(t *testing.T) {
108+
dbw, err := NewBoltWrapper(BoltInMemoryMode, nil)
109+
if err != nil {
110+
t.Error("error creating bolt wrapper: ", err)
111+
}
112+
113+
logger := logging.NewLogger(nil)
114+
115+
// Create a collection on an empty database
116+
segmentC := NewSegmentChangesCollection(dbw, logger)
117+
118+
// Should not panic and should return -1 for any segment
119+
if cn := segmentC.ChangeNumber("any_segment"); cn != -1 {
120+
t.Errorf("Empty database should return -1 for any segment, got %d", cn)
121+
}
122+
}
123+
124+
func TestInitializeWithRemovedKeys(t *testing.T) {
125+
dbw, err := NewBoltWrapper(BoltInMemoryMode, nil)
126+
if err != nil {
127+
t.Error("error creating bolt wrapper: ", err)
128+
}
129+
130+
logger := logging.NewLogger(nil)
131+
segmentC := NewSegmentChangesCollection(dbw, logger)
132+
133+
// Add keys at change number 10
134+
segmentC.Update("s1", set.NewSet("k1", "k2", "k3"), set.NewSet(), 10)
135+
136+
// Remove some keys at change number 25
137+
segmentC.Update("s1", set.NewSet(), set.NewSet("k1"), 25)
138+
139+
// Add new keys at change number 30
140+
segmentC.Update("s1", set.NewSet("k4"), set.NewSet(), 30)
141+
142+
// The max change number should be 30
143+
if cn := segmentC.ChangeNumber("s1"); cn != 30 {
144+
t.Errorf("s1 change number should be 30, got %d", cn)
145+
}
146+
147+
// Create new collection to test initialization
148+
segmentC2 := NewSegmentChangesCollection(dbw, logger)
149+
150+
// Should pick up the maximum change number (30) even with mixed add/remove operations
151+
if cn := segmentC2.ChangeNumber("s1"); cn != 30 {
152+
t.Errorf("After initialization with removed keys, s1 change number should be 30, got %d", cn)
153+
}
154+
}
155+
156+
func TestInitializeMultipleSegments(t *testing.T) {
157+
dbw, err := NewBoltWrapper(BoltInMemoryMode, nil)
158+
if err != nil {
159+
t.Error("error creating bolt wrapper: ", err)
160+
}
161+
162+
logger := logging.NewLogger(nil)
163+
segmentC := NewSegmentChangesCollection(dbw, logger)
164+
165+
// Create multiple segments with different change numbers
166+
segments := map[string]int64{
167+
"segment_a": 100,
168+
"segment_b": 250,
169+
"segment_c": 50,
170+
"segment_d": 999,
171+
}
172+
173+
for name, cn := range segments {
174+
segmentC.Update(name, set.NewSet("key1", "key2"), set.NewSet(), cn)
175+
}
176+
177+
// Create new collection and verify all segments are initialized correctly
178+
segmentC2 := NewSegmentChangesCollection(dbw, logger)
179+
180+
for name, expectedCN := range segments {
181+
if cn := segmentC2.ChangeNumber(name); cn != expectedCN {
182+
t.Errorf("Segment %s should have change number %d, got %d", name, expectedCN, cn)
183+
}
184+
}
185+
}

splitio/version.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22
package splitio
33

44
// Version is the version of this Agent
5-
const Version = "5.12.4"
5+
const Version = "5.12.5"

0 commit comments

Comments
 (0)