A lightweight Java static analysis CLI tool that scans source code for security vulnerabilities, SQL performance anti-patterns, and dependency risks. Targets 14 SAST security rules + 2 SQL quality rules covering 9 of 10 OWASP Top 10:2025 categories, with built-in dependency license compliance checking and optional online vulnerability scanning. Uses AST-based pattern matching with intra-method taint tracking. Generates a self-contained HTML report with security findings, SQL quality issues, dependency licenses, and vulnerability data — all with code context and actionable fix guidance.
Disclaimer: CodeScanUtil is a lightweight static analysis utility created to address a practical need — catching common Java security vulnerabilities early in the development cycle. It is shared as open-source in the hope that others facing similar challenges may find it useful.
This tool is provided as-is, with no warranties or guarantees of any kind. It performs pattern-based detection and is not a substitute for a comprehensive SAST solution such as Checkmarx, Fortify, or SonarQube. It cannot guarantee detection of all vulnerabilities, nor can it guarantee the absence of false positives. Security decisions should never rely solely on the output of this tool.
Use at your own risk and discretion. See LICENSE for the full legal terms.
CodeScanUtil scans Java source files and generates a self-contained HTML report covering:
Static Analysis (SAST):
- 14 security rules with findings grouped by severity (HIGH, MEDIUM, LOW, INFO)
- Code context showing the exact vulnerable line
- Vulnerable pattern vs. secure alternative for every finding
- Industry-standard SAST rule names and CWE IDs
SQL Quality Analysis:
- 2 SQL quality rules detecting performance anti-patterns and inefficient data access
- SELECT *, UPDATE/DELETE without WHERE, N+1 queries, LIKE with leading wildcards, and more
- Reported in a dedicated section, separate from security findings
Dependency Analysis:
- License compliance checking for Maven dependencies (offline via local cache, online via Maven Central)
- Known vulnerability scanning via OSV.dev and NVD (online mode)
- Fix version recommendations for vulnerable dependencies
Report:
- Scan summary (files scanned, total lines, duration)
- SAST findings with sortable/filterable table and expandable details
- SQL quality findings in a separate section
- Dependency license table with permissive/non-permissive status
- Dependency vulnerability table with CVE links, CVSS scores, and fix versions
It is designed as a lightweight scan — not a replacement for enterprise SAST tools, but a way to catch the low-hanging fruit early, reduce scan noise, and coach developers with actionable fix guidance.
- Java 17+ (tested with OpenJDK 21)
- Apache Maven 3.9+ (for building from source)
git clone <repository-url>
cd CodeScanUtil
mvn clean packageThis produces a fat JAR at target/codescanutil-1.5.0.jar (~8 MB) containing all dependencies.
# Scan a directory (recursively finds all .java files)
java -jar target/codescanutil-1.5.0.jar src/main/java
# Scan specific files
java -jar target/codescanutil-1.5.0.jar UserDao.java SecurityConfig.java
# Scan multiple directories
java -jar target/codescanutil-1.5.0.jar module-a/src module-b/src
# Custom output path
java -jar target/codescanutil-1.5.0.jar src/ --output /path/to/scan-report.html
# Filter by minimum severity
java -jar target/codescanutil-1.5.0.jar src/ --severity HIGH
# Fail with exit code 1 if HIGH findings exist
java -jar target/codescanutil-1.5.0.jar src/ --fail-on HIGH
# Run specific rules only
java -jar target/codescanutil-1.5.0.jar src/ --rules CX-SQL-001,CX-CRED-001
# Enable online vulnerability scanning (queries OSV.dev + optional NVD)
java -jar target/codescanutil-1.5.0.jar src/ --online
# Online mode with NVD fallback (set API key first)
export NVD_API_KEY=your-api-key-here
java -jar target/codescanutil-1.5.0.jar src/ --online| Option | Default | Description |
|---|---|---|
<paths> |
(required) | One or more files or directories to scan |
-o, --output |
report.html |
Output HTML report file path |
-s, --severity |
LOW |
Minimum severity to include in report |
--fail-on |
HIGH |
Exit with code 1 if findings at this severity or above |
--rules |
all | Comma-separated rule IDs to enable |
--online |
false |
Enable online dependency vulnerability scanning via OSV.dev/NVD |
-h, --help |
Show help | |
-V, --version |
Show version |
| Code | Meaning |
|---|---|
| 0 | No findings at or above --fail-on severity |
| 1 | Findings detected at or above --fail-on severity |
| 2 | Scanner error (e.g., no rules loaded) |
| Rule ID | SAST Query Name | CWE | Severity | What It Detects |
|---|---|---|---|---|
| CX-SQL-001 | SQL_Injection | 89 | HIGH | String concatenation in JDBC, JPA, Hibernate, Spring JDBC, MyBatis queries |
| CX-XSS-001 | Reflected_XSS_All_Clients | 79 | HIGH | Unencoded user input in HTTP responses and Spring MVC models |
| CX-PATH-001 | Absolute_Path_Traversal | 23 | MEDIUM | Unsanitized file paths, Zip Slip vulnerabilities |
| CX-LOG-001 | Log_Forging | 117 | MEDIUM | User input in log statements without CRLF sanitization |
| CX-CRED-001 | Use_Of_Hardcoded_Password | 798 | HIGH | Hardcoded passwords, API keys, tokens, connection string credentials |
| CX-CSRF-001 | Missing_CSRF_Protection | 352 | MEDIUM | Spring Security CSRF explicitly disabled |
| CX-DESER-001 | Deserialization_of_Untrusted_Data | 502 | HIGH | ObjectInputStream, XMLDecoder, unsafe Jackson/XStream/SnakeYAML config |
| CX-CMD-001 | Command_Injection | 78 | HIGH | Runtime.exec(), ProcessBuilder, ScriptEngine with tainted input |
| CX-REDIR-001 | Open_Redirect | 601 | MEDIUM | Unvalidated URLs in sendRedirect(), Spring redirect views |
| CX-CRYPTO-001 | Use_of_Broken_Cryptographic_Algorithm | 327 | HIGH | MD5, SHA-1, DES, ECB mode, hardcoded keys/IVs, weak key sizes, insecure TLS |
| CX-SSRF-001 | Server_Side_Request_Forgery | 918 | HIGH | Tainted URLs in URL, HttpClient, RestTemplate, WebClient, OkHttp, Jsoup |
| CX-EXCEPT-001 | Improper_Exception_Handling | 755 | MEDIUM | Empty catch blocks, overly broad catch, printStackTrace(), error detail leakage, missing try-with-resources |
| CX-HARDCODE-001 | Hardcoded_Environment_Config | 547 | MEDIUM | Hardcoded IP addresses, absolute file paths, internal/private URLs |
| CX-INFO-001 | Information_Exposure | 200 | MEDIUM | Internal domain names, internal emails, confidentiality markers, configurable sensitive terms |
SQL Quality Rules (reported separately from security findings):
| Rule ID | SAST Query Name | CWE | Severity | What It Detects |
|---|---|---|---|---|
| CX-SQLQ-001 | SQL_Anti_Pattern | 1049 | MEDIUM-HIGH | SELECT *, UPDATE/DELETE without WHERE, LIKE with leading wildcard, ORDER BY without LIMIT, SELECT DISTINCT, OR in WHERE |
| CX-SQLQ-002 | Inefficient_Data_Access | 1073 | HIGH-LOW | N+1 queries (query/findById in loop), findAll()+stream().filter(), @OneToMany(fetch=EAGER), unbounded queries |
| OWASP 2025 Category | Coverage | Rules |
|---|---|---|
| A01 Broken Access Control | Partial | CX-CSRF-001, CX-REDIR-001, CX-PATH-001 |
| A02 Security Misconfiguration | Partial | CX-CSRF-001, CX-CRYPTO-001, CX-HARDCODE-001 |
| A03 Software Supply Chain Failures | Moderate | Dependency vulnerability scan (--online), license checking |
| A04 Cryptographic Failures | Strong | CX-CRYPTO-001, CX-CRED-001 |
| A05 Injection | Strong | CX-SQL-001, CX-CMD-001, CX-LOG-001, CX-XSS-001, CX-SSRF-001 |
| A06 Insecure Design | Not in scope | Architectural, not detectable via SAST |
| A07 Authentication Failures | Partial | CX-CRED-001, CX-CRYPTO-001 |
| A08 Software or Data Integrity | Moderate | CX-DESER-001 |
| A09 Security Logging & Alerting | Partial | CX-LOG-001, CX-INFO-001 |
| A10 Mishandling of Exceptional Conditions | Strong | CX-EXCEPT-001 |
9 of 10 categories covered. The 1 uncovered (A06 Insecure Design) is fundamentally outside SAST scope.
CodeScanUtil includes built-in dependency scanning:
License Checking (always runs, offline):
- Parses
pom.xmlfiles found in or above scan target directories - Checks each dependency's license via local Maven cache (
~/.m2/repository) - Flags non-permissive licenses (GPL, AGPL, SSPL, EUPL)
- With
--online, fetches more accurate license data from Maven Central
Vulnerability Scanning (requires --online):
- Queries OSV.dev (free, no API key) for known vulnerabilities
- If
NVD_API_KEYenvironment variable is set, also queries NVD as fallback for dependencies with no OSV results - Reports CVE/GHSA IDs, CVSS scores, summaries, and recommended fix versions
- Vulnerability IDs link to OSV.dev for full details
Graceful degradation:
- Without
--online: license check uses local cache, vulnerability section shows "not performed" - With
--onlinebut no network: warns and falls back to SAST + offline license results NVD_API_KEYnot set: NVD is silently skipped, OSV.dev results are still used
Create a file named .codescanutil-sensitive-terms.txt in your project root (or any parent directory) with organization-specific terms to flag. A sample template is included at .codescanutil-sensitive-terms.example.txt — copy and customize it:
# Company and client names
AcmeCorp
Project Nighthawk
# Domain patterns (wildcards supported)
*.acme.com
acme.*
*.internal.mycompany.com
# Single-character wildcard
project-?
- Lines starting with
#are comments *matches any sequence of characters (e.g.,*.acme.commatchesapi.acme.com)?matches any single character (e.g.,project-?matchesproject-X)- Plain terms match case-insensitively via substring (e.g.,
AcmeCorpmatches"AcmeCorp dashboard") - The tool searches up the directory tree from the scanned files to find this file
The output is a single self-contained HTML file (no external dependencies, works fully offline):
- Scan summary — files scanned (with collapsible file list), total lines, duration
- Severity dashboard — color-coded cards for HIGH, MEDIUM, LOW, INFO counts
- SAST findings table — sortable by any column, filterable by severity or text search
- Expandable finding details — code context, vulnerable pattern, secure alternative
- SQL quality section — separate table for SQL anti-patterns and inefficient data access findings
- Dependency licenses table — each dependency with license name, permissive/non-permissive status, data source
- Dependency vulnerabilities table — CVE/GHSA IDs (linked to OSV.dev), CVSS scores, summaries, fix versions (with
--online) - Status banners — clear messaging when scans are skipped, incomplete, or clean
- Print-friendly — clean layout when printed or exported to PDF
Pre-generated sample reports are included in the samples/ directory:
| Report | Description |
|---|---|
sample-report-clean-offline.html |
Clean scan — 0 findings, offline license check, vulnerability scan not performed |
sample-report-clean-online.html |
Clean scan — 0 findings, online license check, 0 vulnerabilities |
sample-report-issues-found.html |
Full findings — security issues, SQL quality issues, 60 dependency vulnerabilities (log4j 2.14.1, jackson-databind 2.9.8) |
CodeScanUtil uses Java's ServiceLoader mechanism for rule discovery. To add a new rule:
- Create a class that extends
AbstractASTRule:
package com.codescanutil.rules.myrule;
import com.codescanutil.model.*;
import com.codescanutil.rules.*;
public class MyNewRule extends AbstractASTRule {
@Override public String id() { return "CX-NEW-001"; }
@Override public String name() { return "My_New_Rule"; }
@Override public int cweId() { return 000; }
@Override public Severity defaultSeverity() { return Severity.HIGH; }
@Override
public void visit(MethodCallExpr call, RuleContext ctx) {
super.visit(call, ctx);
// Detection logic here
// Use ctx.report(this, node, message, fix) to report findings
}
}- Register it in
src/main/resources/META-INF/services/com.codescanutil.rules.Rule:
com.codescanutil.rules.myrule.MyNewRule
- Rebuild:
mvn clean package
No other code changes are needed. The ScanEngine automatically discovers and runs all registered rules.
TaintTracker— intra-method taint analysis. CallgetTaintedVariables()thenisExpressionTainted()at sink points.ASTHelpers— shared AST utilities:isStringConcatenation(),isAllLiteralConcat(),getEnclosingMethod(),hasAnnotation(),isScopeNamed(),isInsideLoop(),isInsideRemediationExample(),isInsideConstantDefinition().
CodeScanUtil/
├── pom.xml # Maven build (Java 17, fat JAR via shade plugin)
├── LICENSE # Apache License 2.0
├── NOTICE # Attribution notices
├── THIRD-PARTY-LICENSES # BSD/MIT license texts for embedded components
├── .codescanutil-sensitive-terms.example.txt # Sample sensitive terms template
├── .gitignore # Git exclusions
├── samples/ # Sample HTML reports for reference
│ ├── sample-report-clean-offline.html # Clean scan without --online
│ ├── sample-report-clean-online.html # Clean scan with --online
│ └── sample-report-issues-found.html # Scan with security, SQL quality, and dependency issues
├── src/main/java/com/codescanutil/
│ ├── CodeScanUtil.java # CLI entry point (Picocli)
│ ├── scanner/
│ │ ├── ScanEngine.java # Orchestrator: parse -> rules -> report
│ │ ├── FileCollector.java # Resolves files/directories to .java file list
│ │ └── JavaFileParser.java # JavaParser wrapper
│ ├── model/
│ │ ├── Finding.java # Single SAST vulnerability finding
│ │ ├── Severity.java # HIGH, MEDIUM, LOW, INFO
│ │ ├── ScanResult.java # Aggregated scan results + dependency results
│ │ ├── SecureAlternative.java # Remediation guidance
│ │ ├── MavenDependency.java # Dependency coordinate (GAV)
│ │ ├── DependencyVulnerability.java # Single dependency vulnerability
│ │ ├── DependencyLicense.java # Dependency license info
│ │ └── DependencyScanResult.java # Dependency scan results container
│ ├── rules/
│ │ ├── Rule.java # Rule interface
│ │ ├── AbstractASTRule.java # Base class (VoidVisitorAdapter)
│ │ ├── RuleContext.java # Per-file context + finding collector
│ │ ├── RuleRegistry.java # ServiceLoader-based discovery
│ │ ├── sqli/ # SQL Injection rule
│ │ ├── xss/ # XSS rule
│ │ ├── pathtraversal/ # Path Traversal rule
│ │ ├── loginjection/ # Log Injection rule
│ │ ├── hardcodedcreds/ # Hardcoded Credentials rule
│ │ ├── csrf/ # CSRF rule
│ │ ├── deserialization/ # Insecure Deserialization rule
│ │ ├── commandinjection/ # Command Injection rule
│ │ ├── openredirect/ # Open Redirect rule
│ │ ├── weakcrypto/ # Weak Cryptography rule
│ │ ├── ssrf/ # SSRF rule
│ │ ├── exceptions/ # Exception Handling rule
│ │ ├── hardcodedconfig/ # Hardcoded Environment Config rule
│ │ ├── infodisclosure/ # Information Exposure rule
│ │ └── sqlquality/ # SQL Quality rules (anti-patterns + inefficient access)
│ ├── dependencies/
│ │ ├── DependencyScanner.java # Orchestrator: POM → license check → vuln scan
│ │ ├── PomParser.java # Parse pom.xml, extract dependencies
│ │ ├── LicenseChecker.java # Offline (cache) + online (Maven Central) license check
│ │ ├── OsvClient.java # OSV.dev vulnerability API client
│ │ └── NvdClient.java # NVD vulnerability API client (optional)
│ ├── reporting/
│ │ ├── Reporter.java # Reporter interface
│ │ └── HtmlReporter.java # Self-contained HTML report generator
│ └── util/
│ ├── TaintTracker.java # Intra-method taint analysis
│ └── ASTHelpers.java # Shared AST utilities
└── src/main/resources/
└── META-INF/services/ # ServiceLoader rule registry
Single-file AST pattern matching with intra-method taint tracking. Intentionally scoped to what can be detected without full classpath resolution or cross-class data flow analysis.
| Can Detect | Cannot Detect |
|---|---|
| String concatenation at known sinks | Inter-procedural taint flow across classes |
| Direct user-input-to-sink in same method | Taint propagation through service/DAO layers |
| Hardcoded secrets in Java source | Secrets in external config files |
| Disabled security configurations | Missing configurations in separate files |
| Weak algorithm string literals | Algorithm selection from runtime config |
| Vulnerable API usage patterns | Business logic vulnerabilities |
| Can Detect | Cannot Detect |
|---|---|
| SELECT * in string literal queries | SELECT * in dynamically built queries |
| UPDATE/DELETE without WHERE clause | Missing indexes on queried columns |
| N+1 queries (query/findById in loops) | N+1 from lazy-loading entity traversal |
| LIKE with leading wildcard (full scan) | Implicit type conversions causing scans |
| ORDER BY without LIMIT | Suboptimal join order |
| @OneToMany(fetch=EAGER) on collections | Execution plan analysis (requires DB) |
| findAll() + stream().filter() in Java | Complex query optimization |
| Can Do | Cannot Do |
|---|---|
| Parse pom.xml dependencies with version resolution | Resolve BOM-managed versions without parent POM |
| Check licenses via local Maven cache and Maven Central | Detect license changes in transitive dependencies not in cache |
| Query OSV.dev/NVD for known CVEs | Detect zero-day vulnerabilities |
| Recommend fix versions from OSV data | Guarantee fix version compatibility with your project |
| Offline license check from ~/.m2 cache | Guarantee completeness without online verification |
Licensed under the Apache License, Version 2.0. See LICENSE for the full text.
This project uses third-party libraries. See NOTICE for attributions and THIRD-PARTY-LICENSES for the full license texts of non-Apache-2.0 components.