Repository: smallstep/crypto
Pull request #13 (2020-12-17 20:44:55)

Escape strings in X.509 templates.
### Description

Fixes JSON injection in IID templates.

Related to smallstep/certificates#435


Patch:
diff --git a/Makefile b/Makefile
index 6dae8a0..af87dc9 100644
--- a/Makefile
+++ b/Makefile
@@ -10,7 +10,7 @@ all: lint test
 #########################################
 
 bootstrap:
-	$Q GO111MODULE=on go get github.com/golangci/golangci-lint/cmd/golangci-lint@v1.30.0
+	$Q GO111MODULE=on go get github.com/golangci/golangci-lint/cmd/golangci-lint@v1.33.0
 
 .PHONY: bootstrap
 
diff --git a/internal/bcrypt_pbkdf/bcrypt_pbkdf.go b/internal/bcrypt_pbkdf/bcrypt_pbkdf.go
index fcd7495..863ef1d 100644
--- a/internal/bcrypt_pbkdf/bcrypt_pbkdf.go
+++ b/internal/bcrypt_pbkdf/bcrypt_pbkdf.go
@@ -13,7 +13,7 @@ import (
 	// NOTE! Requires blowfish package version from Aug 1, 2014 or later.
 	// Will produce incorrect results if the package is older.
 	// See commit message for details: http://goo.gl/wx6g8O
-	//nolint:deprecated
+	//nolint:staticcheck
 	"golang.org/x/crypto/blowfish"
 )
 
diff --git a/x509util/templates.go b/x509util/templates.go
index 45ad9a3..bdfce60 100644
--- a/x509util/templates.go
+++ b/x509util/templates.go
@@ -112,7 +112,7 @@ const DefaultLeafTemplate = `{
 // can be provided to force only the verified domains, if the option is true
 // `.SANs` will be set with the verified domains.
 const DefaultIIDLeafTemplate = `{
-	"subject": {"commonName":"{{ .Insecure.CR.Subject.CommonName }}"},
+	"subject": {"commonName": {{ toJson .Insecure.CR.Subject.CommonName }}},
 {{- if .SANs }}
 	"sans": {{ toJson .SANs }},
 {{- else }}


Test patch:
diff --git a/x509util/certificate_request_test.go b/x509util/certificate_request_test.go
index 1e294f9..47c3b88 100644
--- a/x509util/certificate_request_test.go
+++ b/x509util/certificate_request_test.go
@@ -202,7 +202,7 @@ func TestCertificateRequest_GetCertificateRequest(t *testing.T) {
 				got.RawSubject = nil
 				got.RawSubjectPublicKeyInfo = nil
 				got.RawTBSCertificateRequest = nil
-				got.Attributes = nil //nolint:deprecated
+				got.Attributes = nil //nolint:staticcheck
 			}
 			if !reflect.DeepEqual(got, tt.want) {
 				t.Errorf("CertificateRequest.GetCertificateRequest() = %v, want %v", got, tt.want)
@@ -433,7 +433,7 @@ func TestCreateCertificateRequest(t *testing.T) {
 				tt.want.RawSubject = got.RawSubject
 				tt.want.RawSubjectPublicKeyInfo = got.RawSubjectPublicKeyInfo
 				tt.want.RawTBSCertificateRequest = got.RawTBSCertificateRequest
-				tt.want.Attributes = got.Attributes //nolint:deprecated
+				tt.want.Attributes = got.Attributes //nolint:staticcheck
 				tt.want.Extensions = got.Extensions
 				tt.want.Signature = got.Signature
 			}
diff --git a/x509util/options_test.go b/x509util/options_test.go
index 89a867b..db876f4 100644
--- a/x509util/options_test.go
+++ b/x509util/options_test.go
@@ -58,6 +58,7 @@ func Test_getFuncMap_fail(t *testing.T) {
 func TestWithTemplate(t *testing.T) {
 	cr, _ := createCertificateRequest(t, "foo", []string{"foo.com", "foo@foo.com", "::1", "https://foo.com"})
 	crRSA, _ := createRSACertificateRequest(t, 2048, "foo", []string{"foo.com", "foo@foo.com", "::1", "https://foo.com"})
+	crQuotes, _ := createCertificateRequest(t, `foo"}`, []string{"foo.com", "foo@foo.com", "::1", "https://foo.com"})
 	type args struct {
 		text string
 		data TemplateData
@@ -93,7 +94,7 @@ func TestWithTemplate(t *testing.T) {
 		}, false},
 		{"iid", args{DefaultIIDLeafTemplate, TemplateData{}, cr}, Options{
 			CertBuffer: bytes.NewBufferString(`{
-	"subject": {"commonName":"foo"},
+	"subject": {"commonName": "foo"},
 	"dnsNames": ["foo.com"],
 	"emailAddresses": ["foo@foo.com"],
 	"ipAddresses": ["::1"],
@@ -106,10 +107,21 @@ func TestWithTemplate(t *testing.T) {
 			SANsKey: []SubjectAlternativeName{{Type: "dns", Value: "foo.com"}},
 		}, crRSA}, Options{
 			CertBuffer: bytes.NewBufferString(`{
-	"subject": {"commonName":"foo"},
+	"subject": {"commonName": "foo"},
 	"sans": [{"type":"dns","value":"foo.com"}],
 	"keyUsage": ["keyEncipherment", "digitalSignature"],
 	"extKeyUsage": ["serverAuth", "clientAuth"]
+}`),
+		}, false},
+		{"iidEscape", args{DefaultIIDLeafTemplate, TemplateData{}, crQuotes}, Options{
+			CertBuffer: bytes.NewBufferString(`{
+	"subject": {"commonName": "foo\"}"},
+	"dnsNames": ["foo.com"],
+	"emailAddresses": ["foo@foo.com"],
+	"ipAddresses": ["::1"],
+	"uris": ["https://foo.com"],
+	"keyUsage": ["digitalSignature"],
+	"extKeyUsage": ["serverAuth", "clientAuth"]
 }`),
 		}, false},
 		{"admin", args{DefaultAdminLeafTemplate, TemplateData{}, cr}, Options{