diff --git a/go.mod b/go.mod index caf90388a..b82091ed1 100644 --- a/go.mod +++ b/go.mod @@ -37,6 +37,7 @@ require ( github.com/go-enry/go-oniguruma v1.2.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.2 // indirect + github.com/google/addlicense v1.0.0 // indirect github.com/gorilla/mux v1.8.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/inconshreveable/mousetrap v1.0.0 // indirect @@ -61,6 +62,7 @@ require ( golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 // indirect golang.org/x/mod v0.5.1 // indirect golang.org/x/net v0.0.0-20211011170408-caeb26a5c8c0 // indirect + golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect golang.org/x/sys v0.0.0-20211013075003-97ac67df715c // indirect golang.org/x/text v0.3.7 // indirect golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba // indirect diff --git a/go.sum b/go.sum index 4c25d0227..40c8f843d 100644 --- a/go.sum +++ b/go.sum @@ -445,6 +445,8 @@ github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/addlicense v1.0.0 h1:cqvo5suPWlsk6r6o42Fs2K66xYCl2tnhVPUYoP3EnO4= +github.com/google/addlicense v1.0.0/go.mod h1:Sm/DHu7Jk+T5miFHHehdIjbi4M5+dJDRS3Cq0rncIxA= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -1179,6 +1181,7 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= diff --git a/internal/services/engines/csharp/rules_test.go b/internal/services/engines/csharp/rules_test.go new file mode 100644 index 000000000..a7154b9fc --- /dev/null +++ b/internal/services/engines/csharp/rules_test.go @@ -0,0 +1,48 @@ +// Copyright 2021 ZUP IT SERVICOS EM TECNOLOGIA E INOVACAO SA +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package csharp + +import ( + "testing" + + engine "github.com/ZupIT/horusec-engine" + "github.com/ZupIT/horusec/internal/utils/testutil" +) + +func TestRulesVulnerableCode(t *testing.T) { + testcases := []*testutil.RuleTestCase{ + { + Name: "HS-CSHARP-1", + Rule: NewCommandInjection(), + Src: SampleVulnerableCsharpNewCommandInjection, + Findings: []engine.Finding{ + { + CodeSample: "var p = new Process();", + SourceLocation: engine.Location{ + Line: 1, + Column: 8, + }, + }, + }, + }, + } + testutil.TestVulnerableCode(t, testcases) +} + +func TestRulesSafeCode(t *testing.T) { + testcases := []*testutil.RuleTestCase{} + + testutil.TestSafeCode(t, testcases) +} diff --git a/internal/services/engines/csharp/samples_test.go b/internal/services/engines/csharp/samples_test.go new file mode 100644 index 000000000..3e59b55a5 --- /dev/null +++ b/internal/services/engines/csharp/samples_test.go @@ -0,0 +1,22 @@ +// Copyright 2021 ZUP IT SERVICOS EM TECNOLOGIA E INOVACAO SA +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package csharp + +const ( + SampleVulnerableCsharpNewCommandInjection = `var p = new Process(); +p.StartInfo.FileName = "exportLegacy.exe"; +p.StartInfo.Arguments = " -user " + input + " -role user"; +p.Start();` +) diff --git a/internal/services/engines/dart/rules_test.go b/internal/services/engines/dart/rules_test.go new file mode 100644 index 000000000..bff34890a --- /dev/null +++ b/internal/services/engines/dart/rules_test.go @@ -0,0 +1,49 @@ +// Copyright 2021 ZUP IT SERVICOS EM TECNOLOGIA E INOVACAO SA +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package dart + +import ( + "testing" + + engine "github.com/ZupIT/horusec-engine" + "github.com/ZupIT/horusec/internal/utils/testutil" +) + +func TestRulesVulnerableCode(t *testing.T) { + testcases := []*testutil.RuleTestCase{ + { + Name: "HS-DART-6", + Rule: NewSendSMS(), + Src: SampleVulnerableDartSendSMS, + Findings: []engine.Finding{ + { + CodeSample: "import 'package:flutter_sms/flutter_sms.dart';", + SourceLocation: engine.Location{ + Line: 1, + Column: 28, + }, + }, + }, + }, + } + + testutil.TestVulnerableCode(t, testcases) +} + +func TestRulesSafeCode(t *testing.T) { + testcases := []*testutil.RuleTestCase{} + + testutil.TestSafeCode(t, testcases) +} diff --git a/internal/services/engines/dart/sample_test.go b/internal/services/engines/dart/sample_test.go new file mode 100644 index 000000000..d98f130b0 --- /dev/null +++ b/internal/services/engines/dart/sample_test.go @@ -0,0 +1,20 @@ +// Copyright 2021 ZUP IT SERVICOS EM TECNOLOGIA E INOVACAO SA +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package dart + +const ( + SampleVulnerableDartSendSMS = `import 'package:flutter_sms/flutter_sms.dart'; +` +) diff --git a/internal/services/engines/java/rules_test.go b/internal/services/engines/java/rules_test.go new file mode 100644 index 000000000..cb9086c41 --- /dev/null +++ b/internal/services/engines/java/rules_test.go @@ -0,0 +1,68 @@ +// Copyright 2021 ZUP IT SERVICOS EM TECNOLOGIA E INOVACAO SA +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package java + +import ( + engine "github.com/ZupIT/horusec-engine" + "testing" + + "github.com/ZupIT/horusec/internal/utils/testutil" +) + +func TestRulesVulnerableCode(t *testing.T) { + testcases := []*testutil.RuleTestCase{ + { + Name: "HS-JAVA-1", + Rule: NewXMLParsingVulnerableToXXE(), + Src: SampleVulnerableJavaXMLParsingVulnerableToXXE, + Findings: []engine.Finding{ + { + CodeSample: `XMLReader reader = XMLReaderFactory.createXMLReader();`, + SourceLocation: engine.Location{ + Line: 4, + Column: 21, + }, + }, + }, + }, + { + Name: "HS-JAVA-134", + Rule: NewSQLInjection(), + Src: SampleVulnerableJavaSQLInjection, + Findings: []engine.Finding{ + { + CodeSample: "var pstmt = con.prepareStatement(\"select * from mytable where field01 = '\" + field01 + \"'\");", + SourceLocation: engine.Location{ + Line: 14, + Column: 50, + }, + }, + }, + }, + } + + testutil.TestVulnerableCode(t, testcases) +} + +func TestRulesSafeCode(t *testing.T) { + testcases := []*testutil.RuleTestCase{ + { + Name: "HS-JAVA-134", + Rule: NewSQLInjection(), + Src: SampleSafeJavaSQLInjection, + }, + } + testutil.TestSafeCode(t, testcases) +} diff --git a/internal/services/engines/java/sample_test.go b/internal/services/engines/java/sample_test.go new file mode 100644 index 000000000..e83467cc8 --- /dev/null +++ b/internal/services/engines/java/sample_test.go @@ -0,0 +1,72 @@ +// Copyright 2021 ZUP IT SERVICOS EM TECNOLOGIA E INOVACAO SA +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package java + +const ( + SampleVulnerableJavaSQLInjection = ` +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; + +import javax.sql.DataSource; + +public class VulnerableCodeSQLInjection134 { + + public void printResults(DataSource ds, String field01) throws SQLException { + try ( + var con = ds.getConnection(); + var pstmt = con.prepareStatement("select * from mytable where field01 = '" + field01 + "'"); + var rs = pstmt.executeQuery()) { + while (rs.next()) { + System.out.println(rs.getString(1)); + } + } + } +} +` + + SampleSafeJavaSQLInjection = ` +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; + +import javax.sql.DataSource; + +public class VulnerableCodeSQLInjection134 { + + public void printResults(DataSource ds, String field01) throws SQLException { + try { + var con = ds.getConnection(); + var pstmt = con.prepareStatement("select * from mytable where field01 = ? "); + pstmt.setString(1,field01); + var rs = pstmt.executeQuery(); + while (rs.next()) { + System.out.println(rs.getString(1)); + } + } + } +} +` + SampleVulnerableJavaXMLParsingVulnerableToXXE = ` +class Foo { + void fn(String input) { + XMLReader reader = XMLReaderFactory.createXMLReader(); + reader.parse(input) + } +} + ` +) diff --git a/internal/services/engines/jvm/rules_test.go b/internal/services/engines/jvm/rules_test.go new file mode 100644 index 000000000..14ae8b360 --- /dev/null +++ b/internal/services/engines/jvm/rules_test.go @@ -0,0 +1,33 @@ +// Copyright 2021 ZUP IT SERVICOS EM TECNOLOGIA E INOVACAO SA +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package jvm + +import ( + "testing" + + "github.com/ZupIT/horusec/internal/utils/testutil" +) + +func TestRulesVulnerableCode(t *testing.T) { + testcases := []*testutil.RuleTestCase{} + + testutil.TestVulnerableCode(t, testcases) +} + +func TestRulesSafeCode(t *testing.T) { + testcases := []*testutil.RuleTestCase{} + + testutil.TestSafeCode(t, testcases) +} diff --git a/internal/services/engines/jvm/samples_test.go b/internal/services/engines/jvm/samples_test.go new file mode 100644 index 000000000..3b756d8d6 --- /dev/null +++ b/internal/services/engines/jvm/samples_test.go @@ -0,0 +1,17 @@ +// Copyright 2021 ZUP IT SERVICOS EM TECNOLOGIA E INOVACAO SA +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package jvm + +const () diff --git a/internal/services/engines/kubernetes/rules_test.go b/internal/services/engines/kubernetes/rules_test.go new file mode 100644 index 000000000..e21baac39 --- /dev/null +++ b/internal/services/engines/kubernetes/rules_test.go @@ -0,0 +1,55 @@ +// Copyright 2021 ZUP IT SERVICOS EM TECNOLOGIA E INOVACAO SA +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package kubernetes + +import ( + "testing" + + engine "github.com/ZupIT/horusec-engine" + "github.com/ZupIT/horusec/internal/utils/testutil" +) + +func TestRulesVulnerableCode(t *testing.T) { + testcases := []*testutil.RuleTestCase{ + { + Name: "HS-KUBERNETES-1", + Rule: NewAllowPrivilegeEscalation(), + Src: SampleVulnerableAllowPrivilegeEscalation, + Findings: []engine.Finding{ + { + CodeSample: "allowPrivilegeEscalation: true", + SourceLocation: engine.Location{ + Line: 10, + Column: 1, + }, + }, + }, + }, + } + + testutil.TestVulnerableCode(t, testcases) +} + +func TestRulesSafeCode(t *testing.T) { + testcases := []*testutil.RuleTestCase{ + { + Name: "HS-KUBERNETES-1", + Rule: NewAllowPrivilegeEscalation(), + Src: SampleSafeAllowPrivilegeEscalation, + }, + } + + testutil.TestSafeCode(t, testcases) +} diff --git a/internal/services/engines/kubernetes/samples_test.go b/internal/services/engines/kubernetes/samples_test.go new file mode 100644 index 000000000..c2538cfd5 --- /dev/null +++ b/internal/services/engines/kubernetes/samples_test.go @@ -0,0 +1,57 @@ +// Copyright 2021 ZUP IT SERVICOS EM TECNOLOGIA E INOVACAO SA +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package kubernetes + +const ( + SampleVulnerableAllowPrivilegeEscalation = `apiVersion: v1 +kind: Pod +metadata: + name: security-context-demo +spec: + securityContext: + runAsUser: 1000 + runAsGroup: 3000 + fsGroup: 2000 + allowPrivilegeEscalation: true + volumes: + - name: sec-ctx-vol + emptyDir: {} + containers: + - name: sec-ctx-demo + image: busybox + command: [ "sh", "-c", "sleep 1h" ] + volumeMounts: + - name: sec-ctx-vol + mountPath: /data/demo` + SampleSafeAllowPrivilegeEscalation = `apiVersion: v1 +kind: Pod +metadata: + name: security-context-demo +spec: + securityContext: + runAsUser: 1000 + runAsGroup: 3000 + fsGroup: 2000 + volumes: + - name: sec-ctx-vol + emptyDir: {} + containers: + - name: sec-ctx-demo + image: busybox + command: [ "sh", "-c", "sleep 1h" ] + volumeMounts: + - name: sec-ctx-vol + mountPath: /data/demo` +) diff --git a/internal/services/engines/leaks/rules_test.go b/internal/services/engines/leaks/rules_test.go new file mode 100644 index 000000000..7e0091d74 --- /dev/null +++ b/internal/services/engines/leaks/rules_test.go @@ -0,0 +1,573 @@ +// Copyright 2021 ZUP IT SERVICOS EM TECNOLOGIA E INOVACAO SA +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package leaks + +import ( + "testing" + + engine "github.com/ZupIT/horusec-engine" + "github.com/ZupIT/horusec/internal/utils/testutil" +) + +func TestRulesVulnerableCode(t *testing.T) { + testcases := []*testutil.RuleTestCase{ + { + Name: "HS-LEAKS-1", + Rule: NewAWSManagerID(), + Src: SampleVulnerableLeaksRegularAWSManagerID, + Findings: []engine.Finding{ + { + CodeSample: "ACCESS_KEY: 'AKIAJSIE27KKMHXI3BJQ'", + SourceLocation: engine.Location{ + Line: 7, + Column: 18, + }, + }, + }, + }, + { + Name: "HS-LEAKS-2", + Rule: NewAWSSecretKey(), + Src: SampleVulnerableLeaksRegularAWSSecretKey, + Findings: []engine.Finding{ + { + CodeSample: `AWS_SECRET_KEY: 'doc5eRXFpsWllGC5yKJV/Ymm5KwF+IRZo95EudOm'`, + SourceLocation: engine.Location{ + Line: 7, + Column: 6, + }, + }, + }, + }, + { + Name: "HS-LEAKS-3", + Rule: NewAWSMWSKey(), + Src: SampleVulnerableLeaksRegularAWSMWSKey, + Findings: []engine.Finding{ + { + CodeSample: `AWS_WMS_KEY: 'amzn.mws.986478f0-9775-eabc-2af4-e499a8496828'`, + SourceLocation: engine.Location{ + Line: 7, + Column: 20, + }, + }, + }, + }, + { + Name: "HS-LEAKS-4", + Rule: NewFacebookSecretKey(), + Src: SampleVulnerableLeaksRegularFacebookSecretKey, + Findings: []engine.Finding{ + { + CodeSample: `FB_SECRET_KEY: 'cb6f53505911332d30867f44a1c1b9b5'`, + SourceLocation: engine.Location{ + Line: 7, + Column: 6, + }, + }, + }, + }, + { + Name: "HS-LEAKS-5", + Rule: NewFacebookClientID(), + Src: SampleVulnerableLeaksRegularFacebookClientID, + Findings: []engine.Finding{ + { + CodeSample: `FB_CLIENT_ID: '148695999071979'`, + SourceLocation: engine.Location{ + Line: 7, + Column: 6, + }, + }, + }, + }, + { + Name: "HS-LEAKS-7", + Rule: NewTwitterClientID(), + Src: SampleVulnerableLeaksRegularTwitterClientID, + Findings: []engine.Finding{ + { + CodeSample: `TWITTER_CLIENT_ID: '1h6433fsvygnyre5a40'`, + SourceLocation: engine.Location{ + Line: 7, + Column: 6, + }, + }, + }, + }, + { + Name: "LEAKS-6", + Rule: NewTwitterSecretKey(), + Src: SampleVulnerableLeaksRegularTwitterSecretKey, + Findings: []engine.Finding{ + { + CodeSample: `TWITTER_SECRET_KEY: 'ej64cqk9k8px9ae3e47ip89l7if58tqhpxi1r'`, + SourceLocation: engine.Location{ + Line: 7, + Column: 6, + }, + }, + }, + }, + { + Name: "HS-LEAKS-8", + Rule: NewGithub(), + Src: SampleVulnerableLeaksRegularGithub, + Findings: []engine.Finding{ + { + CodeSample: `GITHUB_SECRET_KEY: 'edzvPbU3SYUc7pFc9le20lzIRErTOaxCABQ1'`, + SourceLocation: engine.Location{ + Line: 7, + Column: 6, + }, + }, + }, + }, + { + Name: "HS-LEAKS-9", + Rule: NewLinkedInClientID(), + Src: SampleVulnerableLeaksRegularLinkedInClientID, + Findings: []engine.Finding{ + { + CodeSample: `LINKEDIN_CLIENT_ID: 'g309xttlaw25'`, + SourceLocation: engine.Location{ + Line: 7, + Column: 6, + }, + }, + }, + }, + { + Name: "LEAKS-10", + Rule: NewLinkedInSecretKey(), + Src: SampleVulnerableLeaksRegularLinkedInSecretKey, + Findings: []engine.Finding{ + { + CodeSample: `LINKEDIN_SECRET_KEY: '0d16kcnjyfzmcmjp'`, + SourceLocation: engine.Location{ + Line: 7, + Column: 6, + }, + }, + }, + }, + { + Name: "LEAKS-11", + Rule: NewSlack(), + Src: SampleVulnerableLeaksRegularSlack, + Findings: []engine.Finding{ + { + CodeSample: `SLACK_WEBHOOK: 'https://hooks.slack.com/services/TNeqvYPeO/BncTJ74Hf/NlvFFKKAKPkd6h7FlQCz1Blu'`, + SourceLocation: engine.Location{ + Line: 7, + Column: 22, + }, + }, + }, + }, + { + Name: "HS-LEAKS-12", + Rule: NewAsymmetricPrivateKey(), + Src: SampleVulnerableLeaksRegularAsymmetricPrivateKey, + Findings: []engine.Finding{ + { + CodeSample: `SSH_PRIVATE_KEY: '-----BEGIN PRIVATE KEY-----MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDBj08sp5++4anGcmQxJjAkBgNVBAoTHVByb2dyZXNzIFNvZnR3YXJlIENvcnBvcmF0aW9uMSAwHgYDVQQDDBcqLmF3cy10ZXN0LnByb2dyZXNzLmNvbTCCASIwDQYJKoZIhvcNAQEBBQAD...bml6YXRpb252YWxzaGEyZzIuY3JsMIGgBggrBgEFBQcBAQSBkzCBkDBNBggrBgEFBQcwAoZBaHR0cDovL3NlY3VyZS5nbG9iYWxzaWduLmNvbS9jYWNlcnQvZ3Nvcmdhz3P668YfhUbKdRF6S42Cg6zn-----END PRIVATE KEY-----'`, + SourceLocation: engine.Location{ + Line: 7, + Column: 24, + }, + }, + }, + }, + { + Name: "HS-LEAKS-13", + Rule: NewGoogleAPIKey(), + Src: SampleVulnerableLeaksRegularGoogleAPIKey, + Findings: []engine.Finding{ + { + CodeSample: `GCP_API_KEY: 'AIzaMPZHYiu1RdzE1nG2SaVyOoz244TuacQIR6m'`, + SourceLocation: engine.Location{ + Line: 7, + Column: 20, + }, + }, + }, + }, + { + Name: "HS-LEAKS-14", + Rule: NewGoogleGCPServiceAccount(), + Src: SampleVulnerableLeaksRegularGoogleGCPServiceAccount, + Findings: []engine.Finding{ + { + CodeSample: `GCP_SERVICE_ACCOUNT: '18256698220617903267772185514630273595-oy8_uzouz8tyy46y84ckrwei9_6rq_pb.apps.googleusercontent.com'`, + SourceLocation: engine.Location{ + Line: 7, + Column: 6, + }, + }, + }, + }, + { + Name: "HS-LEAKS-15", + Rule: NewHerokuAPIKey(), + Src: SampleVulnerableLeaksRegularHerokuAPIKey, + Findings: []engine.Finding{ + { + CodeSample: `HEROKU_API_KEY: '3623f8e9-2d05-c9bb-2209082d6b5c'`, + SourceLocation: engine.Location{ + Line: 7, + Column: 6, + }, + }, + }, + }, + { + Name: "HS-LEAKS-16", + Rule: NewMailChimpAPIKey(), + Src: SampleVulnerableLeaksRegularMailChimpAPIKey, + Findings: []engine.Finding{ + { + CodeSample: `MAILCHIMP_API_KEY: 'f7e9c13c10d0b19c3bb003a9f635d488-us72'`, + SourceLocation: engine.Location{ + Line: 7, + Column: 6, + }, + }, + }, + }, + { + Name: "HS-LEAKS-17", + Rule: NewMailgunAPIKey(), + Src: SampleVulnerableLeaksRegularMailgunAPIKey, + Findings: []engine.Finding{ + { + CodeSample: `MAILGUN_API_KEY: 'key-xke9nbc2i5po5cjw3ngyxiz450zxpapu'`, + SourceLocation: engine.Location{ + Line: 7, + Column: 6, + }, + }, + }, + }, + { + Name: "HS-LEAKS-18", + Rule: NewPayPalBraintreeAccessToken(), + Src: SampleVulnerableLeaksRegularPayPalBraintreeAccessToken, + Findings: []engine.Finding{ + { + CodeSample: `PAY_PAL_ACCESS_TOKEN: 'access_token$production$mk0sech2v7qqsol3$db651af2221c22b4ca2f0f583798135e'`, + SourceLocation: engine.Location{ + Line: 7, + Column: 29, + }, + }, + }, + }, + { + Name: "HS-LEAKS-19", + Rule: NewPicaticAPIKey(), + Src: SampleVulnerableLeaksRegularPicaticAPIKey, + Findings: []engine.Finding{ + { + CodeSample: `PICATIC_API_KEY: 'sk_live_voy1p9k7r9g9j8ezmif488nk2p8310nl'`, + SourceLocation: engine.Location{ + Line: 7, + Column: 24, + }, + }, + }, + }, + { + Name: "HS-LEAKS-20", + Rule: NewSendGridAPIKey(), + Src: SampleVulnerableLeaksRegularSendGridAPIKey, + Findings: []engine.Finding{ + { + CodeSample: `SEND_GRID_API_KEY: 'SG.44b7kq3FurdH0bSHBGjPSWhE8vJ.1evu4Un0TXFIb1_6zW4YOdjTMeE'`, + SourceLocation: engine.Location{ + Line: 7, + Column: 26, + }, + }, + }, + }, + { + Name: "HS-LEAKS-21", + Rule: NewStripeAPIKey(), + Src: SampleVulnerableLeaksRegularStripeAPIKey, + Findings: []engine.Finding{ + { + CodeSample: `STRIPE_API_KEY: 'rk_live_8qSZpoI9t0BOGkOLVzvesc6K'`, + SourceLocation: engine.Location{ + Line: 7, + Column: 6, + }, + }, + }, + }, + { + Name: "HS-LEAKS-22", + Rule: NewSquareAccessToken(), + Src: SampleVulnerableLeaksRegularSquareAccessToken, + Findings: []engine.Finding{ + { + CodeSample: `SQUARE_ACCESS_TOKEN: 'sq0atp-clYRBSht6oefa7w_2R56ra'`, + SourceLocation: engine.Location{ + Line: 7, + Column: 28, + }, + }, + }, + }, + { + Name: "HS-LEAKS-23", + Rule: NewSquareOAuthSecret(), + Src: SampleVulnerableLeaksRegularSquareOAuthSecret, + Findings: []engine.Finding{ + { + CodeSample: `SQUARE_SECRET: 'sq0csp-LsEBYQNja]OgT3hRxjJV5cWX^XjpT12n3QkRY_vep2z'`, + SourceLocation: engine.Location{ + Line: 7, + Column: 22, + }, + }, + }, + }, + { + Name: "HS-LEAKS-24", + Rule: NewTwilioAPIKey(), + Src: SampleVulnerableLeaksRegularTwilioAPIKey, + Findings: []engine.Finding{ + { + CodeSample: `TWILIO_API_KEY: '^SK9ae6bd84ccd091eb6bfad8e2a474af95'`, + SourceLocation: engine.Location{ + Line: 7, + Column: 6, + }, + }, + }, + }, + { + Name: "HS-LEAKS-25", + Rule: NewHardCodedCredentialGeneric(), + Src: SampleVulnerableLeaksRegularHardCodedCredentialGeneric, + Findings: []engine.Finding{ + { + CodeSample: `POSTGRES_DBPASSWD: 'Ch@ng3m3'`, + SourceLocation: engine.Location{ + Line: 7, + Column: 15, + }, + }, + }, + }, + { + Name: "HS-LEAKS-26", + Rule: NewHardCodedPassword(), + Src: SampleVulnerableLeaksRegularHardCodedPassword, + Findings: []engine.Finding{ + { + CodeSample: `DB_PASSWORD="gorm"`, + SourceLocation: engine.Location{ + Line: 12, + Column: 4, + }, + }, + }, + }, + { + Name: "HS-LEAKS-27", + Rule: NewPasswordExposedInHardcodedURL(), + Src: SampleVulnerableLeaksRegularPasswordExposedInHardcodedURL, + Findings: []engine.Finding{ + { + CodeSample: `dsn := "postgresql://gorm:gorm@127.0.0.1:5432/gorm?sslmode=disable"`, + SourceLocation: engine.Location{ + Line: 10, + Column: 9, + }, + }, + }, + }, + { + Name: "HS-LEAKS-28", + Rule: NewWPConfig(), + Src: SampleVulnerableLeaksRegularWPConfig, + Findings: []engine.Finding{ + { + CodeSample: `define('AUTH_KEY', 'put your unique phrase here');`, + SourceLocation: engine.Location{ + Line: 3, + Column: 0, + }, + }, + { + CodeSample: `define('DB_PASSWORD', 'wen0221!');`, + SourceLocation: engine.Location{ + Line: 4, + Column: 0, + }, + }, + }, + }, + } + + testutil.TestVulnerableCode(t, testcases) +} +func TestRulesSafeCode(t *testing.T) { + testcases := []*testutil.RuleTestCase{ + { + Name: "HS-LEAKS-1", + Rule: NewAWSManagerID(), + Src: SampleSafeLeaksRegularAWSManagerID, + }, + { + Name: "HS-LEAKS-2", + Rule: NewAWSSecretKey(), + Src: SampleSafeLeaksRegularAWSSecretKey, + }, + { + Name: "HS-LEAKS-3", + Rule: NewAWSMWSKey(), + Src: SampleSafeLeaksRegularAWSMWSKey, + }, + { + Name: "HS-LEAKS-4", + Rule: NewFacebookSecretKey(), + Src: SampleSafeLeaksRegularFacebookSecretKey, + }, + { + Name: "HS-LEAKS-5", + Rule: NewFacebookClientID(), + Src: SampleSafeLeaksRegularFacebookClientID, + }, + { + Name: "HS-LEAKS-7", + Rule: NewTwitterClientID(), + Src: SampleSafeLeaksRegularTwitterClientID, + }, + { + Name: "LEAKS-6", + Rule: NewTwitterSecretKey(), + Src: SampleSafeLeaksRegularTwitterSecretKey, + }, + { + Name: "HS-LEAKS-8", + Rule: NewGithub(), + Src: SampleSafeLeaksRegularGithub, + }, + { + Name: "HS-LEAKS-9", + Rule: NewLinkedInClientID(), + Src: SampleSafeLeaksRegularLinkedInClientID, + }, + { + Name: "LEAKS-10", + Rule: NewLinkedInSecretKey(), + Src: SampleSafeLeaksRegularLinkedInSecretKey, + }, + { + Name: "LEAKS-11", + Rule: NewSlack(), + Src: SampleSafeLeaksRegularSlack, + }, + { + Name: "HS-LEAKS-12", + Rule: NewAsymmetricPrivateKey(), + Src: SampleSafeLeaksRegularAsymmetricPrivateKey, + }, + { + Name: "HS-LEAKS-13", + Rule: NewGoogleAPIKey(), + Src: SampleSafeLeaksRegularGoogleAPIKey, + }, + { + Name: "HS-LEAKS-14", + Rule: NewGoogleGCPServiceAccount(), + Src: SampleSafeLeaksRegularGoogleGCPServiceAccount, + }, + { + Name: "HS-LEAKS-15", + Rule: NewHerokuAPIKey(), + Src: SampleSafeLeaksRegularHerokuAPIKey, + }, + { + Name: "HS-LEAKS-16", + Rule: NewMailChimpAPIKey(), + Src: SampleSafeLeaksRegularMailChimpAPIKey, + }, + { + Name: "HS-LEAKS-17", + Rule: NewMailgunAPIKey(), + Src: SampleSafeLeaksRegularMailgunAPIKey, + }, + { + Name: "HS-LEAKS-18", + Rule: NewPayPalBraintreeAccessToken(), + Src: SampleSafeLeaksRegularPayPalBraintreeAccessToken, + }, + { + Name: "HS-LEAKS-19", + Rule: NewPicaticAPIKey(), + Src: SampleSafeLeaksRegularPicaticAPIKey, + }, + { + Name: "HS-LEAKS-20", + Rule: NewSendGridAPIKey(), + Src: SampleSafeLeaksRegularSendGridAPIKey, + }, + { + Name: "HS-LEAKS-21", + Rule: NewStripeAPIKey(), + Src: SampleSafeLeaksRegularStripeAPIKey, + }, + { + Name: "HS-LEAKS-22", + Rule: NewSquareAccessToken(), + Src: SampleSafeLeaksRegularSquareAccessToken, + }, + { + Name: "HS-LEAKS-23", + Rule: NewSquareOAuthSecret(), + Src: SampleSafeLeaksRegularSquareOAuthSecret, + }, + { + Name: "HS-LEAKS-24", + Rule: NewTwilioAPIKey(), + Src: SampleSafeLeaksRegularTwilioAPIKey, + }, + { + Name: "HS-LEAKS-25", + Rule: NewHardCodedCredentialGeneric(), + Src: SampleSafeLeaksRegularHardCodedCredentialGeneric, + }, + { + Name: "HS-LEAKS-26", + Rule: NewHardCodedPassword(), + Src: SampleSafeLeaksRegularHardCodedPassword, + }, + { + Name: "HS-LEAKS-27", + Rule: NewPasswordExposedInHardcodedURL(), + Src: SampleSafeLeaksRegularPasswordExposedInHardcodedURL, + }, + { + Name: "HS-LEAKS-28", + Rule: NewWPConfig(), + Src: SampleSafeLeaksRegularWPConfig, + }, + } + testutil.TestSafeCode(t, testcases) +} diff --git a/internal/services/engines/samples_test.go b/internal/services/engines/leaks/samples_test.go similarity index 89% rename from internal/services/engines/samples_test.go rename to internal/services/engines/leaks/samples_test.go index f3454689a..17c471a11 100644 --- a/internal/services/engines/samples_test.go +++ b/internal/services/engines/leaks/samples_test.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package engines_test +package leaks const ( SampleVulnerableLeaksRegularAWSManagerID = ` @@ -586,55 +586,6 @@ func main() { define('AUTH_KEY', getenv("AUTH_KEY")); ` - SampleVulnerableJavaSQLInjection = ` -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import javax.sql.DataSource; -public class VulnerableCodeSQLInjection134 { - - public void printResults(DataSource ds, String field01) throws SQLException { - try ( - var con = ds.getConnection(); - var pstmt = con.prepareStatement("select * from mytable where field01 = '" + field01 + "'"); - var rs = pstmt.executeQuery()) { - while (rs.next()) { - System.out.println(rs.getString(1)); - } - } - } -} -` - - SampleSafeJavaSQLInjection = ` -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; - -import javax.sql.DataSource; - -public class VulnerableCodeSQLInjection134 { - - public void printResults(DataSource ds, String field01) throws SQLException { - try { - var con = ds.getConnection(); - var pstmt = con.prepareStatement("select * from mytable where field01 = ? "); - pstmt.setString(1,field01); - var rs = pstmt.executeQuery(); - while (rs.next()) { - System.out.println(rs.getString(1)); - } - } - } -} -` - SampleSafeJavaScriptUseEval = ` -function f() { - eval("echo foo"); -} - ` ) diff --git a/internal/services/engines/nginx/rules_test.go b/internal/services/engines/nginx/rules_test.go new file mode 100644 index 000000000..52c818dea --- /dev/null +++ b/internal/services/engines/nginx/rules_test.go @@ -0,0 +1,55 @@ +// Copyright 2021 ZUP IT SERVICOS EM TECNOLOGIA E INOVACAO SA +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package nginx + +import ( + "testing" + + engine "github.com/ZupIT/horusec-engine" + "github.com/ZupIT/horusec/internal/utils/testutil" +) + +func TestRulesVulnerableCode(t *testing.T) { + testcases := []*testutil.RuleTestCase{ + { + Name: "HS-NGINX-2", + Rule: NewIncludeXContentTypeOptionsHeader(), + Src: SampleVulnerableIncludeXContentTypeOptionsHeader, + Findings: []engine.Finding{ + { + CodeSample: "", + SourceLocation: engine.Location{ + Line: 0, + Column: 0, + }, + }, + }, + }, + } + + testutil.TestVulnerableCode(t, testcases) +} + +func TestRulesSafeCode(t *testing.T) { + testcases := []*testutil.RuleTestCase{ + { + Name: "HS-NGINX-2", + Rule: NewIncludeXContentTypeOptionsHeader(), + Src: SampleSafeIncludeXContentTypeOptionsHeader, + }, + } + + testutil.TestSafeCode(t, testcases) +} diff --git a/internal/services/engines/nginx/samples_test.go b/internal/services/engines/nginx/samples_test.go new file mode 100644 index 000000000..c498212f1 --- /dev/null +++ b/internal/services/engines/nginx/samples_test.go @@ -0,0 +1,35 @@ +// Copyright 2021 ZUP IT SERVICOS EM TECNOLOGIA E INOVACAO SA +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package nginx + +const ( + SampleVulnerableIncludeXContentTypeOptionsHeader = ` +add_header X-Frame-Options "SAMEORIGIN"; +add_header Strict-Transport-Security "max-age=15768000; includeSubDomains"; +add_header X-XSS-Protection "1; mode=block"; +add_header Content-Security-Policy "default-src 'self'; img-src *; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' 'unsafe-eval'"; +upstream plone52 { + server 127.0.0.1:8080; +}` + SampleSafeIncludeXContentTypeOptionsHeader = ` +add_header X-Frame-Options "SAMEORIGIN"; +add_header Strict-Transport-Security "max-age=15768000; includeSubDomains"; +add_header X-XSS-Protection "1; mode=block"; +add_header X-Content-Type-Options "nosniff"; +add_header Content-Security-Policy "default-src 'self'; img-src *; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' 'unsafe-eval'"; +upstream plone52 { + server 127.0.0.1:8080; +}` +) diff --git a/internal/services/engines/nodejs/rules_test.go b/internal/services/engines/nodejs/rules_test.go new file mode 100644 index 000000000..4bff73e07 --- /dev/null +++ b/internal/services/engines/nodejs/rules_test.go @@ -0,0 +1,90 @@ +// Copyright 2021 ZUP IT SERVICOS EM TECNOLOGIA E INOVACAO SA +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package nodejs + +import ( + "testing" + + engine "github.com/ZupIT/horusec-engine" + "github.com/ZupIT/horusec/internal/utils/testutil" +) + +func TestRulesVulnerableCode(t *testing.T) { + testcases := []*testutil.RuleTestCase{ + { + Name: "HS-JAVASCRIPT-1", + Rule: NewNoLogSensitiveInformationInConsole(), + Src: SampleVulnerableJavaScriptLogSensitiveInformation, + Findings: []engine.Finding{ + { + CodeSample: `console.log("user email: ", email)`, + SourceLocation: engine.Location{ + Line: 2, + Column: 0, + }, + }, + { + CodeSample: `console.debug("user password: ", pwd)`, + SourceLocation: engine.Location{ + Line: 3, + Column: 0, + }, + }, + }, + }, + { + Name: "HS-JAVASCRIPT-2", + Rule: NewNoUseEval(), + Src: SampleVulnerableJavaScriptUseEval, + Findings: []engine.Finding{ + { + CodeSample: `eval("bash -c" + req.body);`, + SourceLocation: engine.Location{ + Line: 3, + Column: 1, + }, + }, + }, + }, + { + Name: "HS-JAVASCRIPT-3", + Rule: NewNoDisableTlsRejectUnauthorized(), + Src: SampleVulnerableJavaScriptDisableTlsRejectUnauthorized, + Findings: []engine.Finding{ + { + CodeSample: `process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";`, + SourceLocation: engine.Location{ + Line: 2, + Column: 12, + }, + }, + }, + }, + } + + testutil.TestVulnerableCode(t, testcases) +} + +func TestRulesSafeCode(t *testing.T) { + testcases := []*testutil.RuleTestCase{ + { + Name: "HS-JAVASCRIPT-2", + Rule: NewNoUseEval(), + Src: SampleSafeJavaScriptUseEval, + }, + } + + testutil.TestSafeCode(t, testcases) +} diff --git a/internal/services/engines/nodejs/samples_test.go b/internal/services/engines/nodejs/samples_test.go new file mode 100644 index 000000000..2731eaf67 --- /dev/null +++ b/internal/services/engines/nodejs/samples_test.go @@ -0,0 +1,36 @@ +// Copyright 2021 ZUP IT SERVICOS EM TECNOLOGIA E INOVACAO SA +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package nodejs + +const ( + SampleSafeJavaScriptUseEval = ` +function f() { + eval("echo foo"); +} + ` + + SampleVulnerableJavaScriptDisableTlsRejectUnauthorized = ` +process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0"; + ` + SampleVulnerableJavaScriptUseEval = ` +function f(req) { + eval("bash -c" + req.body); +} + ` + SampleVulnerableJavaScriptLogSensitiveInformation = ` +console.log("user email: ", email) +console.debug("user password: ", pwd) + ` +) diff --git a/internal/services/engines/rules_test.go b/internal/services/engines/rules_test.go index 671de8d5d..01b37f668 100644 --- a/internal/services/engines/rules_test.go +++ b/internal/services/engines/rules_test.go @@ -20,9 +20,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - engine "github.com/ZupIT/horusec-engine" "github.com/ZupIT/horusec-engine/text" - enginesenum "github.com/ZupIT/horusec/internal/enums/engines" "github.com/ZupIT/horusec/internal/services/engines" "github.com/ZupIT/horusec/internal/services/engines/csharp" "github.com/ZupIT/horusec/internal/services/engines/dart" @@ -35,682 +33,6 @@ import ( "github.com/ZupIT/horusec/internal/services/engines/swift" ) -type testcase struct { - name string - src string - rule text.TextRule - findings []engine.Finding -} - -func TestRulesVulnerableCode(t *testing.T) { - testcases := []testcase{ - // Leaks tests - { - name: "HS-LEAKS-1", - rule: leaks.NewAWSManagerID(), - src: SampleVulnerableLeaksRegularAWSManagerID, - findings: []engine.Finding{ - { - CodeSample: "ACCESS_KEY: 'AKIAJSIE27KKMHXI3BJQ'", - SourceLocation: engine.Location{ - Line: 7, - Column: 18, - }, - }, - }, - }, - { - name: "HS-LEAKS-2", - rule: leaks.NewAWSSecretKey(), - src: SampleVulnerableLeaksRegularAWSSecretKey, - findings: []engine.Finding{ - { - CodeSample: `AWS_SECRET_KEY: 'doc5eRXFpsWllGC5yKJV/Ymm5KwF+IRZo95EudOm'`, - SourceLocation: engine.Location{ - Line: 7, - Column: 6, - }, - }, - }, - }, - { - name: "HS-LEAKS-3", - rule: leaks.NewAWSMWSKey(), - src: SampleVulnerableLeaksRegularAWSMWSKey, - findings: []engine.Finding{ - { - CodeSample: `AWS_WMS_KEY: 'amzn.mws.986478f0-9775-eabc-2af4-e499a8496828'`, - SourceLocation: engine.Location{ - Line: 7, - Column: 20, - }, - }, - }, - }, - { - name: "HS-LEAKS-4", - rule: leaks.NewFacebookSecretKey(), - src: SampleVulnerableLeaksRegularFacebookSecretKey, - findings: []engine.Finding{ - { - CodeSample: `FB_SECRET_KEY: 'cb6f53505911332d30867f44a1c1b9b5'`, - SourceLocation: engine.Location{ - Line: 7, - Column: 6, - }, - }, - }, - }, - { - name: "HS-LEAKS-5", - rule: leaks.NewFacebookClientID(), - src: SampleVulnerableLeaksRegularFacebookClientID, - findings: []engine.Finding{ - { - CodeSample: `FB_CLIENT_ID: '148695999071979'`, - SourceLocation: engine.Location{ - Line: 7, - Column: 6, - }, - }, - }, - }, - { - name: "HS-LEAKS-7", - rule: leaks.NewTwitterClientID(), - src: SampleVulnerableLeaksRegularTwitterClientID, - findings: []engine.Finding{ - { - CodeSample: `TWITTER_CLIENT_ID: '1h6433fsvygnyre5a40'`, - SourceLocation: engine.Location{ - Line: 7, - Column: 6, - }, - }, - }, - }, - { - name: "Leaks-LEAKS-6", - rule: leaks.NewTwitterSecretKey(), - src: SampleVulnerableLeaksRegularTwitterSecretKey, - findings: []engine.Finding{ - { - CodeSample: `TWITTER_SECRET_KEY: 'ej64cqk9k8px9ae3e47ip89l7if58tqhpxi1r'`, - SourceLocation: engine.Location{ - Line: 7, - Column: 6, - }, - }, - }, - }, - { - name: "HS-LEAKS-8", - rule: leaks.NewGithub(), - src: SampleVulnerableLeaksRegularGithub, - findings: []engine.Finding{ - { - CodeSample: `GITHUB_SECRET_KEY: 'edzvPbU3SYUc7pFc9le20lzIRErTOaxCABQ1'`, - SourceLocation: engine.Location{ - Line: 7, - Column: 6, - }, - }, - }, - }, - { - name: "HS-LEAKS-9", - rule: leaks.NewLinkedInClientID(), - src: SampleVulnerableLeaksRegularLinkedInClientID, - findings: []engine.Finding{ - { - CodeSample: `LINKEDIN_CLIENT_ID: 'g309xttlaw25'`, - SourceLocation: engine.Location{ - Line: 7, - Column: 6, - }, - }, - }, - }, - { - name: "Leaks-LEAKS-10", - rule: leaks.NewLinkedInSecretKey(), - src: SampleVulnerableLeaksRegularLinkedInSecretKey, - findings: []engine.Finding{ - { - CodeSample: `LINKEDIN_SECRET_KEY: '0d16kcnjyfzmcmjp'`, - SourceLocation: engine.Location{ - Line: 7, - Column: 6, - }, - }, - }, - }, - { - name: "Leaks-LEAKS-11", - rule: leaks.NewSlack(), - src: SampleVulnerableLeaksRegularSlack, - findings: []engine.Finding{ - { - CodeSample: `SLACK_WEBHOOK: 'https://hooks.slack.com/services/TNeqvYPeO/BncTJ74Hf/NlvFFKKAKPkd6h7FlQCz1Blu'`, - SourceLocation: engine.Location{ - Line: 7, - Column: 22, - }, - }, - }, - }, - { - name: "HS-LEAKS-12", - rule: leaks.NewAsymmetricPrivateKey(), - src: SampleVulnerableLeaksRegularAsymmetricPrivateKey, - findings: []engine.Finding{ - { - CodeSample: `SSH_PRIVATE_KEY: '-----BEGIN PRIVATE KEY-----MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDBj08sp5++4anGcmQxJjAkBgNVBAoTHVByb2dyZXNzIFNvZnR3YXJlIENvcnBvcmF0aW9uMSAwHgYDVQQDDBcqLmF3cy10ZXN0LnByb2dyZXNzLmNvbTCCASIwDQYJKoZIhvcNAQEBBQAD...bml6YXRpb252YWxzaGEyZzIuY3JsMIGgBggrBgEFBQcBAQSBkzCBkDBNBggrBgEFBQcwAoZBaHR0cDovL3NlY3VyZS5nbG9iYWxzaWduLmNvbS9jYWNlcnQvZ3Nvcmdhz3P668YfhUbKdRF6S42Cg6zn-----END PRIVATE KEY-----'`, - SourceLocation: engine.Location{ - Line: 7, - Column: 24, - }, - }, - }, - }, - { - name: "HS-LEAKS-13", - rule: leaks.NewGoogleAPIKey(), - src: SampleVulnerableLeaksRegularGoogleAPIKey, - findings: []engine.Finding{ - { - CodeSample: `GCP_API_KEY: 'AIzaMPZHYiu1RdzE1nG2SaVyOoz244TuacQIR6m'`, - SourceLocation: engine.Location{ - Line: 7, - Column: 20, - }, - }, - }, - }, - { - name: "HS-LEAKS-14", - rule: leaks.NewGoogleGCPServiceAccount(), - src: SampleVulnerableLeaksRegularGoogleGCPServiceAccount, - findings: []engine.Finding{ - { - CodeSample: `GCP_SERVICE_ACCOUNT: '18256698220617903267772185514630273595-oy8_uzouz8tyy46y84ckrwei9_6rq_pb.apps.googleusercontent.com'`, - SourceLocation: engine.Location{ - Line: 7, - Column: 6, - }, - }, - }, - }, - { - name: "HS-LEAKS-15", - rule: leaks.NewHerokuAPIKey(), - src: SampleVulnerableLeaksRegularHerokuAPIKey, - findings: []engine.Finding{ - { - CodeSample: `HEROKU_API_KEY: '3623f8e9-2d05-c9bb-2209082d6b5c'`, - SourceLocation: engine.Location{ - Line: 7, - Column: 6, - }, - }, - }, - }, - { - name: "HS-LEAKS-16", - rule: leaks.NewMailChimpAPIKey(), - src: SampleVulnerableLeaksRegularMailChimpAPIKey, - findings: []engine.Finding{ - { - CodeSample: `MAILCHIMP_API_KEY: 'f7e9c13c10d0b19c3bb003a9f635d488-us72'`, - SourceLocation: engine.Location{ - Line: 7, - Column: 6, - }, - }, - }, - }, - { - name: "HS-LEAKS-17", - rule: leaks.NewMailgunAPIKey(), - src: SampleVulnerableLeaksRegularMailgunAPIKey, - findings: []engine.Finding{ - { - CodeSample: `MAILGUN_API_KEY: 'key-xke9nbc2i5po5cjw3ngyxiz450zxpapu'`, - SourceLocation: engine.Location{ - Line: 7, - Column: 6, - }, - }, - }, - }, - { - name: "HS-LEAKS-18", - rule: leaks.NewPayPalBraintreeAccessToken(), - src: SampleVulnerableLeaksRegularPayPalBraintreeAccessToken, - findings: []engine.Finding{ - { - CodeSample: `PAY_PAL_ACCESS_TOKEN: 'access_token$production$mk0sech2v7qqsol3$db651af2221c22b4ca2f0f583798135e'`, - SourceLocation: engine.Location{ - Line: 7, - Column: 29, - }, - }, - }, - }, - { - name: "HS-LEAKS-19", - rule: leaks.NewPicaticAPIKey(), - src: SampleVulnerableLeaksRegularPicaticAPIKey, - findings: []engine.Finding{ - { - CodeSample: `PICATIC_API_KEY: 'sk_live_voy1p9k7r9g9j8ezmif488nk2p8310nl'`, - SourceLocation: engine.Location{ - Line: 7, - Column: 24, - }, - }, - }, - }, - { - name: "HS-LEAKS-20", - rule: leaks.NewSendGridAPIKey(), - src: SampleVulnerableLeaksRegularSendGridAPIKey, - findings: []engine.Finding{ - { - CodeSample: `SEND_GRID_API_KEY: 'SG.44b7kq3FurdH0bSHBGjPSWhE8vJ.1evu4Un0TXFIb1_6zW4YOdjTMeE'`, - SourceLocation: engine.Location{ - Line: 7, - Column: 26, - }, - }, - }, - }, - { - name: "HS-LEAKS-21", - rule: leaks.NewStripeAPIKey(), - src: SampleVulnerableLeaksRegularStripeAPIKey, - findings: []engine.Finding{ - { - CodeSample: `STRIPE_API_KEY: 'rk_live_8qSZpoI9t0BOGkOLVzvesc6K'`, - SourceLocation: engine.Location{ - Line: 7, - Column: 6, - }, - }, - }, - }, - { - name: "HS-LEAKS-22", - rule: leaks.NewSquareAccessToken(), - src: SampleVulnerableLeaksRegularSquareAccessToken, - findings: []engine.Finding{ - { - CodeSample: `SQUARE_ACCESS_TOKEN: 'sq0atp-clYRBSht6oefa7w_2R56ra'`, - SourceLocation: engine.Location{ - Line: 7, - Column: 28, - }, - }, - }, - }, - { - name: "HS-LEAKS-23", - rule: leaks.NewSquareOAuthSecret(), - src: SampleVulnerableLeaksRegularSquareOAuthSecret, - findings: []engine.Finding{ - { - CodeSample: `SQUARE_SECRET: 'sq0csp-LsEBYQNja]OgT3hRxjJV5cWX^XjpT12n3QkRY_vep2z'`, - SourceLocation: engine.Location{ - Line: 7, - Column: 22, - }, - }, - }, - }, - { - name: "HS-LEAKS-24", - rule: leaks.NewTwilioAPIKey(), - src: SampleVulnerableLeaksRegularTwilioAPIKey, - findings: []engine.Finding{ - { - CodeSample: `TWILIO_API_KEY: '^SK9ae6bd84ccd091eb6bfad8e2a474af95'`, - SourceLocation: engine.Location{ - Line: 7, - Column: 6, - }, - }, - }, - }, - { - name: "HS-LEAKS-25", - rule: leaks.NewHardCodedCredentialGeneric(), - src: SampleVulnerableLeaksRegularHardCodedCredentialGeneric, - findings: []engine.Finding{ - { - CodeSample: `POSTGRES_DBPASSWD: 'Ch@ng3m3'`, - SourceLocation: engine.Location{ - Line: 7, - Column: 15, - }, - }, - }, - }, - { - name: "HS-LEAKS-26", - rule: leaks.NewHardCodedPassword(), - src: SampleVulnerableLeaksRegularHardCodedPassword, - findings: []engine.Finding{ - { - CodeSample: `DB_PASSWORD="gorm"`, - SourceLocation: engine.Location{ - Line: 12, - Column: 4, - }, - }, - }, - }, - { - name: "HS-LEAKS-27", - rule: leaks.NewPasswordExposedInHardcodedURL(), - src: SampleVulnerableLeaksRegularPasswordExposedInHardcodedURL, - findings: []engine.Finding{ - { - CodeSample: `dsn := "postgresql://gorm:gorm@127.0.0.1:5432/gorm?sslmode=disable"`, - SourceLocation: engine.Location{ - Line: 10, - Column: 9, - }, - }, - }, - }, - { - name: "HS-LEAKS-28", - rule: leaks.NewWPConfig(), - src: SampleVulnerableLeaksRegularWPConfig, - findings: []engine.Finding{ - { - CodeSample: `define('AUTH_KEY', 'put your unique phrase here');`, - SourceLocation: engine.Location{ - Line: 3, - Column: 0, - }, - }, - { - CodeSample: `define('DB_PASSWORD', 'wen0221!');`, - SourceLocation: engine.Location{ - Line: 4, - Column: 0, - }, - }, - }, - }, - - // Java tests - { - name: "HS-JAVA-1", - rule: java.NewXMLParsingVulnerableToXXE(), - src: SampleVulnerableJavaXMLParsingVulnerableToXXE, - findings: []engine.Finding{ - { - CodeSample: `XMLReader reader = XMLReaderFactory.createXMLReader();`, - SourceLocation: engine.Location{ - Line: 4, - Column: 21, - }, - }, - }, - }, - { - name: "HS-JAVA-134", - rule: java.NewSQLInjection(), - src: SampleVulnerableJavaSQLInjection, - findings: []engine.Finding{ - { - CodeSample: "var pstmt = con.prepareStatement(\"select * from mytable where field01 = '\" + field01 + \"'\");", - SourceLocation: engine.Location{ - Line: 14, - Column: 50, - }, - }, - }, - }, - - // Javascript tests - { - name: "HS-JAVASCRIPT-1", - rule: nodejs.NewNoLogSensitiveInformationInConsole(), - src: SampleVulnerableJavaScriptLogSensitiveInformation, - findings: []engine.Finding{ - { - CodeSample: `console.log("user email: ", email)`, - SourceLocation: engine.Location{ - Line: 2, - Column: 0, - }, - }, - { - CodeSample: `console.debug("user password: ", pwd)`, - SourceLocation: engine.Location{ - Line: 3, - Column: 0, - }, - }, - }, - }, - { - name: "HS-JAVASCRIPT-2", - rule: nodejs.NewNoUseEval(), - src: SampleVulnerableJavaScriptUseEval, - findings: []engine.Finding{ - { - CodeSample: `eval("bash -c" + req.body);`, - SourceLocation: engine.Location{ - Line: 3, - Column: 1, - }, - }, - }, - }, - { - name: "HS-JAVASCRIPT-3", - rule: nodejs.NewNoDisableTlsRejectUnauthorized(), - src: SampleVulnerableJavaScriptDisableTlsRejectUnauthorized, - findings: []engine.Finding{ - { - CodeSample: `process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";`, - SourceLocation: engine.Location{ - Line: 2, - Column: 12, - }, - }, - }, - }, - } - - for _, tt := range testcases { - t.Run(tt.name, func(t *testing.T) { - findings := executeRule(t, tt) - require.Len(t, findings, len(tt.findings), "Expected equal issues on vulnerable code") - for idx, finding := range findings { - expected := tt.findings[idx] - assert.Equal(t, expected.CodeSample, finding.CodeSample) - assert.Equal(t, expected.SourceLocation, finding.SourceLocation) - assert.Equal(t, tt.rule.ID, finding.ID) - assert.Equal(t, tt.rule.Name, finding.Name) - assert.Equal(t, tt.rule.Severity, finding.Severity) - assert.Equal(t, tt.rule.Confidence, finding.Confidence) - assert.Equal(t, tt.rule.Description, finding.Description) - } - }) - } -} - -func TestRulesSafeCode(t *testing.T) { - testcases := []testcase{ - // Leaks tests - { - name: "HS-LEAKS-1", - rule: leaks.NewAWSManagerID(), - src: SampleSafeLeaksRegularAWSManagerID, - }, - { - name: "HS-LEAKS-2", - rule: leaks.NewAWSSecretKey(), - src: SampleSafeLeaksRegularAWSSecretKey, - }, - { - name: "HS-LEAKS-3", - rule: leaks.NewAWSMWSKey(), - src: SampleSafeLeaksRegularAWSMWSKey, - }, - { - name: "HS-LEAKS-4", - rule: leaks.NewFacebookSecretKey(), - src: SampleSafeLeaksRegularFacebookSecretKey, - }, - { - name: "HS-LEAKS-5", - rule: leaks.NewFacebookClientID(), - src: SampleSafeLeaksRegularFacebookClientID, - }, - { - name: "HS-LEAKS-7", - rule: leaks.NewTwitterClientID(), - src: SampleSafeLeaksRegularTwitterClientID, - }, - { - name: "Leaks-LEAKS-6", - rule: leaks.NewTwitterSecretKey(), - src: SampleSafeLeaksRegularTwitterSecretKey, - }, - { - name: "HS-LEAKS-8", - rule: leaks.NewGithub(), - src: SampleSafeLeaksRegularGithub, - }, - { - name: "HS-LEAKS-9", - rule: leaks.NewLinkedInClientID(), - src: SampleSafeLeaksRegularLinkedInClientID, - }, - { - name: "Leaks-LEAKS-10", - rule: leaks.NewLinkedInSecretKey(), - src: SampleSafeLeaksRegularLinkedInSecretKey, - }, - { - name: "Leaks-LEAKS-11", - rule: leaks.NewSlack(), - src: SampleSafeLeaksRegularSlack, - }, - { - name: "HS-LEAKS-12", - rule: leaks.NewAsymmetricPrivateKey(), - src: SampleSafeLeaksRegularAsymmetricPrivateKey, - }, - { - name: "HS-LEAKS-13", - rule: leaks.NewGoogleAPIKey(), - src: SampleSafeLeaksRegularGoogleAPIKey, - }, - { - name: "HS-LEAKS-14", - rule: leaks.NewGoogleGCPServiceAccount(), - src: SampleSafeLeaksRegularGoogleGCPServiceAccount, - }, - { - name: "HS-LEAKS-15", - rule: leaks.NewHerokuAPIKey(), - src: SampleSafeLeaksRegularHerokuAPIKey, - }, - { - name: "HS-LEAKS-16", - rule: leaks.NewMailChimpAPIKey(), - src: SampleSafeLeaksRegularMailChimpAPIKey, - }, - { - name: "HS-LEAKS-17", - rule: leaks.NewMailgunAPIKey(), - src: SampleSafeLeaksRegularMailgunAPIKey, - }, - { - name: "HS-LEAKS-18", - rule: leaks.NewPayPalBraintreeAccessToken(), - src: SampleSafeLeaksRegularPayPalBraintreeAccessToken, - }, - { - name: "HS-LEAKS-19", - rule: leaks.NewPicaticAPIKey(), - src: SampleSafeLeaksRegularPicaticAPIKey, - }, - { - name: "HS-LEAKS-20", - rule: leaks.NewSendGridAPIKey(), - src: SampleSafeLeaksRegularSendGridAPIKey, - }, - { - name: "HS-LEAKS-21", - rule: leaks.NewStripeAPIKey(), - src: SampleSafeLeaksRegularStripeAPIKey, - }, - { - name: "HS-LEAKS-22", - rule: leaks.NewSquareAccessToken(), - src: SampleSafeLeaksRegularSquareAccessToken, - }, - { - name: "HS-LEAKS-23", - rule: leaks.NewSquareOAuthSecret(), - src: SampleSafeLeaksRegularSquareOAuthSecret, - }, - { - name: "HS-LEAKS-24", - rule: leaks.NewTwilioAPIKey(), - src: SampleSafeLeaksRegularTwilioAPIKey, - }, - { - name: "HS-LEAKS-25", - rule: leaks.NewHardCodedCredentialGeneric(), - src: SampleSafeLeaksRegularHardCodedCredentialGeneric, - }, - { - name: "HS-LEAKS-26", - rule: leaks.NewHardCodedPassword(), - src: SampleSafeLeaksRegularHardCodedPassword, - }, - { - name: "HS-LEAKS-27", - rule: leaks.NewPasswordExposedInHardcodedURL(), - src: SampleSafeLeaksRegularPasswordExposedInHardcodedURL, - }, - { - name: "HS-LEAKS-28", - rule: leaks.NewWPConfig(), - src: SampleSafeLeaksRegularWPConfig, - }, - - { - name: "HS-JAVA-134", - rule: java.NewSQLInjection(), - src: SampleSafeJavaSQLInjection, - }, - - // Javascript tests - { - name: "HS-JAVASCRIPT-2", - rule: nodejs.NewNoUseEval(), - src: SampleSafeJavaScriptUseEval, - }, - } - - for _, tt := range testcases { - t.Run(tt.name, func(t *testing.T) { - findings := executeRule(t, tt) - assert.Empty(t, findings, "Expected not issues on safe code to rule %s", tt.name) - }) - } -} - func TestGetRules(t *testing.T) { testcases := []struct { engine string @@ -794,19 +116,3 @@ func TestGetRules(t *testing.T) { }) } } - -func executeRule(tb testing.TB, tt testcase) []engine.Finding { - textFile, err := text.NewTextFile("", []byte(tt.src)) - require.Nil(tb, err, "Expected nil error to create text file") - - unit := text.TextUnit{ - Files: []text.TextFile{ - textFile, - }, - } - - return engine.RunMaxUnitsByAnalysis( - []engine.Unit{unit}, []engine.Rule{tt.rule}, enginesenum.DefaultMaxUnitsPerAnalysis, - ) - -} diff --git a/internal/services/engines/swift/rules_test.go b/internal/services/engines/swift/rules_test.go new file mode 100644 index 000000000..02e8580ae --- /dev/null +++ b/internal/services/engines/swift/rules_test.go @@ -0,0 +1,54 @@ +// Copyright 2021 ZUP IT SERVICOS EM TECNOLOGIA E INOVACAO SA +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package swift + +import ( + "testing" + + engine "github.com/ZupIT/horusec-engine" + "github.com/ZupIT/horusec/internal/utils/testutil" +) + +func TestRulesVulnerableCode(t *testing.T) { + testcases := []*testutil.RuleTestCase{ + { + Name: "HS-SWIFT-6", + Rule: NewWeakMD5CryptoCipher(), + Src: SampleVulnerableWeakMD5CryptoCipher, + Findings: []engine.Finding{ + { + CodeSample: `import CryptoSwift`, + SourceLocation: engine.Location{ + Line: 1, + Column: 0, + }, + }, + }, + }, + } + + testutil.TestVulnerableCode(t, testcases) +} + +func TestRulesSafeCode(t *testing.T) { + testcases := []*testutil.RuleTestCase{ + { + Name: "HS-SWIFT-6", + Rule: NewWeakMD5CryptoCipher(), + Src: SampleSafeWeakMD5CryptoCipher, + }, + } + testutil.TestSafeCode(t, testcases) +} diff --git a/internal/services/engines/swift/samples_test.go b/internal/services/engines/swift/samples_test.go new file mode 100644 index 000000000..8d516dd93 --- /dev/null +++ b/internal/services/engines/swift/samples_test.go @@ -0,0 +1,45 @@ +// Copyright 2021 ZUP IT SERVICOS EM TECNOLOGIA E INOVACAO SA +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package swift + +const ( + SampleVulnerableWeakMD5CryptoCipher = `import CryptoSwift + + "SwiftSummit".md5()` + SampleSafeWeakMD5CryptoCipher = `import Foundation +import var CommonCrypto.CC_MD5_DIGEST_LENGTH +import func CommonCrypto.CC_MD5 +import typealias CommonCrypto.CC_LONG + +func MD5(string: String) -> Data { + let length = Int(CC_MD5_DIGEST_LENGTH) + let messageData = string.data(using:.utf8)! + var digestData = Data(count: length) + + _ = digestData.withUnsafeMutableBytes { digestBytes -> UInt8 in + messageData.withUnsafeBytes { messageBytes -> UInt8 in + if let messageBytesBaseAddress = messageBytes.baseAddress, let digestBytesBlindMemory = digestBytes.bindMemory(to: UInt8.self).baseAddress { + let messageLength = CC_LONG(messageData.count) + CC_MD5(messageBytesBaseAddress, messageLength, digestBytesBlindMemory) + } + return 0 + } + } + return digestData + } + +//Test: +let md5Data = MD5(string:"Hello")` +) diff --git a/internal/utils/testutil/rules_test_generic.go b/internal/utils/testutil/rules_test_generic.go new file mode 100644 index 000000000..5143240ac --- /dev/null +++ b/internal/utils/testutil/rules_test_generic.go @@ -0,0 +1,80 @@ +// Copyright 2021 ZUP IT SERVICOS EM TECNOLOGIA E INOVACAO SA +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package testutil + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + engine "github.com/ZupIT/horusec-engine" + "github.com/ZupIT/horusec-engine/text" + enginesenum "github.com/ZupIT/horusec/internal/enums/engines" +) + +func TestVulnerableCode(t *testing.T, testcases []*RuleTestCase) { + for _, tt := range testcases { + t.Run(tt.Name, func(t *testing.T) { + findings := executeRule(t, tt) + assert.Len(t, findings, len(tt.Findings), "Expected equal issues on vulnerable code") + assertExpectedFindingAndRuleCase(t, findings, tt) + }) + } +} + +// nolint +func assertExpectedFindingAndRuleCase(t *testing.T, findings []engine.Finding, tt *RuleTestCase) { + for idx, finding := range findings { + expected := tt.Findings[idx] + assert.Equal(t, expected.CodeSample, finding.CodeSample) + assert.Equal(t, expected.SourceLocation, finding.SourceLocation) + assert.Equal(t, tt.Rule.ID, finding.ID) + assert.Equal(t, tt.Rule.Name, finding.Name) + assert.Equal(t, tt.Rule.Severity, finding.Severity) + assert.Equal(t, tt.Rule.Confidence, finding.Confidence) + assert.Equal(t, tt.Rule.Description, finding.Description) + } +} +func TestSafeCode(t *testing.T, testcases []*RuleTestCase) { + for _, tt := range testcases { + t.Run(tt.Name, func(t *testing.T) { + Findings := executeRule(t, tt) + assert.Empty(t, Findings, "Expected not issues on safe code to Rule %s", tt.Name) + }) + } +} + +func executeRule(tb testing.TB, tt *RuleTestCase) []engine.Finding { + textFile, err := text.NewTextFile("", []byte(tt.Src)) + require.Nil(tb, err, "Expected nil error to create text file") + + unit := text.TextUnit{ + Files: []text.TextFile{ + textFile, + }, + } + + return engine.RunMaxUnitsByAnalysis( + []engine.Unit{unit}, []engine.Rule{tt.Rule}, enginesenum.DefaultMaxUnitsPerAnalysis, + ) +} + +type RuleTestCase struct { + Name string + Src string + Rule text.TextRule + Findings []engine.Finding +}