diff --git a/.github/workflows/security-scan.yml b/.github/workflows/security-scan.yml index 3e37129..f460f96 100644 --- a/.github/workflows/security-scan.yml +++ b/.github/workflows/security-scan.yml @@ -3,37 +3,138 @@ name: Security Vulnerability Scan on: workflow_dispatch: +env: + JAVA_VERSION: '11' + jobs: grype-scan: + name: "Java/Gradle Vulnerability Scan" runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - name: Checkout repository + uses: actions/checkout@v4 - - name: Setup Java version - uses: actions/setup-java@v3 + - name: Setup Java + uses: actions/setup-java@v4 with: - java-version: '11' + java-version: ${{ env.JAVA_VERSION }} distribution: 'zulu' - - name: Download dependencies - run: ./gradlew dependencies --no-daemon + # Collect all runtime dependency JARs into .dep-jars/ inside the workspace. + # + # A one-off Gradle init script copies the runtimeClasspath configuration + # directly — no cache-path guessing, works with any layout. + # Keeping JARs inside $GITHUB_WORKSPACE is critical: anchore/sbom-action + # mounts only the workspace into its container, so any path outside it + # is silently invisible to syft. + - name: Collect runtime dependency JARs + id: collect-deps + continue-on-error: true + run: | + mkdir -p .dep-jars + [ -f "gradlew" ] && chmod +x gradlew + GRADLEW=$([ -f "gradlew" ] && echo "./gradlew" || echo "gradle") + + # Init script: copies runtimeClasspath (or nearest equivalent) for + # every subproject into .dep-jars/ without touching build.gradle. + # Written with printf to avoid the '<<' heredoc operator, which + # GitHub's YAML parser misreads as a merge key inside a block scalar. + printf '%s\n' \ + 'allprojects {' \ + " tasks.register('_copyDepsForScan') {" \ + ' doLast {' \ + " def cfg = project.configurations.findByName('runtimeClasspath') ?:" \ + " project.configurations.findByName('runtime') ?:" \ + " project.configurations.findByName('compileClasspath')" \ + ' if (cfg) {' \ + " def destDir = rootProject.file('.dep-jars')" \ + ' destDir.mkdirs()' \ + ' try {' \ + ' cfg.resolvedConfiguration.lenientConfiguration.artifacts' \ + ' .findAll { art ->' \ + " art.file.name.endsWith('.jar') &&" \ + " !art.file.name.endsWith('-sources.jar') &&" \ + " !art.file.name.endsWith('-javadoc.jar')" \ + ' }' \ + ' .each { art ->' \ + ' def dest = new File(destDir, art.file.name)' \ + ' java.nio.file.Files.copy(' \ + ' art.file.toPath(),' \ + ' dest.toPath(),' \ + ' java.nio.file.StandardCopyOption.REPLACE_EXISTING' \ + ' )' \ + ' }' \ + ' } catch (ignored) {}' \ + ' }' \ + ' }' \ + ' }' \ + '}' \ + > /tmp/copy-deps.init.gradle + + $GRADLEW --no-daemon \ + --init-script /tmp/copy-deps.init.gradle \ + _copyDepsForScan 2>/dev/null || \ + $GRADLEW --no-daemon \ + --init-script /tmp/copy-deps.init.gradle \ + :_copyDepsForScan 2>/dev/null || true + + JAR_COUNT=$(find .dep-jars -maxdepth 1 -name '*.jar' | wc -l | tr -d ' ') + echo "jar_count=$JAR_COUNT" >> "$GITHUB_OUTPUT" + echo "Collected $JAR_COUNT runtime JARs into .dep-jars/" + + - name: Resolve scan target + id: scan-target + run: | + JAR_COUNT="${{ steps.collect-deps.outputs.jar_count }}" + if [ "${JAR_COUNT:-0}" -gt 0 ]; then + echo "ref=.dep-jars" >> "$GITHUB_OUTPUT" + echo "Scan target: .dep-jars (${JAR_COUNT} runtime JARs)" + else + echo "ref=." >> "$GITHUB_OUTPUT" + echo "::warning::No runtime JARs collected — falling back to source scan (results may be incomplete)" + fi + + # Generate SBOM via syft (anchore/sbom-action). + # syft reads META-INF/maven/*/pom.properties from each JAR to extract + # precise GAV coordinates, correctly surfacing bundled libraries inside + # fat/shaded JARs (e.g. testsigma-java-sdk's embedded jackson-databind). + # This is more reliable than the Gradle CycloneDX plugin, which only + # sees declared dependencies and misses shaded transitive content. + - name: Generate Java SBOM (syft) + uses: anchore/sbom-action@v0 + with: + path: ${{ steps.scan-target.outputs.ref }} + format: cyclonedx-json + output-file: sbom-java.cdx.json + artifact-name: sbom-java.cdx.json - name: Install Grype run: curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh | sh -s -- -b /usr/local/bin - name: Run Grype vulnerability scanner run: | - GRADLE_CACHE="$HOME/.gradle/caches/modules-2/files-2.1" - echo "Scanning Gradle cache: $(find $GRADLE_CACHE -name '*.jar' | wc -l) JARs found" - grype "dir:$GRADLE_CACHE" \ - --output table - grype "dir:$GRADLE_CACHE" \ - --output sarif > grype-results.sarif + echo "=== Grype vulnerability table ===" + grype "sbom:sbom-java.cdx.json" --output table + + grype "sbom:sbom-java.cdx.json" --output sarif > grype-results.sarif + + - name: Trivy Java scan (JSON) + uses: aquasecurity/trivy-action@0.34.2 + with: + scan-type: sbom + scan-ref: sbom-java.cdx.json + format: json + output: trivy-java.json + severity: LOW,MEDIUM,HIGH,CRITICAL + exit-code: "0" - name: Upload scan results as artifact uses: actions/upload-artifact@v4 if: always() with: name: grype-scan-results - path: 'grype-results.sarif' + path: | + grype-results.sarif + sbom-java.cdx.json + trivy-java.json diff --git a/build.gradle b/build.gradle index 0d40c35..e2e283c 100644 --- a/build.gradle +++ b/build.gradle @@ -28,7 +28,7 @@ repositories { } group = 'com.testsigma' -version = '1.2.24_cloud' +version = '1.2.26_cloud' description = 'Testsigma Java SDK' java.sourceCompatibility = JavaVersion.VERSION_11 @@ -37,9 +37,9 @@ dependencies { implementation 'org.seleniumhq.selenium:selenium-api:4.33.0' implementation 'org.seleniumhq.selenium:selenium-java:4.33.0' implementation 'io.appium:java-client:9.4.0' - implementation 'org.apache.commons:commons-lang3:3.12.0' - implementation 'org.testng:testng:7.4.0' - implementation 'org.json:json:20160810' + implementation 'org.apache.commons:commons-lang3:3.18.0' + implementation 'org.testng:testng:7.10.2' + implementation 'org.json:json:20231013' implementation 'com.fasterxml.jackson.core:jackson-annotations:2.13.0' annotationProcessor 'org.projectlombok:lombok:1.18.20' implementation 'org.apache.httpcomponents:httpclient:4.5.14' diff --git a/gradle.properties b/gradle.properties index f37a866..f47f466 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,7 +4,7 @@ signAllPublications=true GROUP=com.testsigma POM_ARTIFACT_ID=testsigma-java-sdk -VERSION_NAME=1.2.24_cloud +VERSION_NAME=1.2.26_cloud POM_NAME=Testsigma Java SDK POM_DESCRIPTION=Testsigma Java SDK