HIGH server side template injectionadonisjscockroachdb

Server Side Template Injection in Adonisjs with Cockroachdb

Server Side Template Injection in Adonisjs with Cockroachdb — how this specific combination creates or exposes the vulnerability

Server Side Template Injection (SSTI) in AdonisJS with CockroachDB arises when an application renders user-controlled input as part of a template without proper escaping or sandboxing, and that template interacts with CockroachDB. AdonisJS uses Edge by default; if dynamic expressions embed raw user input into the template logic or queries, an attacker can influence control flow or data access patterns. Because CockroachDB is often accessed via an ORM or query builder, the risk is not direct database injection through templates, but rather template-driven logic that alters query construction or exposes sensitive data.

Consider an endpoint that renders a dashboard using a username supplied via query parameters. If the template conditionally includes sections based on that username without validation, an attacker may probe for template context leakage. For example, injecting payloads like ${''['constructor']['name']} can reveal whether the runtime exposes internal objects. When the template subsequently builds a CockroachDB query using the same input—such as filtering rows by a tenant identifier derived from the template context—the injected logic can change the query’s WHERE clause, leading to unauthorized data access across tenants.

In AdonisJS, templates are compiled and cached; if user input reaches the template layer and influences which database calls are made, the boundary between presentation and persistence blurs. CockroachDB’s SQL compatibility means typical SQL injection techniques apply at the query layer, but SSTI focuses on the template engine’s ability to execute arbitrary logic that affects which queries are sent. This is especially risky when dynamic imports or runtime expressions construct query strings based on template variables. Attack patterns include using template injection to enumerate usernames, trigger error messages that reveal schema details, or manipulate pagination to exfiltrate rows.

An example flow: a route accepts search, passes it to an Edge template that conditionally adds filters to a CockroachDB query. If search contains template syntax, it may execute unintended branches, causing the query builder to omit tenant filters. The resulting SQL issued to CockroachDB could return rows belonging to other users. This highlights the need to treat template input as untrusted and to enforce strict separation between template logic and data access layers.

middleBrick detects such risks by correlating runtime behavior with OpenAPI specs and unauthenticated probing. It flags where templates handle untrusted data that influences database interactions, providing remediation guidance that emphasizes input validation and context-aware escaping rather than attempting to fix the database layer directly.

Cockroachdb-Specific Remediation in Adonisjs — concrete code fixes

To prevent SSTI when using CockroachDB in AdonisJS, ensure user input never reaches the template engine in a way that can alter control flow or query construction. Use strict validation, context-aware escaping, and parameterized queries.

  • Validate and sanitize all inputs before they reach views. Use AdonisJS schema validation to enforce type, length, and allowed characters.
  • Prefer parameterized queries with the Lucid ORM or query builder instead of string interpolation.
  • Apply output escaping for any data rendered in templates, using Edge’s built-in escaping.

Code examples

Unsafe pattern: Dynamic query construction influenced by template-tainted input

// routes.ts
import Route from '@ioc:Adonis/Core/Route'

Route.get('/search', async ({ request, view }) => {
  const search = request.qs().search // user input
  // Unsafe: using input to decide which columns to select
  const column = search == 'name' ? 'username' : 'email'
  const results = await User.query().select(column).where('tenant_id', currentTenantId)
  await view.render('dashboard', { results, search })
})

// resources/views/dashboard.edge
@if(search === 'name') @for(let row of results) {{ row.username }} @endfor @else @for(let row of results) {{ row.email }} @endfor @endif

Safe pattern: Parameterized queries and strict context-aware rendering

// routes.ts
import Route from '@ioc:Adonis/Core/Route'
import { schema } from '@ioc:Adonis/Core/Validator'

const searchSchema = schema.create({
  search: schema.string.optional({}, [ 'normalize_whitespace' ])
})

Route.get('/search', async ({ request, view }) => {
  const payload = await request.validate({ schema: searchSchema })
  const search = payload.search

  // Always use parameterized queries; never interpolate user input into SQL strings
  const query = User.query().where('tenant_id', currentTenantId)
  if (search) {
    query.whereILike('username', `%${search}%`)
  }
  const results = await query.exec()

  // Safe: Edge auto-escapes by default in {{ }}
  await view.render('dashboard', { results, search })
})

// resources/views/dashboard.edge
@if(search) Results for {{ search }} @endif
    @for(let row of results)
  • {{ row.username }} — {{ row.email }}
  • @endfor

Tenant isolation with CockroachDB: Use runtime-bound tenant identifiers and avoid dynamic database/table names.

// Always resolve tenant from authenticated session, not from user input
import { getTenantIdFromSession } from 'src/lib/auth'

Route.get('/profile', async ({ auth, view }) => {
  const tenantId = getTenantIdFromSession(auth)
  const profile = await User.query()
    .where('tenant_id', tenantId)
    .where('id', auth.user!.id)
    .firstOrFail()

  await view.render('profile', { profile })
})

// In your Edge template, never reconstruct table or column names from user input
// UNSAFE: `User.query().table(userSuppliedTable).where(...)`
// SAFE: use a static schema and tenant scoping

Frequently Asked Questions

Can SSTI in AdonisJS with CockroachDB lead to direct SQL injection?
SSTI primarily affects template logic execution. However, if template-injected logic alters SQL query construction, it can lead to unauthorized data access. Direct SQL injection is prevented by using parameterized queries and avoiding string interpolation; the risk is indirect via template-driven query manipulation.
How does middleBrick help detect SSTI risks with CockroachDB integrations?
middleBrick correlates runtime behavior with OpenAPI specifications and runs unauthenticated probes to identify where templates handle untrusted data that influences backend calls. It highlights paths where template logic can affect database interactions, providing remediation guidance focused on input validation and output escaping.