import ballerina/sql;
public function userDefinedSecureOperation (@sensitive string secureParameter) {}function main (string[] args) {
    endpoint sql:Client customerDatabase {
        database: sql:DB_MYSQL,
        host: "localhost",
        port: 3306,
        name: "testdb",
        username: "root",
        password: "root",
        options: {maximumPoolSize:5}
    };
    var dataTable = customerDatabase -> select("SELECT firstname from customers where registrationID = " + args[0], null, null);
    userDefinedSecureOperation(args[0]);    if (isInteger(args[0])) {
        userDefinedSecureOperation(untaint args[0]);
    } else {
        error err = {message:"Validation error: ID should be an integer"};
        throw err;
    }    var closeStatus = customerDatabase -> close();
    return;
}public function isInteger (string input) returns boolean{
    Regex reg = {pattern:"\\d+"};
    boolean isInteger = check input.matchesWithRegex(reg);
    return isInteger;
}

Taint Checking

Ballerina compiler includes a taint analyzer that prevents untrusted data from being passed to security sensitive parameters.

import ballerina/sql;
public function userDefinedSecureOperation (@sensitive string secureParameter) {

It is possible to use @sensitive annotation with parameters of user defined functions and actions. This will allow, users to restrict passing tainted data into a security sensitive parameter.

}
function main (string[] args) {
    endpoint sql:Client customerDatabase {
        database: sql:DB_MYSQL,
        host: "localhost",
        port: 3306,
        name: "testdb",
        username: "root",
        password: "root",
        options: {maximumPoolSize:5}
    };
    var dataTable = customerDatabase -> select("SELECT firstname from customers where registrationID = " + args[0], null, null);

Sensitive parameters of operations builtin to Ballerina carry @sensitive annotation, to make sure tainted data cannot be passed into such parameters. For example, the taint checking mechanism will completely prevent SQL injection vulnerabilities by disallowing any tainted data in SQL query. This line will result in a compiler error, since query has been appended with a user provided argument.

    userDefinedSecureOperation(args[0]);

This line will result in a compiler error, since a user provided argument has been passed to a sensitive parameter.

    if (isInteger(args[0])) {
        userDefinedSecureOperation(untaint args[0]);
    } else {
        error err = {message:"Validation error: ID should be an integer"};
        throw err;
    }

After performing necessary validations and/or escaping, it is possible to use the “untaint” unary expression, to mark the proceeding value untainted and pass it to a sensitive parameter.

    var closeStatus = customerDatabase -> close();
    return;
}
public function isInteger (string input) returns boolean{
    Regex reg = {pattern:"\\d+"};
    boolean isInteger = check input.matchesWithRegex(reg);
    return isInteger;
}
$ ballerina run taint-checking.bal
error: ./Test1.bal:28:48: tainted value passed to sensitive parameter 'sqlQuery'
error: ./Test1.bal:32:32: tainted value passed to sensitive parameter 'securitySensitiveParameter'
compilation contains errors