Skip to content

Commit cfe3923

Browse files
Gackotabbysable
andauthored
Controller: Several security fixes. (#13068)
Co-authored-by: Tabitha Sable <[email protected]>
1 parent 3a31ad2 commit cfe3923

File tree

7 files changed

+36
-15
lines changed

7 files changed

+36
-15
lines changed

internal/ingress/annotations/auth/main.go

+14-5
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package auth
1919
import (
2020
"fmt"
2121
"os"
22+
"path/filepath"
2223
"regexp"
2324
"strings"
2425

@@ -203,16 +204,24 @@ func (a auth) Parse(ing *networking.Ingress) (interface{}, error) {
203204
return nil, err
204205
}
205206

206-
passFilename := fmt.Sprintf("%v/%v-%v-%v.passwd", a.authDirectory, ing.GetNamespace(), ing.UID, secret.UID)
207+
passFileName := fmt.Sprintf("%v-%v-%v.passwd", ing.GetNamespace(), ing.UID, secret.UID)
208+
passFilePath := filepath.Join(a.authDirectory, passFileName)
209+
210+
// Ensure password file name does not contain any path traversal characters.
211+
if a.authDirectory != filepath.Dir(passFilePath) || passFileName != filepath.Base(passFilePath) {
212+
return nil, ing_errors.LocationDeniedError{
213+
Reason: fmt.Errorf("invalid password file name: %s", passFileName),
214+
}
215+
}
207216

208217
switch secretType {
209218
case fileAuth:
210-
err = dumpSecretAuthFile(passFilename, secret)
219+
err = dumpSecretAuthFile(passFilePath, secret)
211220
if err != nil {
212221
return nil, err
213222
}
214223
case mapAuth:
215-
err = dumpSecretAuthMap(passFilename, secret)
224+
err = dumpSecretAuthMap(passFilePath, secret)
216225
if err != nil {
217226
return nil, err
218227
}
@@ -225,9 +234,9 @@ func (a auth) Parse(ing *networking.Ingress) (interface{}, error) {
225234
return &Config{
226235
Type: at,
227236
Realm: realm,
228-
File: passFilename,
237+
File: passFilePath,
229238
Secured: true,
230-
FileSHA: file.SHA1(passFilename),
239+
FileSHA: file.SHA1(passFilePath),
231240
Secret: name,
232241
SecretType: secretType,
233242
}, nil

internal/ingress/controller/controller.go

+4
Original file line numberDiff line numberDiff line change
@@ -420,11 +420,15 @@ func (n *NGINXController) CheckIngress(ing *networking.Ingress) error {
420420
return err
421421
}
422422

423+
/* Deactivated to mitigate CVE-2025-1974
424+
// TODO: Implement sandboxing so this test can be done safely
423425
err = n.testTemplate(content)
424426
if err != nil {
425427
n.metricCollector.IncCheckErrorCount(ing.ObjectMeta.Namespace, ing.Name)
426428
return err
427429
}
430+
*/
431+
428432
n.metricCollector.IncCheckCount(ing.ObjectMeta.Namespace, ing.Name)
429433
endCheck := time.Now().UnixNano() / 1000000
430434
n.metricCollector.SetAdmissionMetrics(

internal/ingress/controller/controller_test.go

+3
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,8 @@ func TestCheckIngress(t *testing.T) {
250250
}
251251
})
252252

253+
/* Deactivated to mitigate CVE-2025-1974
254+
// TODO: Implement sandboxing so this test can be done safely
253255
t.Run("When nginx test returns an error", func(t *testing.T) {
254256
nginx.command = testNginxTestCommand{
255257
t: t,
@@ -261,6 +263,7 @@ func TestCheckIngress(t *testing.T) {
261263
t.Errorf("with a new ingress with an error, an error should be returned")
262264
}
263265
})
266+
*/
264267

265268
t.Run("When the default annotation prefix is used despite an override", func(t *testing.T) {
266269
defer func() {

internal/ingress/controller/template/template.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -1622,11 +1622,11 @@ func buildMirrorLocations(locs []*ingress.Location) string {
16221622
mapped.Insert(loc.Mirror.Source)
16231623
buffer.WriteString(fmt.Sprintf(`location = %v {
16241624
internal;
1625-
proxy_set_header Host "%v";
1626-
proxy_pass "%v";
1625+
proxy_set_header Host %v;
1626+
proxy_pass %v;
16271627
}
16281628
1629-
`, loc.Mirror.Source, loc.Mirror.Host, loc.Mirror.Target))
1629+
`, strconv.Quote(loc.Mirror.Source), strconv.Quote(loc.Mirror.Host), strconv.Quote(loc.Mirror.Target)))
16301630
}
16311631

16321632
return buffer.String()

rootfs/etc/nginx/template/nginx.tmpl

+3-3
Original file line numberDiff line numberDiff line change
@@ -879,7 +879,7 @@ stream {
879879

880880
{{ if not ( empty $server.CertificateAuth.MatchCN ) }}
881881
{{ if gt (len $server.CertificateAuth.MatchCN) 0 }}
882-
if ( $ssl_client_s_dn !~ {{ $server.CertificateAuth.MatchCN }} ) {
882+
if ( $ssl_client_s_dn !~ {{ $server.CertificateAuth.MatchCN | quote }} ) {
883883
return 403 "client certificate unauthorized";
884884
}
885885
{{ end }}
@@ -1082,7 +1082,7 @@ stream {
10821082
set $target {{ changeHostPort $externalAuth.URL $authUpstreamName }};
10831083
{{ else }}
10841084
proxy_http_version {{ $location.Proxy.ProxyHTTPVersion }};
1085-
set $target {{ $externalAuth.URL }};
1085+
set $target {{ $externalAuth.URL | quote }};
10861086
{{ end }}
10871087
proxy_pass $target;
10881088
}
@@ -1120,7 +1120,7 @@ stream {
11201120
{{ buildOpentelemetryForLocation $all.Cfg.EnableOpentelemetry $all.Cfg.OpentelemetryTrustIncomingSpan $location }}
11211121

11221122
{{ if $location.Mirror.Source }}
1123-
mirror {{ $location.Mirror.Source }};
1123+
mirror {{ $location.Mirror.Source | quote }};
11241124
mirror_request_body {{ $location.Mirror.RequestBody }};
11251125
{{ end }}
11261126

test/e2e/admission/admission.go

+6-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ import (
2626

2727
"github.com/onsi/ginkgo/v2"
2828
"github.com/stretchr/testify/assert"
29-
apierrors "k8s.io/apimachinery/pkg/api/errors"
3029
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3130

3231
"k8s.io/ingress-nginx/test/e2e/framework"
@@ -99,6 +98,8 @@ var _ = framework.IngressNginxDescribeSerial("[Admission] admission controller",
9998
assert.NotNil(ginkgo.GinkgoT(), err, "creating an ingress with invalid path should return an error")
10099
})
101100

101+
/* Deactivated to mitigate CVE-2025-1974
102+
// TODO: Implement sandboxing so this test can be done safely
102103
ginkgo.It("should return an error if there is an error validating the ingress definition", func() {
103104
disableSnippet := f.AllowSnippetConfiguration()
104105
defer disableSnippet()
@@ -112,6 +113,7 @@ var _ = framework.IngressNginxDescribeSerial("[Admission] admission controller",
112113
_, err := f.KubeClientSet.NetworkingV1().Ingresses(f.Namespace).Create(context.TODO(), firstIngress, metav1.CreateOptions{})
113114
assert.NotNil(ginkgo.GinkgoT(), err, "creating an ingress with invalid configuration should return an error")
114115
})
116+
*/
115117

116118
ginkgo.It("should return an error if there is an invalid value in some annotation", func() {
117119
host := admissionTestHost
@@ -207,6 +209,8 @@ var _ = framework.IngressNginxDescribeSerial("[Admission] admission controller",
207209
Status(http.StatusOK)
208210
})
209211

212+
/* Deactivated to mitigate CVE-2025-1974
213+
// TODO: Implement sandboxing so this test can be done safely
210214
ginkgo.It("should return an error if the Ingress V1 definition contains invalid annotations", func() {
211215
disableSnippet := f.AllowSnippetConfiguration()
212216
defer disableSnippet()
@@ -220,6 +224,7 @@ var _ = framework.IngressNginxDescribeSerial("[Admission] admission controller",
220224
assert.NotNil(ginkgo.GinkgoT(), err, "creating an ingress with invalid configuration should return an error")
221225
}
222226
})
227+
*/
223228

224229
ginkgo.It("should not return an error for an invalid Ingress when it has unknown class", func() {
225230
disableSnippet := f.AllowSnippetConfiguration()

test/e2e/annotations/mirror.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ var _ = framework.DescribeAnnotation("mirror-*", func() {
4343

4444
f.WaitForNginxServer(host,
4545
func(server string) bool {
46-
return strings.Contains(server, fmt.Sprintf("mirror /_mirror-%v;", ing.UID)) &&
46+
return strings.Contains(server, fmt.Sprintf("mirror \"/_mirror-%v\";", ing.UID)) &&
4747
strings.Contains(server, "mirror_request_body on;")
4848
})
4949
})
@@ -58,7 +58,7 @@ var _ = framework.DescribeAnnotation("mirror-*", func() {
5858

5959
f.WaitForNginxServer(host,
6060
func(server string) bool {
61-
return strings.Contains(server, fmt.Sprintf("mirror /_mirror-%v;", ing.UID)) &&
61+
return strings.Contains(server, fmt.Sprintf("mirror \"/_mirror-%v\";", ing.UID)) &&
6262
strings.Contains(server, "mirror_request_body on;") &&
6363
strings.Contains(server, `proxy_pass "https://test.env.com/$request_uri";`)
6464
})
@@ -75,7 +75,7 @@ var _ = framework.DescribeAnnotation("mirror-*", func() {
7575

7676
f.WaitForNginxServer(host,
7777
func(server string) bool {
78-
return strings.Contains(server, fmt.Sprintf("mirror /_mirror-%v;", ing.UID)) &&
78+
return strings.Contains(server, fmt.Sprintf("mirror \"/_mirror-%v\";", ing.UID)) &&
7979
strings.Contains(server, "mirror_request_body off;")
8080
})
8181
})

0 commit comments

Comments
 (0)