Straight Into The Page

An analytics assistant turns a question into SQL, runs it, and renders an explanation of the rows. Which of these let untrusted text reach somewhere it is executed or interpreted as code? More than one applies.

app.post('/ask', async (req, res) => {
  const sql  = await model.generateSQL(req.body.question);
  const rows = await db.query(sql);                 // pool user: app_rw
  const text = await model.explain(rows);
  res.send(`<div class="answer">${text}</div>`);
});
A

rows is untrusted input to the second model call, so a value a customer typed into a free-text field earlier can carry instructions into model.explain.

B

There is no rate limit on /ask, so an attacker can drive unbounded model spend.

C

The generated statement executes under the application's read-write role, so nothing constrains it to a read or to the asking user's own tenant.

D

text is interpolated into the response body with no contextual output encoding, so a script tag or an event handler the model emits runs in the reader's browser.

E

res.send sets no explicit Content-Type, so browsers content-sniff the response and may execute it as JavaScript.