SourceClear (Veracode) in Java: Complete SCA Security Guide

Introduction to Veracode SourceClear

Veracode SourceClear (formerly SourceClear) is a Software Composition Analysis (SCA) tool that identifies vulnerabilities in open-source dependencies and provides actionable remediation guidance. It integrates seamlessly into development workflows to prevent vulnerable dependencies from entering your codebase.

Key Features

  • Dependency Vulnerability Scanning: Identifies known vulnerabilities in third-party libraries
  • Software Bill of Materials (SBOM): Generates comprehensive inventory of all dependencies
  • Policy Enforcement: Enforces security policies across projects
  • Remediation Guidance: Provides fix recommendations and patch availability
  • CI/CD Integration: Scans dependencies in build pipelines
  • License Compliance: Detects license violations in dependencies

Implementation Guide

Dependencies and Setup

Maven Configuration (pom.xml)

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>veracode-sca-demo</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- Veracode SCA Version -->
<veracode.scan.version>23.6.8.0</veracode.scan.version>
<!-- Security Dependencies -->
<owasp.dependency.check.version>8.2.1</owasp.dependency.check.version>
<cyclonedx.maven.version>2.7.4</cyclonedx.maven.version>
<!-- Application Dependencies -->
<spring.boot.version>2.7.0</spring.boot.version>
<jackson.version>2.13.3</jackson.version>
<logback.version>1.2.11</logback.version>
</properties>
<dependencyManagement>
<dependencies>
<!-- Spring Boot BOM -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring.boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- Spring Boot Starters -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<!-- Database -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<!-- JSON Processing -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>${jackson.version}</version>
</dependency>
<!-- Logging -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
</dependency>
<!-- Security Libraries -->
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.70</version>
</dependency>
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>4.2.1</version>
</dependency>
<!-- Apache Commons (common source of vulnerabilities) -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-text</artifactId>
<version>1.10.0</version> <!-- Fixed version to avoid CVE-2022-42889 -->
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.5</version>
</dependency>
<!-- Test Dependencies -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<!-- Spring Boot Maven Plugin -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring.boot.version}</version>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Veracode SCA Maven Plugin -->
<plugin>
<groupId>com.veracode.maven</groupId>
<artifactId>veracode-scan-maven-plugin</artifactId>
<version>${veracode.scan.version}</version>
<executions>
<execution>
<id>veracode-sca-scan</id>
<goals>
<goal>scan</goal>
</goals>
<phase>verify</phase>
<configuration>
<appName>${project.artifactId}</appName>
<failOnViolation>true</failOnViolation>
<severityThreshold>HIGH</severityThreshold>
<outputDirectory>${project.build.directory}/veracode-reports</outputDirectory>
<formats>HTML,JSON,XML</formats>
<includeDevDependencies>false</includeDevDependencies>
<scanDependencies>true</scanDependencies>
<scanTestDependencies>false</scanTestDependencies>
</configuration>
</execution>
</executions>
</plugin>
<!-- CycloneDX SBOM Generation -->
<plugin>
<groupId>org.cyclonedx</groupId>
<artifactId>cyclonedx-maven-plugin</artifactId>
<version>${cyclonedx.maven.version}</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>makeAggregateBom</goal>
</goals>
</execution>
</executions>
<configuration>
<projectType>library</projectType>
<schemaVersion>1.4</schemaVersion>
<includeBomSerialNumber>true</includeBomSerialNumber>
<includeCompileScope>true</includeCompileScope>
<includeProvidedScope>true</includeProvidedScope>
<includeRuntimeScope>true</includeRuntimeScope>
<includeSystemScope>true</includeSystemScope>
<includeTestScope>false</includeTestScope>
<outputFormat>all</outputFormat>
<outputName>bom</outputName>
</configuration>
</plugin>
<!-- OWASP Dependency Check -->
<plugin>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-maven</artifactId>
<version>${owasp.dependency.check.version}</version>
<executions>
<execution>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
<configuration>
<failBuildOnAnyVulnerability>true</failBuildOnAnyVulnerability>
<suppressionFile>${project.basedir}/security/dependency-check-suppressions.xml</suppressionFile>
<format>HTML</format>
<formats>HTML,JSON,XML</formats>
<cveValidForHours>24</cveValidForHours>
</configuration>
</plugin>
<!-- Versions Maven Plugin -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>versions-maven-plugin</artifactId>
<version>2.14.2</version>
<configuration>
<rulesUri>file://${project.basedir}/security/dependency-update-rules.xml</rulesUri>
</configuration>
</plugin>
</plugins>
</build>
<reporting>
<plugins>
<plugin>
<groupId>com.veracode.maven</groupId>
<artifactId>veracode-scan-maven-plugin</artifactId>
<version>${veracode.scan.version}</version>
</plugin>
<plugin>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-maven</artifactId>
<version>${owasp.dependency.check.version}</version>
</plugin>
</plugins>
</reporting>
</project>

Security Configuration Files

Veracode Configuration (veracode.yml)

# Veracode SCA Configuration
version: 1
scan:
# Application configuration
app:
name: "veracode-sca-demo"
version: "1.0.0"
type: "java"
# Scan configuration
analysis:
language: "java"
build-tool: "maven"
java-version: "11"
# Security policies
security:
fail-on-severity: "HIGH"
max-critical: 0
max-high: 3
max-medium: 10
max-low: 20
# License compliance
licenses:
allowed:
- "Apache-2.0"
- "MIT"
- "BSD-3-Clause"
forbidden:
- "GPL-3.0"
- "AGPL-3.0"
warn-on:
- "LGPL-2.1"
- "LGPL-3.0"
# Dependency scanning
dependencies:
scan-production: true
scan-development: false
scan-test: false
exclude-groups:
- "org.junit.*"
- "junit.*"
exclude-artifacts:
- "spring-boot-devtools"
# Reporting
reporting:
formats:
- "html"
- "json"
- "xml"
output-directory: "target/veracode-reports"
include-remediation: true
include-license-info: true
# CI/CD Integration
ci:
fail-on-violation: true
upload-results: true
branch: "${GIT_BRANCH}"
commit: "${GIT_COMMIT}"
build-url: "${BUILD_URL}"
# Advanced settings
advanced:
parallel-downloads: 5
timeout: 300
memory-limit: "4G"
# Custom policies
custom-policies:
- id: "CUSTOM-SECURITY-1"
description: "No critical vulnerabilities allowed"
rule: "severity == 'CRITICAL'"
action: "FAIL"
- id: "CUSTOM-LICENSE-1"
description: "No GPL licenses allowed"
rule: "license == 'GPL-3.0' OR license == 'AGPL-3.0'"
action: "FAIL"

Dependency Update Rules (security/dependency-update-rules.xml)

<?xml version="1.0" encoding="UTF-8"?>
<ruleset comparisonMethod="maven"
xmlns="http://mojo.codehaus.org/versions-maven-plugin/rule/2.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://mojo.codehaus.org/versions-maven-plugin/rule/2.0.0 
http://mojo.codehaus.org/versions-maven-plugin/xsd/rule-2.0.0.xsd">
<rules>
<!-- Ignore major version updates for Spring Boot -->
<rule groupId="org.springframework.boot" comparisonMethod="maven">
<ignoreVersions>
<ignoreVersion type="regex">.*\.RELEASE</ignoreVersion>
</ignoreVersions>
<banLatestVersion>true</banLatestVersion>
<banRelease>true</banRelease>
<banSnapshots>true</banSnapshots>
<excludes>
<exclude>2.7.0</exclude>
</excludes>
</rule>
<!-- Allow only patch updates for security libraries -->
<rule groupId="com.fasterxml.jackson.core" comparisonMethod="maven">
<ignoreVersions>
<ignoreVersion type="regex">2\.13\.[0-9]+</ignoreVersion>
</ignoreVersions>
</rule>
<!-- Block vulnerable versions -->
<rule groupId="org.apache.commons" artifactId="commons-text" comparisonMethod="maven">
<banVersions>
<banVersion>1.9</banVersion>
<banVersion>1.8</banVersion>
<banVersion>1.7</banVersion>
</banVersions>
</rule>
<!-- Allow only specific logback versions -->
<rule groupId="ch.qos.logback" comparisonMethod="maven">
<ignoreVersions>
<ignoreVersion type="regex">1\.2\.[0-9]+</ignoreVersion>
</ignoreVersions>
</rule>
<!-- Security: Always update bouncycastle -->
<rule groupId="org.bouncycastle" comparisonMethod="maven">
<alwaysUpdate>true</alwaysUpdate>
</rule>
</rules>
</ruleset>

OWASP Dependency Check Suppressions (security/dependency-check-suppressions.xml)

<?xml version="1.0" encoding="UTF-8"?>
<suppressions xmlns="https://jeremylong.github.io/DependencyCheck/dependency-suppression.1.3.xsd">
<!-- Suppress false positives for Spring Framework -->
<suppress>
<notes><![CDATA[
False positive for Spring Framework - CVE doesn't affect our usage
]]></notes>
<cve>CVE-2018-1258</cve>
</suppress>
<suppress>
<notes><![CDATA[
False positive for Spring Framework - CVE doesn't affect our usage
]]></notes>
<cve>CVE-2022-22965</cve>
</suppress>
<!-- Suppress false positives for Jackson -->
<suppress>
<notes><![CDATA[
False positive for Jackson - CVE doesn't affect our usage pattern
]]></notes>
<cve>CVE-2020-36518</cve>
</suppress>
<!-- Suppress test dependencies -->
<suppress>
<notes><![CDATA[
Suppress vulnerabilities in test dependencies
]]></notes>
<filePath regex="true">.*test.*\.jar$</filePath>
</suppress>
<!-- Suppress specific H2 database false positives -->
<suppress>
<notes><![CDATA[
H2 database used only in development and testing
]]></notes>
<filePath regex="true">.*h2.*\.jar$</filePath>
</suppress>
<!-- Suppress low severity vulnerabilities -->
<suppress base="true">
<notes><![CDATA[
Suppress low severity vulnerabilities that don't pose immediate risk
]]></notes>
<severity>LOW</severity>
</suppress>
</suppressions>

Secure Application Code

Security Configuration Class

package com.example.veracode.config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import java.util.Arrays;
/**
* Security configuration with Veracode-recommended practices
*/
@Configuration
@EnableWebSecurity
public class SecurityConfig {
private static final Logger logger = LoggerFactory.getLogger(SecurityConfig.class);
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
// CSRF configuration
.csrf(csrf -> csrf
.ignoringAntMatchers("/api/public/**")
)
// CORS configuration
.cors(cors -> cors.configurationSource(corsConfigurationSource()))
// Authorization rules
.authorizeHttpRequests(authz -> authz
.antMatchers("/api/public/**").permitAll()
.antMatchers("/api/admin/**").hasRole("ADMIN")
.antMatchers("/api/**").authenticated()
.anyRequest().permitAll()
)
// Headers security
.headers(headers -> headers
.contentSecurityPolicy(csp -> csp
.policyDirectives("default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'")
)
.frameOptions().deny()
.xssProtection().block(true)
);
logger.info("Security configuration initialized successfully");
return http.build();
}
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOriginPatterns(Arrays.asList(
"https://*.example.com",
"http://localhost:[*]"
));
configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS"));
configuration.setAllowedHeaders(Arrays.asList("Authorization", "Content-Type", "X-Requested-With"));
configuration.setAllowCredentials(true);
configuration.setMaxAge(3600L);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/api/**", configuration);
return source;
}
}

Dependency Security Scanner

package com.example.veracode.security;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.event.EventListener;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.io.InputStream;
import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
/**
* Component to scan dependencies for security issues at runtime
*/
@Component
public class DependencySecurityScanner {
private static final Logger logger = LoggerFactory.getLogger(DependencySecurityScanner.class);
private static final String[] VULNERABLE_PATTERNS = {
"org/apache/commons/text/",  // CVE-2022-42889
"log4j/core/",               // Log4Shell
"com/fasterxml/jackson/",    // Jackson CVEs
"org/springframework/",      // Spring CVEs
};
@EventListener(ApplicationReadyEvent.class)
public void scanDependencies() {
logger.info("Starting dependency security scan...");
String classpath = System.getProperty("java.class.path");
String[] paths = classpath.split(System.getProperty("path.separator"));
for (String path : paths) {
if (path.endsWith(".jar")) {
scanJarFile(path);
}
}
logger.info("Dependency security scan completed");
}
private void scanJarFile(String jarPath) {
try (JarFile jarFile = new JarFile(jarPath)) {
Enumeration<JarEntry> entries = jarFile.entries();
while (entries.hasMoreElements()) {
JarEntry entry = entries.nextElement();
String entryName = entry.getName();
// Check for known vulnerable patterns
for (String pattern : VULNERABLE_PATTERNS) {
if (entryName.contains(pattern)) {
logger.warn("Potentially vulnerable dependency detected: {} in {}", 
pattern, jarPath);
break;
}
}
// Calculate checksum for critical files
if (entryName.endsWith(".class") && isSecuritySensitive(entryName)) {
String checksum = calculateChecksum(jarFile, entry);
logger.debug("Checksum for {}: {}", entryName, checksum);
}
}
} catch (IOException e) {
logger.error("Error scanning JAR file: {}", jarPath, e);
}
}
private boolean isSecuritySensitive(String className) {
return className.contains("Cipher") ||
className.contains("Key") ||
className.contains("Signature") ||
className.contains("SecureRandom");
}
private String calculateChecksum(JarFile jarFile, JarEntry entry) throws IOException {
try (InputStream is = jarFile.getInputStream(entry);
DigestInputStream dis = new DigestInputStream(is, 
MessageDigest.getInstance("SHA-256"))) {
// Read the entire stream to compute digest
byte[] buffer = new byte[8192];
while (dis.read(buffer) != -1) {
// Just reading to compute digest
}
byte[] digest = dis.getMessageDigest().digest();
return bytesToHex(digest);
} catch (NoSuchAlgorithmException e) {
throw new IOException("SHA-256 algorithm not available", e);
}
}
private String bytesToHex(byte[] bytes) {
StringBuilder hexString = new StringBuilder();
for (byte b : bytes) {
String hex = Integer.toHexString(0xff & b);
if (hex.length() == 1) {
hexString.append('0');
}
hexString.append(hex);
}
return hexString.toString();
}
}

Secure Controller with Input Validation

package com.example.veracode.controller;
import com.example.veracode.model.User;
import com.example.veracode.service.UserService;
import com.example.veracode.util.SecurityValidator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.List;
import java.util.Map;
/**
* Secure REST controller with comprehensive input validation
*/
@RestController
@RequestMapping("/api/users")
@Validated
public class UserController {
private static final Logger logger = LoggerFactory.getLogger(UserController.class);
@Autowired
private UserService userService;
@Autowired
private SecurityValidator securityValidator;
/**
* Get user by ID with comprehensive validation
*/
@GetMapping("/{id}")
public ResponseEntity<User> getUser(@PathVariable String id,
@RequestHeader("Authorization") String authHeader) {
// Validate authentication
if (!securityValidator.isValidAuthHeader(authHeader)) {
logger.warn("Invalid authentication header");
return ResponseEntity.status(401).build();
}
// Validate user ID format
if (!securityValidator.isValidUserId(id)) {
logger.warn("Invalid user ID format: {}", id);
return ResponseEntity.badRequest().build();
}
try {
User user = userService.findUserById(id);
if (user == null) {
return ResponseEntity.notFound().build();
}
// Sanitize sensitive data
user.sanitizeSensitiveData();
return ResponseEntity.ok(user);
} catch (SecurityException e) {
logger.warn("Security violation while fetching user: {}", id, e);
return ResponseEntity.status(403).build();
} catch (Exception e) {
logger.error("Error fetching user: {}", id, e);
return ResponseEntity.internalServerError().build();
}
}
/**
* Create user with comprehensive validation
*/
@PostMapping
public ResponseEntity<User> createUser(@Valid @RequestBody User user,
@RequestHeader("Authorization") String authHeader) {
// Validate authentication
if (!securityValidator.isValidAuthHeader(authHeader)) {
return ResponseEntity.status(401).build();
}
// Additional security validation
if (!securityValidator.isValidUser(user)) {
return ResponseEntity.badRequest().build();
}
// Check for potential XSS in user input
if (securityValidator.containsXss(user.getUsername()) ||
securityValidator.containsXss(user.getEmail())) {
logger.warn("Potential XSS attempt detected");
return ResponseEntity.badRequest().build();
}
try {
User createdUser = userService.createUser(user);
createdUser.sanitizeSensitiveData();
logger.info("User created successfully: {}", createdUser.getId());
return ResponseEntity.ok(createdUser);
} catch (Exception e) {
logger.error("Error creating user", e);
return ResponseEntity.internalServerError().build();
}
}
/**
* Search users with input sanitization
*/
@GetMapping("/search")
public ResponseEntity<List<User>> searchUsers(@RequestParam String query,
@RequestHeader("Authorization") String authHeader) {
// Validate authentication
if (!securityValidator.isValidAuthHeader(authHeader)) {
return ResponseEntity.status(401).build();
}
// Sanitize and validate search query
String sanitizedQuery = securityValidator.sanitizeSearchQuery(query);
if (sanitizedQuery == null || sanitizedQuery.trim().isEmpty()) {
return ResponseEntity.badRequest().build();
}
// Check for SQL injection patterns
if (securityValidator.containsSqlInjection(sanitizedQuery)) {
logger.warn("Potential SQL injection attempt detected: {}", sanitizedQuery);
return ResponseEntity.badRequest().build();
}
try {
List<User> users = userService.searchUsers(sanitizedQuery);
users.forEach(User::sanitizeSensitiveData);
return ResponseEntity.ok(users);
} catch (Exception e) {
logger.error("Error searching users with query: {}", sanitizedQuery, e);
return ResponseEntity.internalServerError().build();
}
}
/**
* Update user password with security checks
*/
@PutMapping("/{id}/password")
public ResponseEntity<Void> updatePassword(@PathVariable String id,
@RequestBody Map<String, String> passwordUpdate,
@RequestHeader("Authorization") String authHeader) {
// Validate authentication
if (!securityValidator.isValidAuthHeader(authHeader)) {
return ResponseEntity.status(401).build();
}
// Validate user ID
if (!securityValidator.isValidUserId(id)) {
return ResponseEntity.badRequest().build();
}
String newPassword = passwordUpdate.get("newPassword");
if (newPassword == null || newPassword.length() < 8) {
return ResponseEntity.badRequest().build();
}
try {
userService.updatePassword(id, newPassword);
logger.info("Password updated successfully for user: {}", id);
return ResponseEntity.ok().build();
} catch (SecurityException e) {
logger.warn("Security violation while updating password for user: {}", id, e);
return ResponseEntity.status(403).build();
} catch (Exception e) {
logger.error("Error updating password for user: {}", id, e);
return ResponseEntity.internalServerError().build();
}
}
}

Secure Service Implementation

package com.example.veracode.service;
import com.example.veracode.model.User;
import com.example.veracode.repository.UserRepository;
import com.example.veracode.util.PasswordHasher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.regex.Pattern;
/**
* Secure user service implementation with comprehensive security measures
*/
@Service
public class UserService {
private static final Logger logger = LoggerFactory.getLogger(UserService.class);
// SQL injection prevention patterns
private static final Pattern SQL_INJECTION_PATTERN = 
Pattern.compile("([';]+|(--)+|(\\|\\|)+|(&&)+|(\\b(OR|AND)\\b)+)", 
Pattern.CASE_INSENSITIVE);
@Autowired
private UserRepository userRepository;
@Autowired
private PasswordHasher passwordHasher;
/**
* Find user by ID with security validation
*/
public User findUserById(String id) {
// Input validation
if (id == null || id.trim().isEmpty()) {
throw new IllegalArgumentException("User ID cannot be null or empty");
}
// Security validation
if (containsSqlInjection(id)) {
logger.warn("Potential SQL injection attempt detected in user ID: {}", id);
throw new SecurityException("Invalid user ID format");
}
// Check for XSS patterns
if (containsXss(id)) {
logger.warn("Potential XSS attempt detected in user ID: {}", id);
throw new SecurityException("Invalid user ID format");
}
try {
return userRepository.findById(id)
.orElse(null);
} catch (DataAccessException e) {
logger.error("Database error while fetching user: {}", id, e);
throw new RuntimeException("Unable to fetch user", e);
}
}
/**
* Create user with secure password handling
*/
@Transactional
public User createUser(User user) {
// Validate user object
if (user == null) {
throw new IllegalArgumentException("User cannot be null");
}
// Validate user data
validateUserData(user);
// Hash password before storage
if (user.getPassword() != null) {
String hashedPassword = passwordHasher.hashPassword(user.getPassword());
user.setPassword(hashedPassword);
}
try {
User savedUser = userRepository.save(user);
logger.info("User created with ID: {}", savedUser.getId());
return savedUser;
} catch (DataAccessException e) {
logger.error("Database error while creating user", e);
throw new RuntimeException("Unable to create user", e);
}
}
/**
* Search users with comprehensive input sanitization
*/
public List<User> searchUsers(String query) {
// Validate input
if (query == null || query.trim().isEmpty()) {
throw new IllegalArgumentException("Search query cannot be null or empty");
}
// Sanitize and validate query
String sanitizedQuery = sanitizeSearchQuery(query);
if (sanitizedQuery == null) {
throw new SecurityException("Invalid search query");
}
// Check for SQL injection
if (containsSqlInjection(sanitizedQuery)) {
logger.warn("Potential SQL injection attempt detected in search query: {}", query);
throw new SecurityException("Invalid search query");
}
try {
return userRepository.findByUsernameContaining(sanitizedQuery);
} catch (DataAccessException e) {
logger.error("Database error while searching users with query: {}", sanitizedQuery, e);
throw new RuntimeException("Unable to search users", e);
}
}
/**
* Update user password securely
*/
@Transactional
public void updatePassword(String userId, String newPassword) {
// Validate inputs
if (userId == null || newPassword == null) {
throw new IllegalArgumentException("User ID and password cannot be null");
}
// Validate password strength
if (!isPasswordStrong(newPassword)) {
throw new IllegalArgumentException("Password does not meet strength requirements");
}
try {
User user = userRepository.findById(userId)
.orElseThrow(() -> new RuntimeException("User not found"));
// Hash new password
String hashedPassword = passwordHasher.hashPassword(newPassword);
user.setPassword(hashedPassword);
userRepository.save(user);
logger.info("Password updated for user: {}", userId);
} catch (DataAccessException e) {
logger.error("Database error while updating password for user: {}", userId, e);
throw new RuntimeException("Unable to update password", e);
}
}
/**
* Validate user data comprehensively
*/
private void validateUserData(User user) {
if (user.getUsername() == null || user.getUsername().trim().isEmpty()) {
throw new IllegalArgumentException("Username is required");
}
if (user.getEmail() == null || user.getEmail().trim().isEmpty()) {
throw new IllegalArgumentException("Email is required");
}
if (user.getPassword() == null || user.getPassword().length() < 8) {
throw new IllegalArgumentException("Password must be at least 8 characters long");
}
// Check for XSS in user data
if (containsXss(user.getUsername()) || containsXss(user.getEmail())) {
throw new SecurityException("User data contains potentially dangerous content");
}
// Validate email format
if (!isValidEmail(user.getEmail())) {
throw new IllegalArgumentException("Invalid email format");
}
}
/**
* Check for SQL injection patterns
*/
private boolean containsSqlInjection(String input) {
return SQL_INJECTION_PATTERN.matcher(input).find();
}
/**
* Check for XSS patterns
*/
private boolean containsXss(String input) {
Pattern xssPattern = Pattern.compile(
"(<script|javascript:|onload=|onerror=|onclick=|alert\\(|document\\.cookie)", 
Pattern.CASE_INSENSITIVE
);
return xssPattern.matcher(input).find();
}
/**
* Sanitize search query
*/
private String sanitizeSearchQuery(String query) {
if (query == null) return null;
// Remove potentially dangerous characters
String sanitized = query.replaceAll("[';\"\\\\<>()]", "");
// Limit length
if (sanitized.length() > 100) {
sanitized = sanitized.substring(0, 100);
}
return sanitized.trim();
}
/**
* Validate email format
*/
private boolean isValidEmail(String email) {
Pattern emailPattern = Pattern.compile(
"^[A-Za-z0-9+_.-]+@(.+)$"
);
return emailPattern.matcher(email).matches();
}
/**
* Check password strength
*/
private boolean isPasswordStrong(String password) {
if (password == null || password.length() < 8) {
return false;
}
// Check for at least one uppercase letter
if (!password.matches(".*[A-Z].*")) {
return false;
}
// Check for at least one lowercase letter
if (!password.matches(".*[a-z].*")) {
return false;
}
// Check for at least one digit
if (!password.matches(".*\\d.*")) {
return false;
}
// Check for at least one special character
if (!password.matches(".*[!@#$%^&*()_+\\-=\\[\\]{};':\"\\\\|,.<>\\/?].*")) {
return false;
}
return true;
}
}

Security Utilities

package com.example.veracode.util;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Component;
import java.security.SecureRandom;
import java.util.Base64;
import java.util.regex.Pattern;
/**
* Security utilities for password hashing and validation
*/
@Component
public class PasswordHasher {
private final BCryptPasswordEncoder bcryptEncoder;
private final SecureRandom secureRandom;
public PasswordHasher() {
this.bcryptEncoder = new BCryptPasswordEncoder(12);
this.secureRandom = new SecureRandom();
}
/**
* Hash password using bcrypt with secure configuration
*/
public String hashPassword(String plainPassword) {
if (plainPassword == null || plainPassword.trim().isEmpty()) {
throw new IllegalArgumentException("Password cannot be null or empty");
}
if (plainPassword.length() < 8) {
throw new IllegalArgumentException("Password must be at least 8 characters long");
}
// Additional security: check for common passwords
if (isCommonPassword(plainPassword)) {
throw new IllegalArgumentException("Password is too common");
}
return bcryptEncoder.encode(plainPassword);
}
/**
* Verify password against hash with timing attack protection
*/
public boolean verifyPassword(String plainPassword, String hashedPassword) {
if (plainPassword == null || hashedPassword == null) {
// Use constant-time comparison even for null inputs
dummyHashComparison();
return false;
}
return bcryptEncoder.matches(plainPassword, hashedPassword);
}
/**
* Dummy hash comparison to prevent timing attacks
*/
public void dummyHashComparison() {
// Perform a dummy hash with similar computation time
String dummyPassword = generateRandomString(16);
bcryptEncoder.encode(dummyPassword);
}
/**
* Check if password is in common passwords list
*/
private boolean isCommonPassword(String password) {
String[] commonPasswords = {
"password", "123456", "12345678", "1234", "qwerty", 
"letmein", "admin", "welcome", "monkey", "password1"
};
for (String common : commonPasswords) {
if (password.equalsIgnoreCase(common)) {
return true;
}
}
return false;
}
/**
* Generate secure random string
*/
private String generateRandomString(int length) {
byte[] bytes = new byte[length];
secureRandom.nextBytes(bytes);
return Base64.getEncoder().encodeToString(bytes);
}
}
/**
* Comprehensive security validator
*/
@Component
public class SecurityValidator {
private static final Pattern USER_ID_PATTERN = Pattern.compile("^[a-zA-Z0-9-_]{1,50}$");
private static final Pattern USERNAME_PATTERN = Pattern.compile("^[a-zA-Z0-9_]{3,30}$");
private static final Pattern EMAIL_PATTERN = Pattern.compile("^[A-Za-z0-9+_.-]+@(.+)$");
private static final Pattern AUTH_HEADER_PATTERN = Pattern.compile("^Bearer [a-zA-Z0-9-_]+\\.[a-zA-Z0-9-_]+\\.[a-zA-Z0-9-_]+$");
private static final Pattern SQL_INJECTION_PATTERN = Pattern.compile("([';]+|(--)+|(\\|\\|)+|(&&)+)", Pattern.CASE_INSENSITIVE);
private static final Pattern XSS_PATTERN = Pattern.compile("(<script|javascript:|onload=|onerror=|onclick=|alert\\(|document\\.cookie)", Pattern.CASE_INSENSITIVE);
/**
* Validate user ID format
*/
public boolean isValidUserId(String userId) {
return userId != null && USER_ID_PATTERN.matcher(userId).matches();
}
/**
* Validate username format
*/
public boolean isValidUsername(String username) {
return username != null && USERNAME_PATTERN.matcher(username).matches();
}
/**
* Validate email format
*/
public boolean isValidEmail(String email) {
return email != null && EMAIL_PATTERN.matcher(email).matches();
}
/**
* Validate authentication header format
*/
public boolean isValidAuthHeader(String authHeader) {
return authHeader != null && AUTH_HEADER_PATTERN.matcher(authHeader).matches();
}
/**
* Validate user object
*/
public boolean isValidUser(User user) {
if (user == null) return false;
return isValidUsername(user.getUsername()) &&
isValidEmail(user.getEmail()) &&
(user.getPassword() == null || user.getPassword().length() >= 8);
}
/**
* Check for SQL injection patterns
*/
public boolean containsSqlInjection(String input) {
return input != null && SQL_INJECTION_PATTERN.matcher(input).find();
}
/**
* Check for XSS patterns
*/
public boolean containsXss(String input) {
return input != null && XSS_PATTERN.matcher(input).find();
}
/**
* Sanitize search query
*/
public String sanitizeSearchQuery(String query) {
if (query == null) return null;
// Remove potentially dangerous characters
String sanitized = query.replaceAll("[';\"\\\\<>()]", "");
// Limit length
if (sanitized.length() > 100) {
sanitized = sanitized.substring(0, 100);
}
return sanitized.trim();
}
}

CI/CD Integration

GitHub Actions Workflow (.github/workflows/veracode-sca.yml)

name: Veracode SCA Security Scan
on:
push:
branches: [ main, develop, feature/** ]
pull_request:
branches: [ main, develop ]
schedule:
- cron: '0 2 * * 1'  # Weekly on Monday at 2 AM
jobs:
security-scan:
name: Veracode SCA Security Scan
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Set up Java
uses: actions/setup-java@v3
with:
java-version: '11'
distribution: 'temurin'
cache: 'maven'
- name: Cache Maven packages
uses: actions/cache@v3
with:
path: ~/.m2
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
restore-keys: ${{ runner.os }}-m2
- name: Build application
run: mvn clean compile -DskipTests
- name: Run Veracode SCA Scan
env:
VERACODE_API_KEY_ID: ${{ secrets.VERACODE_API_KEY_ID }}
VERACODE_API_KEY_SECRET: ${{ secrets.VERACODE_API_KEY_SECRET }}
run: |
mvn com.veracode.maven:veracode-scan-maven-plugin:scan \
-DappName="veracode-sca-demo" \
-DfailOnViolation=true \
-DseverityThreshold=HIGH \
-DoutputDirectory=target/veracode-reports
- name: Generate SBOM
run: mvn org.cyclonedx:cyclonedx-maven-plugin:makeAggregateBom
- name: Run OWASP Dependency Check
run: mvn org.owasp:dependency-check-maven:check
- name: Check for dependency updates
run: mvn versions:display-dependency-updates versions:display-plugin-updates
- name: Upload Security Reports
uses: actions/upload-artifact@v3
with:
name: security-reports
path: |
target/veracode-reports/
target/bom.*
target/dependency-check-report.html
target/dependency-updates.txt
- name: Security Scan Summary
if: always()
run: |
echo "## Veracode SCA Security Scan Results" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
if [ -f "target/veracode-reports/report.html" ]; then
echo "### ✅ Veracode SCA Scan Completed" >> $GITHUB_STEP_SUMMARY
echo "- Dependency vulnerability analysis finished" >> $GITHUB_STEP_SUMMARY
echo "- License compliance check completed" >> $GITHUB_STEP_SUMMARY
else
echo "### ❌ Veracode SCA Scan Failed" >> $GITHUB_STEP_SUMMARY
fi
if [ -f "target/bom.json" ]; then
echo "### ✅ SBOM Generated" >> $GITHUB_STEP_SUMMARY
echo "- Software Bill of Materials created" >> $GITHUB_STEP_SUMMARY
fi
echo "### 🔍 Next Steps" >> $GITHUB_STEP_SUMMARY
echo "- Review security reports in artifacts" >> $GITHUB_STEP_SUMMARY
echo "- Address high severity vulnerabilities immediately" >> $GITHUB_STEP_SUMMARY
echo "- Update dependencies with available patches" >> $GITHUB_STEP_SUMMARY
dependency-audit:
name: Dependency Security Audit
runs-on: ubuntu-latest
needs: security-scan
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Set up Java
uses: actions/setup-java@v3
with:
java-version: '11'
distribution: 'temurin'
- name: Download Security Reports
uses: actions/download-artifact@v3
with:
name: security-reports
- name: Analyze Dependencies
run: |
echo "## Dependency Security Analysis" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
if [ -f "veracode-reports/report.json" ]; then
HIGH_VULNS=$(jq '.vulnerabilities | map(select(.severity == "HIGH" or .severity == "CRITICAL")) | length' veracode-reports/report.json)
echo "### High/Critical Vulnerabilities: $HIGH_VULNS" >> $GITHUB_STEP_SUMMARY
fi
echo "### Recommended Actions:" >> $GITHUB_STEP_SUMMARY
echo "1. Review all high severity vulnerabilities" >> $GITHUB_STEP_SUMMARY
echo "2. Update vulnerable dependencies to patched versions" >> $GITHUB_STEP_SUMMARY
echo "3. Consider alternative libraries for frequently vulnerable dependencies" >> $GITHUB_STEP_SUMMARY
continue-on-error: true

Jenkins Pipeline (Jenkinsfile)

pipeline {
agent any
environment {
VERACODE_API_KEY_ID = credentials('veracode-api-key-id')
VERACODE_API_KEY_SECRET = credentials('veracode-api-key-secret')
JAVA_HOME = '/usr/lib/jvm/java-11-openjdk'
}
stages {
stage('Checkout') {
steps {
checkout scm
}
}
stage('Build') {
steps {
sh 'mvn clean compile -DskipTests'
}
}
stage('Unit Tests') {
steps {
sh 'mvn test'
}
post {
always {
junit 'target/surefire-reports/*.xml'
}
}
}
stage('Security Scan') {
parallel {
stage('Veracode SCA') {
steps {
sh '''
mvn com.veracode.maven:veracode-scan-maven-plugin:scan \
-DappName="${JOB_NAME}" \
-DfailOnViolation=true \
-DseverityThreshold=HIGH \
-DoutputDirectory=target/veracode-reports
'''
}
post {
always {
publishHTML([
allowMissing: false,
alwaysLinkToLastBuild: true,
keepAll: true,
reportDir: 'target/veracode-reports',
reportFiles: 'report.html',
reportName: 'Veracode SCA Report'
])
}
}
}
stage('SBOM Generation') {
steps {
sh 'mvn org.cyclonedx:cyclonedx-maven-plugin:makeAggregateBom'
}
post {
always {
archiveArtifacts artifacts: 'target/bom.*', fingerprint: true
}
}
}
stage('OWASP Dependency Check') {
steps {
sh 'mvn org.owasp:dependency-check-maven:check'
}
post {
always {
publishHTML([
allowMissing: false,
alwaysLinkToLastBuild: true,
keepAll: true,
reportDir: 'target',
reportFiles: 'dependency-check-report.html',
reportName: 'OWASP Dependency Check Report'
])
}
}
}
}
}
stage('Dependency Audit') {
steps {
sh '''
mvn versions:display-dependency-updates versions:display-plugin-updates
mvn dependency:tree -DoutputFile=target/dependency-tree.txt
'''
}
post {
always {
archiveArtifacts artifacts: 'target/dependency-tree.txt', fingerprint: true
}
}
}
stage('Integration Tests') {
steps {
sh 'mvn verify -DskipUnitTests'
}
post {
always {
junit 'target/failsafe-reports/*.xml'
}
}
}
}
post {
always {
archiveArtifacts artifacts: 'target/*.jar', fingerprint: true
cleanWs()
}
success {
emailext (
subject: "SUCCESS: Job '${env.JOB_NAME} [${env.BUILD_NUMBER}]'",
body: """
Security scan completed successfully.
Reports:
- Veracode SCA: ${env.BUILD_URL}veracode-sca/
- OWASP Dependency Check: ${env.BUILD_URL}dependency-check/
Check console output for detailed results: ${env.BUILD_URL}console
""",
to: "${env.BUILD_USER_EMAIL}"
)
}
failure {
emailext (
subject: "FAILED: Job '${env.JOB_NAME} [${env.BUILD_NUMBER}]'",
body: """
Security scan failed. Vulnerabilities detected or scan error occurred.
Check console output for details: ${env.BUILD_URL}console
Immediate action required for high severity vulnerabilities.
""",
to: "${env.BUILD_USER_EMAIL}"
)
}
unstable {
emailext (
subject: "UNSTABLE: Job '${env.JOB_NAME} [${env.BUILD_NUMBER}]'",
body: """
Security scan completed with warnings.
Medium or low severity vulnerabilities detected.
Review reports and address issues.
Check console output: ${env.BUILD_URL}console
""",
to: "${env.BUILD_USER_EMAIL}"
)
}
}
}

Security Test Cases

package com.example.veracode.security;
import com.example.veracode.util.PasswordHasher;
import com.example.veracode.util.SecurityValidator;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import static org.junit.jupiter.api.Assertions.*;
/**
* Security test cases for Veracode SCA validation
*/
@SpringBootTest
public class SecurityTests {
@Test
public void testSqlInjectionDetection() {
SecurityValidator validator = new SecurityValidator();
// Test SQL injection patterns
assertTrue(validator.containsSqlInjection("user' OR '1'='1"));
assertTrue(validator.containsSqlInjection("admin'; DROP TABLE users; --"));
assertTrue(validator.containsSqlInjection("test\" OR \"1\"=\"1"));
assertTrue(validator.containsSqlInjection("x' AND 1=1"));
assertTrue(validator.containsSqlInjection("x' OR 'a'='a"));
// Test safe inputs
assertFalse(validator.containsSqlInjection("user123"));
assertFalse(validator.containsSqlInjection("normal-query"));
assertFalse(validator.containsSqlInjection("test_user"));
}
@Test
public void testXssDetection() {
SecurityValidator validator = new SecurityValidator();
// Test XSS patterns
assertTrue(validator.containsXss("<script>alert('XSS')</script>"));
assertTrue(validator.containsXss("javascript:alert('XSS')"));
assertTrue(validator.containsXss("onload=\"maliciousCode()\""));
assertTrue(validator.containsXss("onerror=\"alert(1)\""));
assertTrue(validator.containsXss("alert(document.cookie)"));
// Test safe inputs
assertFalse(validator.containsXss("Hello World"));
assertFalse(validator.containsXss("user123"));
assertFalse(validator.containsXss("[email protected]"));
}
@Test
public void testPasswordHashing() {
PasswordHasher hasher = new PasswordHasher();
String password = "SecurePassword123!";
// Test password hashing
String hashed = hasher.hashPassword(password);
assertNotNull(hashed);
assertNotEquals(password, hashed);
// Test password verification
assertTrue(hasher.verifyPassword(password, hashed));
assertFalse(hasher.verifyPassword("WrongPassword", hashed));
// Test timing attack protection
long startTime = System.nanoTime();
hasher.verifyPassword("wrong", hashed);
long endTime = System.nanoTime();
long duration = endTime - startTime;
// Verification should take reasonable time (not instant for wrong passwords)
assertTrue(duration > 1000); // At least 1 microsecond
}
@Test
public void testInputValidation() {
SecurityValidator validator = new SecurityValidator();
// Test user ID validation
assertTrue(validator.isValidUserId("user123"));
assertTrue(validator.isValidUserId("user-123"));
assertTrue(validator.isValidUserId("user_123"));
assertFalse(validator.isValidUserId("user' OR '1'='1"));
assertFalse(validator.isValidUserId(""));
assertFalse(validator.isValidUserId(null));
// Test email validation
assertTrue(validator.isValidEmail("[email protected]"));
assertTrue(validator.isValidEmail("[email protected]"));
assertFalse(validator.isValidEmail("invalid-email"));
assertFalse(validator.isValidEmail("test@"));
assertFalse(validator.isValidEmail("@example.com"));
}
@Test
public void testSearchQuerySanitization() {
SecurityValidator validator = new SecurityValidator();
// Test query sanitization
String maliciousQuery = "test'; DROP TABLE users; --<script>alert('xss')</script>";
String sanitized = validator.sanitizeSearchQuery(maliciousQuery);
assertFalse(sanitized.contains("'"));
assertFalse(sanitized.contains(";"));
assertFalse(sanitized.contains("--"));
assertFalse(sanitized.contains("<"));
assertFalse(sanitized.contains(">"));
assertFalse(sanitized.contains("("));
assertFalse(sanitized.contains(")"));
}
@Test
public void testCommonPasswordDetection() {
// This test would normally be in PasswordHasher
// Testing that common passwords are rejected
PasswordHasher hasher = new PasswordHasher();
assertThrows(IllegalArgumentException.class, () -> {
hasher.hashPassword("password");
});
assertThrows(IllegalArgumentException.class, () -> {
hasher.hashPassword("123456");
});
}
}

Dependency Monitoring Script

#!/bin/bash
# dependency-security-monitor.sh
set -e
echo "Starting Dependency Security Monitor..."
echo "======================================"
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# Function to print colored output
print_status() {
local color=$1
local message=$2
echo -e "${color}${message}${NC}"
}
# Check if Maven is available
if ! command -v mvn &> /dev/null; then
print_status $RED "Maven is not installed or not in PATH"
exit 1
fi
# Create reports directory
mkdir -p target/security-reports
print_status $YELLOW "1. Generating Software Bill of Materials (SBOM)..."
mvn org.cyclonedx:cyclonedx-maven-plugin:makeAggregateBom -q
print_status $YELLOW "2. Running Veracode SCA Scan..."
if [ -z "$VERACODE_API_KEY_ID" ] || [ -z "$VERACODE_API_KEY_SECRET" ]; then
print_status $RED "Veracode API credentials not set. Skipping Veracode scan."
else
mvn com.veracode.maven:veracode-scan-maven-plugin:scan -q \
-DappName="veracode-sca-demo" \
-DfailOnViolation=false \
-DoutputDirectory=target/security-reports/veracode
fi
print_status $YELLOW "3. Running OWASP Dependency Check..."
mvn org.owasp:dependency-check-maven:check -q \
-DoutputDirectory=target/security-reports/owasp
print_status $YELLOW "4. Checking for dependency updates..."
mvn versions:display-dependency-updates -q > target/security-reports/dependency-updates.txt
print_status $YELLOW "5. Generating dependency tree..."
mvn dependency:tree -q -DoutputFile=target/security-reports/dependency-tree.txt
print_status $YELLOW "6. Analyzing vulnerable dependencies..."
# Count vulnerabilities from OWASP report
if [ -f "target/security-reports/owasp/dependency-check-report.json" ]; then
CRITICAL_COUNT=$(jq '.dependencies[] | select(.vulnerabilities[].severity == "CRITICAL") | .fileName' target/security-reports/owasp/dependency-check-report.json | wc -l)
HIGH_COUNT=$(jq '.dependencies[] | select(.vulnerabilities[].severity == "HIGH") | .fileName' target/security-reports/owasp/dependency-check-report.json | wc -l)
MEDIUM_COUNT=$(jq '.dependencies[] | select(.vulnerabilities[].severity == "MEDIUM") | .fileName' target/security-reports/owasp/dependency-check-report.json | wc -l)
echo ""
print_status $RED "VULNERABILITY SUMMARY:"
echo "=========================="
print_status $RED "Critical: $CRITICAL_COUNT"
print_status $RED "High: $HIGH_COUNT"
print_status $YELLOW "Medium: $MEDIUM_COUNT"
if [ $CRITICAL_COUNT -gt 0 ] || [ $HIGH_COUNT -gt 0 ]; then
print_status $RED "ACTION REQUIRED: Critical or High severity vulnerabilities detected!"
exit 1
fi
else
print_status $YELLOW "OWASP report not available for analysis"
fi
print_status $GREEN "Dependency security monitoring completed successfully!"
echo "Reports generated in: target/security-reports/"
echo "Files:"
echo "  - SBOM: target/bom.json"
echo "  - OWASP Report: target/security-reports/owasp/dependency-check-report.html"
echo "  - Dependency Updates: target/security-reports/dependency-updates.txt"
echo "  - Dependency Tree: target/security-reports/dependency-tree.txt"
if [ -d "target/security-reports/veracode" ]; then
echo "  - Veracode Report: target/security-reports/veracode/report.html"
fi

Best Practices

1. Regular Dependency Updates

/**
* Utility class to manage dependency security
*/
@Component
public class DependencySecurityManager {
/**
* Check for known vulnerable dependencies
*/
public void checkVulnerableDependencies() {
// Known vulnerable versions to check
Map<String, String> vulnerableVersions = Map.of(
"org.apache.commons:commons-text", "1.9", // CVE-2022-42889
"ch.qos.logback:logback-core", "1.2.8",   // Logback vulnerabilities
"com.fasterxml.jackson.core:jackson-databind", "2.12.0" // Jackson CVEs
);
// Implementation to check current versions
// and warn about vulnerable ones
}
/**
* Generate security report for dependencies
*/
public void generateSecurityReport() {
// Generate comprehensive security report
// including SBOM, vulnerability analysis, etc.
}
}

2. Security Policy Enforcement

/**
* Security policy enforcement for dependencies
*/
@Component
public class SecurityPolicyEnforcer {
/**
* Enforce security policies for dependencies
*/
public void enforcePolicies() {
checkForbiddenLicenses();
checkVulnerabilityThresholds();
checkOutdatedDependencies();
}
private void checkForbiddenLicenses() {
// Check for GPL, AGPL, etc.
}
private void checkVulnerabilityThresholds() {
// Fail build if critical vulnerabilities exceed threshold
}
private void checkOutdatedDependencies() {
// Warn about dependencies with major version updates available
}
}

Conclusion

This comprehensive Veracode SourceClear implementation provides:

  • Complete SCA integration with Maven builds
  • Automated vulnerability scanning in CI/CD pipelines
  • SBOM generation for dependency transparency
  • Security policy enforcement with customizable rules
  • Comprehensive reporting with multiple formats
  • Remediation guidance for vulnerable dependencies

Key benefits include early detection of vulnerable dependencies, automated security enforcement, comprehensive dependency visibility, and seamless integration with development workflows.

Remember to:

  • Run SCA scans regularly in your CI/CD pipeline
  • Address critical and high severity vulnerabilities immediately
  • Maintain an up-to-date SBOM
  • Enforce security policies consistently
  • Educate developers on secure dependency management
  • Monitor for new vulnerabilities in your dependencies

Secure Java Dependency Management, Vulnerability Scanning & Software Supply Chain Protection (SBOM, SCA, CI Security & License Compliance)

https://macronepal.com/blog/github-code-scanning-in-java-complete-guide/
Explains GitHub Code Scanning for Java using tools like CodeQL to automatically analyze source code and detect security vulnerabilities directly inside CI/CD pipelines before deployment.

https://macronepal.com/blog/license-compliance-in-java-comprehensive-guide/
Explains software license compliance in Java projects, ensuring dependencies follow legal requirements (MIT, Apache, GPL, etc.) and preventing license violations in enterprise software.

https://macronepal.com/blog/container-security-for-java-uncovering-vulnerabilities-with-grype/
Explains using Grype to scan Java container images and filesystems for known CVEs in OS packages and application dependencies to improve container security.

https://macronepal.com/blog/syft-sbom-generation-in-java-comprehensive-software-bill-of-materials-for-jvm-applications/
Explains using Syft to generate SBOMs (Software Bill of Materials) for Java applications, listing all dependencies, libraries, and components for supply chain transparency.

https://macronepal.com/blog/comprehensive-dependency-analysis-generating-and-scanning-sboms-with-trivy-for-java/
Explains using Trivy to generate SBOMs and scan Java dependencies and container images for vulnerabilities, integrating security checks into CI/CD pipelines.

https://macronepal.com/blog/dependabot-for-java-in-java/
Explains GitHub Dependabot for Java projects, which automatically detects vulnerable dependencies and creates pull requests to update them securely.

https://macronepal.com/blog/parasoft-jtest-in-java-comprehensive-guide-to-code-analysis-and-testing/
Explains Parasoft Jtest, a static analysis and testing tool for Java that helps detect bugs, security issues, and code quality problems early in development.

https://macronepal.com/blog/snyk-open-source-in-java-comprehensive-dependency-vulnerability-management-2/
Explains Snyk Open Source for Java, which continuously scans dependencies for vulnerabilities and provides automated fix suggestions and monitoring.

https://macronepal.com/blog/owasp-dependency-check-in-java-complete-vulnerability-scanning-guide/
Explains OWASP Dependency-Check, which scans Java dependencies against the National Vulnerability Database (NVD) to detect known security vulnerabilities.

https://macronepal.com/blog/securing-your-dependencies-a-java-developers-guide-to-whitesource-mend-bolt/
Explains Mend (WhiteSource) Bolt for Java, a dependency management and SCA tool that provides vulnerability detection, license compliance, and security policy enforcement in enterprise environments.

Secure Java Dependency Management, Vulnerability Scanning & Software Supply Chain Protection (SBOM, SCA, CI Security & License Compliance)

https://macronepal.com/blog/github-code-scanning-in-java-complete-guide/
Explains GitHub Code Scanning for Java using tools like CodeQL to automatically analyze source code and detect security vulnerabilities directly inside CI/CD pipelines before deployment.

https://macronepal.com/blog/license-compliance-in-java-comprehensive-guide/
Explains software license compliance in Java projects, ensuring dependencies follow legal requirements (MIT, Apache, GPL, etc.) and preventing license violations in enterprise software.

https://macronepal.com/blog/container-security-for-java-uncovering-vulnerabilities-with-grype/
Explains using Grype to scan Java container images and filesystems for known CVEs in OS packages and application dependencies to improve container security.

https://macronepal.com/blog/syft-sbom-generation-in-java-comprehensive-software-bill-of-materials-for-jvm-applications/
Explains using Syft to generate SBOMs (Software Bill of Materials) for Java applications, listing all dependencies, libraries, and components for supply chain transparency.

https://macronepal.com/blog/comprehensive-dependency-analysis-generating-and-scanning-sboms-with-trivy-for-java/
Explains using Trivy to generate SBOMs and scan Java dependencies and container images for vulnerabilities, integrating security checks into CI/CD pipelines.

https://macronepal.com/blog/dependabot-for-java-in-java/
Explains GitHub Dependabot for Java projects, which automatically detects vulnerable dependencies and creates pull requests to update them securely.

https://macronepal.com/blog/parasoft-jtest-in-java-comprehensive-guide-to-code-analysis-and-testing/
Explains Parasoft Jtest, a static analysis and testing tool for Java that helps detect bugs, security issues, and code quality problems early in development.

https://macronepal.com/blog/snyk-open-source-in-java-comprehensive-dependency-vulnerability-management-2/
Explains Snyk Open Source for Java, which continuously scans dependencies for vulnerabilities and provides automated fix suggestions and monitoring.

https://macronepal.com/blog/owasp-dependency-check-in-java-complete-vulnerability-scanning-guide/
Explains OWASP Dependency-Check, which scans Java dependencies against the National Vulnerability Database (NVD) to detect known security vulnerabilities.

https://macronepal.com/blog/securing-your-dependencies-a-java-developers-guide-to-whitesource-mend-bolt/
Explains Mend (WhiteSource) Bolt for Java, a dependency management and SCA tool that provides vulnerability detection, license compliance, and security policy enforcement in enterprise environments.

Leave a Reply

Your email address will not be published. Required fields are marked *


Macro Nepal Helper