Portal Community

Security Controls Summary

ControlMechanismApplies To
Credential isolationConnection strings stored via ICredentialResolver (credentialId int)All datasource types
SQL injection preventionParameterized queries only; string interpolation blockedSqlQueryNode
Read-only enforcementSQL validator rejects non-SELECT statementsSqlQueryNode
Row limit capHard cap of 500 rows enforced server-sideSqlQueryNode, RestDatasourceNode
Query timeout30s default, 120s max — prevents long-running queries blocking executorsSqlQueryNode
Access controlNodeCapabilityPolicy controls which tenants can use Datasources capabilityAll datasource types
Datasource allowlistTenants can be restricted to specific datasource IDsAll datasource types

Credential Storage

// IDatasourceConnectionFactory resolves credentials at connection time:
public async Task<IDbConnection> OpenAsync(DatasourceDefinition datasource, CancellationToken ct)
{
    var connectionString = await _credentials.GetPasswordAsync(datasource.CredentialId, ct);
    var connection = _providerFactory.CreateConnection(datasource.Type);
    connection.ConnectionString = connectionString;
    await connection.OpenAsync(ct);
    return connection;
}

Datasource Allowlist (Tenant Policy)

{
  "tenantId": "tenant-acme",
  "allowedDatasourceIds": ["payroll-db", "erp-api"],
  "blockedDatasourceIds": ["hr-legacy-db"]
}
Database credentials: Connection strings must be stored via ICredentialResolver. Raw connection strings (including passwords) must never appear in node config, datasource definitions stored in configuration files, or environment variables accessible to workflow designers. A connection string in DatasourceDefinition config is a critical security defect.