Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
group=io.ballerina.scan
version=0.5.0
version=0.5.1

# Plugin versions
spotbugsPluginVersion=5.0.14
Expand Down
1 change: 1 addition & 0 deletions scan-command/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,7 @@ tasks.test {

useTestNG() {
suites 'src/test/resources/testng.xml'
testLogging.showStandardStreams = true
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,20 @@

package io.ballerina.scan;

import java.util.Map;

/**
* {@code ScannerContext} represents a context that exposes properties required by scanner plugins from the scan tool.
*
* @since 0.1.0
* */
*/
public interface ScannerContext {
/**
* Returns the {@link Reporter} to be used to report identified issues.
* Returns the {@link Reporter} to be used to report identified issues.
*
* @return reporter that needs to be used to report issues identified.
* */
*/
Reporter getReporter();

Map<String, Object> userData();
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,24 @@
package io.ballerina.scan.internal;

import io.ballerina.scan.Rule;
import io.ballerina.scan.RuleKind;

import java.util.ArrayList;
import java.util.List;

import static io.ballerina.scan.RuleKind.CODE_SMELL;
import static io.ballerina.scan.RuleKind.VULNERABILITY;
import static io.ballerina.scan.internal.RuleFactory.createRule;

/**
* {@code CoreRule} contains the core static code analysis rules.
*
* @since 0.1.0
* */
*/
enum CoreRule {
AVOID_CHECKPANIC(RuleFactory.createRule(1, "Avoid checkpanic", RuleKind.CODE_SMELL)),
UNUSED_FUNCTION_PARAMETER(RuleFactory.createRule(2,
"Unused function parameter", RuleKind.CODE_SMELL));
AVOID_CHECKPANIC(createRule(1, "Avoid checkpanic", CODE_SMELL)),
UNUSED_FUNCTION_PARAMETER(createRule(2, "Unused function parameter", CODE_SMELL)),
HARD_CODED_SECRET(createRule(3, "Hard-coded secrets are security-sensitive", VULNERABILITY)),
NON_CONFIGURABLE_SECRET(createRule(4, "Non configurable secrets are security-sensitive", VULNERABILITY));

private final Rule rule;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com).
*
* WSO2 LLC. licenses this file to you 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 io.ballerina.scan.internal;

import io.ballerina.compiler.api.symbols.Symbol;

import java.util.List;

/**
* Represents a function that contains sensitive arguments (e.g., secrets, passwords).
* This record stores the function's symbol and the positions of the arguments
* that are considered sensitive.
*
* <p>The sensitive parameters are tracked by their positions within the function's
* argument list. This can be used for detecting hardcoded secrets or validating
* configurations of sensitive data passed to the function.</p>
*
* @param symbol The symbol representing the function.
* @param sensitiveParamPositions A list of integer positions indicating which
* parameters of the function are considered sensitive.
*/
record FunctionWithSensitiveParams(Symbol symbol, List<Integer> sensitiveParamPositions) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@
* Represents the project analyzer used for analyzing projects.
*
* @since 0.1.0
* */
*/
class ProjectAnalyzer {
private final Project project;
private final ScanTomlFile scanTomlFile;
Expand All @@ -103,6 +103,13 @@ class ProjectAnalyzer {

List<Issue> analyze(List<Rule> inbuiltRules) {
ScannerContextImpl scannerContext = new ScannerContextImpl(inbuiltRules);
// Phase 1: Scan the entire codebase and collect necessary user data across documents
project.currentPackage().moduleIds().forEach(moduleId -> {
Module module = project.currentPackage().module(moduleId);
module.documentIds().forEach(scanDocument(module, scannerContext));
module.testDocumentIds().forEach(scanDocument(module, scannerContext));
});
// Phase 2: Analyze the documents individually, which may use the user data collected in the previous phase
project.currentPackage().moduleIds().forEach(moduleId -> {
Module module = project.currentPackage().module(moduleId);
module.documentIds().forEach(analyzeDocument(module, scannerContext));
Expand All @@ -111,6 +118,16 @@ List<Issue> analyze(List<Rule> inbuiltRules) {
return scannerContext.getReporter().getIssues();
}

private Consumer<DocumentId> scanDocument(Module module, ScannerContextImpl scannerContext) {
SemanticModel semanticModel = module.getCompilation().getSemanticModel();
return documentId -> {
Document document = module.document(documentId);
SensitiveParameterTracker scanner = new SensitiveParameterTracker(document.syntaxTree(),
scannerContext, semanticModel);
scanner.scan();
};
}

private Consumer<DocumentId> analyzeDocument(Module module, ScannerContextImpl scannerContext) {
SemanticModel semanticModel = module.getCompilation().getSemanticModel();
return documentId -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,22 +21,31 @@
import io.ballerina.scan.Rule;
import io.ballerina.scan.ScannerContext;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
* Represents the implementation of the {@link ScannerContext} interface.
*
* @since 0.1.0
* */
*/
class ScannerContextImpl implements ScannerContext {
private final ReporterImpl reporter;
private final Map<String, Object> userData;

ScannerContextImpl(List<Rule> rules) {
this.reporter = new ReporterImpl(rules);
reporter = new ReporterImpl(rules);
userData = new HashMap<>();
}

@Override
public ReporterImpl getReporter() {
return reporter;
}

@Override
public Map<String, Object> userData() {
return userData;
}
}
Loading