diff --git a/generic/gradle/security/build-gradle-password-hardcoded.build.gradle b/generic/gradle/security/build-gradle-password-hardcoded.build.gradle new file mode 100644 index 0000000000..819ee44872 --- /dev/null +++ b/generic/gradle/security/build-gradle-password-hardcoded.build.gradle @@ -0,0 +1,108 @@ +plugins { + id 'java' + id 'org.springframework.boot' version '3.0.5' + id 'io.spring.dependency-management' version '1.1.4' + id "jacoco" +} + +group = 'test' +version = 'latest' + +java { + sourceCompatibility = '17' +} + +jar { + archiveFileName = "test-reports.jar" +} + +configurations { + compileOnly { + extendsFrom annotationProcessor + } +} + +repositories { + if (Boolean.getBoolean("build-in-runner")) { + maven { + url = "https://test.maven.test/artifactory/maven/" + } + } else { + mavenLocal() + mavenCentral() + } + maven { + var env = System.getenv() + + url = uri(env["LIBRARY_URL"] ?: "https://test.maven.test/artifactory/maven-test-dev") + credentials { + username = env["LIBRARY_USER"] ?: "maven-test-dev" + // ruleid: build-gradle-password-hardcoded + password = env["LIBRARY_PASS"] ?: "jWnyxxxxxxxxxxX7ZQxxxxxxxx" + + username = env["LIBRARY_USER_2"] ?: "maven-second-dev" + // ok: build-gradle-password-hardcoded + password = env["LIBRARY_PASS_2"] + + username = env["LIBRARY_USER_3"] ?: "maven-test-dev" + // ruleid: build-gradle-password-hardcoded + password = env["LIBRARY_PASS_3"] ?: "somerandomstring" + + } + } +} + +dependencyManagement { + imports { + mavenBom 'de.codecentric:spring-boot-admin-dependencies:3.2.1' + } +} + +dependencies { + implementation 'org.springframework.boot:spring-boot-starter-data-jpa' + implementation 'org.springframework.boot:spring-boot-starter-web' + implementation 'org.springframework.boot:spring-boot-starter-validation' + implementation 'org.springframework.kafka:spring-kafka' + implementation 'de.codecentric:spring-boot-admin-starter-client' + implementation 'org.springframework.boot:spring-boot-starter-actuator' + implementation 'org.apache.commons:commons-lang3:3.11' + implementation "software.amazon.awssdk:s3-transfer-manager:2.20.109" + implementation 'io.swagger.core.v3:swagger-core-jakarta:2.2.15' + implementation "org.springframework.boot:spring-boot-starter-webflux" + implementation "com.vladmihalcea:hibernate-types-60:2.21.1" + implementation 'com.opencsv:opencsv:5.0' + implementation 'com.google.guava:guava:18.0' + implementation 'org.apache.tika:tika-parsers:1.2' + implementation 'commons-io:commons-io:2.10.0' + implementation 'org.mapstruct:mapstruct:1.4.2.Final' + implementation 'jakarta.annotation:jakarta.annotation-api:2.1.1' + implementation("io.minio:minio:8.5.6") + implementation 'org.postgresql:postgresql:42.3.7' + implementation 'org.springframework.ws:spring-ws-core:4.0.10' + compileOnly 'org.projectlombok:lombok' + annotationProcessor 'org.projectlombok:lombok' + annotationProcessor 'org.hibernate.orm:hibernate-jpamodelgen:6.1.6.Final' + annotationProcessor 'org.mapstruct:mapstruct-processor:1.4.2.Final' + testImplementation 'org.springframework.boot:spring-boot-starter-test' + testImplementation 'org.springframework.kafka:spring-kafka-test' +} + +jacoco { + toolVersion = "0.8.7" +} + +jacocoTestReport { + dependsOn test +} + +test { + testLogging { + exceptionFormat = "FULL" + events = ["FAILED", "STANDARD_ERROR"] + } + finalizedBy jacocoTestReport +} + +springBoot { + buildInfo() +} diff --git a/generic/gradle/security/build-gradle-password-hardcoded.yaml b/generic/gradle/security/build-gradle-password-hardcoded.yaml new file mode 100644 index 0000000000..ec632bbcac --- /dev/null +++ b/generic/gradle/security/build-gradle-password-hardcoded.yaml @@ -0,0 +1,38 @@ +rules: +- id: build-gradle-password-hardcoded + message: A secret is hard-coded in the application. Secrets stored in source code, + such as credentials, identifiers, and other types of sensitive data, can be leaked + and used by internal or external malicious actors. It is recommended to rotate + the secret and retrieve them from a secure secret vault or Hardware Security Module + (HSM), alternatively environment variables can be used if allowed by your company + policy. + severity: WARNING + metadata: + likelihood: LOW + impact: HIGH + confidence: LOW + category: security + subcategory: + - vuln + cwe: + - 'CWE-798: Use of Hard-coded Credentials' + cwe2020-top25: true + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures + technology: + - secrets + vulnerability_class: + - Hard-coded Secrets + source_rule_url: https://semgrep.dev/playground/r/qNU2d1G/achufistov6_personal_org.groovy-build-gradle-password-hardcoded + languages: + - generic + patterns: + - pattern: | + password = env[...] ?: "$SECRET" + paths: + include: + - "*build.gradle" diff --git a/kotlin/gradle/security/build-gradle-password-hardcoded.build.gradle.kts b/kotlin/gradle/security/build-gradle-password-hardcoded.build.gradle.kts new file mode 100644 index 0000000000..7727918593 --- /dev/null +++ b/kotlin/gradle/security/build-gradle-password-hardcoded.build.gradle.kts @@ -0,0 +1,206 @@ +import org.gradle.api.tasks.testing.logging.TestExceptionFormat +import org.gradle.api.tasks.testing.logging.TestLogEvent +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + +plugins { + val kotlinVersion = "1.8.0" + + id("org.springframework.boot") version "3.1.1" + id("io.spring.dependency-management") version "1.1.0" + id("io.gitlab.arturbosch.detekt") version "1.22.0" + kotlin("jvm") version kotlinVersion + kotlin("plugin.spring") version kotlinVersion + id("org.sonarqube") version "3.0" + id("org.springdoc.openapi-gradle-plugin") version "1.6.0" + jacoco + application +} + +group = "test" +version = "latest" + +val javaVersion = "17" +val koTestVersion = "5.5.5" +val mockkVersion = "1.13.4" +val runDetekt = !project.hasProperty("noDetekt") + +val file = File("$rootDir/.git") +val gitDir = if (file.isFile) "$rootDir/${file.readText().split(": ").last().trim()}" else "$rootDir/.git" + +java { + sourceCompatibility = JavaVersion.VERSION_17 +} + +repositories { + if (System.getProperty("build-in-runner")?.toBoolean() == true) { + maven { + url = uri("https://art.test.test/artifactory/maven/") + } + } else { + mavenLocal() + mavenCentral() + } + maven { + val env = System.getenv() + + url = uri(env["LIBRARY_URL"] ?: "https://art.test.test/artifactory/maven-some-dev") + credentials { + username = env["LIBRARY_USER_1"] ?: "maven-first-dev" + // ruleid: build-gradle-password-hardcoded + password = env["LIBRARY_PASS_1"] ?: "jWnyxxxxxxxxxxX7ZQxxxxxxxx" + + username = env["LIBRARY_USER_2"] ?: "maven-second-dev" + // ok: build-gradle-password-hardcoded + password = env["LIBRARY_PASS_2"] + } + } +} + +dependencyManagement { + imports { + mavenBom("de.codecentric:spring-boot-admin-dependencies:3.2.1") + } +} + +dependencies { + detektPlugins("io.gitlab.arturbosch.detekt:detekt-formatting:1.22.0") + + implementation("org.springframework.boot:spring-boot-starter-data-jpa") + implementation("org.springframework.boot:spring-boot-starter-web") + implementation("com.fasterxml.jackson.module:jackson-module-kotlin") + implementation("org.jetbrains.kotlin:kotlin-reflect") + implementation("org.liquibase:liquibase-core") + implementation("org.springframework.kafka:spring-kafka") + implementation("org.springdoc:springdoc-openapi-starter-webmvc-ui:2.2.0") + implementation("de.codecentric:spring-boot-admin-starter-client") + implementation("org.springframework.boot:spring-boot-starter-actuator") + implementation("io.github.microutils:kotlin-logging-jvm:3.0.5") + + runtimeOnly("org.postgresql:postgresql") + + testImplementation("org.springframework.boot:spring-boot-starter-test") { + exclude(module = "mockito-core") + exclude(module = "mockito-junit-jupiter") + } + testImplementation("org.springframework.kafka:spring-kafka-test") + testImplementation("com.ninja-squad:springmockk:4.0.0") + testImplementation("io.kotest.extensions:kotest-extensions-spring:1.1.2") + testImplementation("io.kotest:kotest-runner-junit5-jvm:$koTestVersion") + testImplementation("io.kotest:kotest-assertions-core-jvm:$koTestVersion") + testImplementation("io.kotest.extensions:kotest-extensions-embedded-kafka:1.0.6") + testImplementation("org.instancio:instancio-core:2.11.0") + testImplementation("io.kotest.extensions:kotest-extensions-wiremock:2.0.0") + + testRuntimeOnly("com.h2database:h2") +} + +application { + mainClass.set("someKt.someKtYeah") +} + +kotlin { + jvmToolchain { + languageVersion.set(JavaLanguageVersion.of(javaVersion)) + } +} + +jacoco { + toolVersion = "0.8.7" +} + +detekt { + buildUponDefaultConfig = true + autoCorrect = true + allRules = false // activate all available (even unstable) rules. + config = files("$projectDir/config/config.yml") +} + +tasks { + jacocoTestReport { + dependsOn(test) + reports { + xml.required.set(true) + } + classDirectories.setFrom( + files(classDirectories.files.map { + fileTree(it) { + exclude( + "**/config/*", + "**/constants/*", + "**/controller/*", + "**/domain/*", + "**/exception/*", + "**/SomeServiceBell.kt", + ) + } + }) + ) + } + + withType { + configureEach { + jvmTarget = javaVersion + } + onlyIf { runDetekt } + } + + withType { + configureEach { + jvmTarget = javaVersion + } + onlyIf { runDetekt } + } + + withType { + configureEach { + useJUnitPlatform() + } + testLogging { + exceptionFormat = TestExceptionFormat.FULL + events = setOf(TestLogEvent.FAILED, TestLogEvent.STANDARD_ERROR) + } + finalizedBy(jacocoTestReport) + } + + withType { + kotlinOptions { + freeCompilerArgs += "-Xjsr305=strict" + jvmTarget = javaVersion + } + } + + val installGitHooksName = "installGitHooks" + + val copyGitHooks = register("copyGitHooks") { + description = "Copies the git hooks from $gitDir/hooks to the .git folder." + from("$rootDir/hooks/") { + include("pre-commit.sh") + rename("(.*).sh", "$1") + } + into("$gitDir/hooks") + onlyIf { runDetekt } + finalizedBy(installGitHooksName) + } + + register(installGitHooksName) { + description = "Installs the pre-commit git hooks from $gitDir/hooks." + group = "git hooks" + commandLine("chmod") + args("+x", "$gitDir/hooks/pre-commit") + onlyIf { !org.jetbrains.kotlin.cli.common.isWindows && runDetekt } + outputs.upToDateWhen { copyGitHooks.get().state.upToDate } + doLast { + println("Git hook installed successfully.") + } + } + + afterEvaluate { + assemble { + dependsOn(copyGitHooks) + } + } +} + +springBoot { + buildInfo() +} \ No newline at end of file diff --git a/kotlin/gradle/security/build-gradle-password-hardcoded.yaml b/kotlin/gradle/security/build-gradle-password-hardcoded.yaml new file mode 100644 index 0000000000..2776569e27 --- /dev/null +++ b/kotlin/gradle/security/build-gradle-password-hardcoded.yaml @@ -0,0 +1,49 @@ +rules: +- id: build-gradle-password-hardcoded + message: A secret is hard-coded in the application. Secrets stored in source code, + such as credentials, identifiers, and other types of sensitive data, can be leaked + and used by internal or external malicious actors. It is recommended to rotate + the secret and retrieve them from a secure secret vault or Hardware Security Module + (HSM), alternatively environment variables can be used if allowed by your company + policy. + severity: WARNING + metadata: + likelihood: LOW + impact: HIGH + confidence: MEDIUM + category: security + subcategory: + - vuln + cwe: + - 'CWE-798: Use of Hard-coded Credentials' + cwe2020-top25: true + cwe2021-top25: true + cwe2022-top25: true + owasp: + - A07:2021 - Identification and Authentication Failures + references: + - https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures + technology: + - secrets + vulnerability_class: + - Hard-coded Secrets + source_rule_url: https://semgrep.dev/playground/r/d8Ur5BA/achufistov6_personal_org.build-gradle-password-hardcoded + languages: + - kotlin + options: + symbolic_propagation: true + patterns: + - pattern-either: + - pattern: '$PASS = env[...] ?: $VALUE' + - metavariable-regex: + metavariable: $PASS + regex: (password|pass|passwd|loginPassword) + - metavariable-pattern: + language: generic + metavariable: $VALUE + patterns: + - pattern-either: + - pattern-regex: ^[A-Za-z0-9/+=]+$ + paths: + include: + - "*build.gradle.kts"