import ballerina/lang.'int;
import ballerinax/java.jdbc;
function userDefinedSecureOperation(@untainted string secureParameter) {}type Student record {
string firstname;
};public function main(string... args) {
jdbc:Client customerDBEP = new ({
url: "jdbc:mysql://localhost:3306/testdb",
username: "root",
password: "root",
poolOptions: {maximumPoolSize: 5},
dbOptions: {useSSL: false}
});
var result = customerDBEP->
select("SELECT firstname FROM student WHERE" +
" registration_id = " + args[0], ()); if (result is error) {
panic result;
} table<Student> dataTable = <table<Student>>result;
userDefinedSecureOperation(args[0]); if (isInteger(args[0])) {
userDefinedSecureOperation(<@untainted>args[0]);
} else {
error err = error("Validation error: ID should be an integer");
panic err;
} while (dataTable.hasNext()) {
Student jsonData = dataTable.getNext();
userDefinedSecureOperation(jsonData.firstname); string sanitizedData1 = sanitizeAndReturnTainted(jsonData.firstname);
userDefinedSecureOperation(sanitizedData1); string sanitizedData2 = sanitizeAndReturnUntainted(jsonData.firstname);
userDefinedSecureOperation(sanitizedData2);
}
checkpanic customerDBEP.stop();
return;
}function sanitizeAndReturnTainted(string input) returns string {
return input;
}
function sanitizeAndReturnUntainted(string input) returns @untainted string {
return input;
}function isInteger(string input) returns boolean {
var intVal = 'int:fromString(input);
if (intVal is error) {
return false;
} else {
return true;
}
}# To run this sample, navigate to the directory that contains the
# `.bal` file, and execute the `ballerina run` command below.
ballerina run taint_checking.bal
error: .::taint_checking.bal:60:36: tainted value passed to untainted parameter 'secureParameter'
error: .::taint_checking.bal:31:39: tainted value passed to untainted parameter 'sqlQuery'
error: .::taint_checking.bal:41:32: tainted value passed to untainted parameter 'secureParameter'
error: .::taint_checking.bal:65:36: tainted value passed to untainted parameter 'secureParameter'
Taint CheckingBallerina is designed to ensure that programs written in Ballerina are inherently secure. Ballerina programs are resilient to major security vulnerabilities including SQL injection, path manipulation, file manipulation, unauthorized file access, and unvalidated redirect (open redirect). A taint analysis mechanism is used to achieve this. As a result of the taint analysis mechanism, the Ballerina compiler identifies untrusted (tainted) data by observing how tainted data propagates through the program. If untrusted data is passed to a security sensitive parameter, a compile error is generated. |
|
|
|
The |
|
|
|
|
|
|
|
Sensitive parameters of functions that are built-in to Ballerina are decorated with the For example, the taint checking mechanism of Ballerina completely prevents SQL injection vulnerabilities by disallowing tainted data in the SQL query. This line results in a compile error because the query is appended with a user-provided argument. |
|
|
|
|
|
This line results in a compiler error because a user-provided argument is passed to a sensitive parameter. |
|
|
|
After performing necessary validations and/or escaping, we can use type cast expression with @untainted annotation
to mark the proceeding value as |
|
|
|
The return values of certain functions built-in to Ballerina are decorated with the This line results in a compile error because a value derived from a database read (tainted) is passed to a sensitive parameter. |
|
|
|
This line results in a compile error because the |
|
|
|
This line successfully compiles. Although the |
|
|
|
transform and sanitize the string here. |
|
The |
|
transform and sanitize the string here. |
|
|