Skip to content

add slack bot - #122

Open
amyliiu wants to merge 7 commits into
mainfrom
feat/slack-bot
Open

amyliiu wants to merge 7 commits into
mainfrom
feat/slack-bot

Conversation

@amyliiu

@amyliiu amyliiu commented Aug 20, 2026

Copy link
Copy Markdown
Contributor
  • Add a Slack Events webhook (/api/slack/events) so organizers can @mention a bot and ask natural-language questions about dashboard Postgres (read-only SQL via Drizzle).
  • Restrict access to Slack users whose email matches a users row with role organizer; skip session auth for /api/slack.
  • Wire Slack/OpenAI secrets into ECS (task-definition.json) and document app setup, env vars, and local tunneling in docs/slack.md.

…oard data.

Co-authored-by: Cursor <cursoragent@cursor.com>
@amyliiu
amyliiu requested review from arnavs-0 and hujalex August 20, 2026 14:46

@hujalex hujalex left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated code review (medium effort). 10 findings, most severe first. Verified as non-issues: signature verification (constant-time, length-checked, 5-minute skew), the intentional /api/slack middleware bypass, SET LOCAL transaction_read_only = on after a prior SET, the ai/@ai-sdk/openai lockfile resolution, and the hasSeenEvent LRU eviction.

Comment thread lib/slack/sql.ts Outdated
Comment thread lib/slack/thread.ts Outdated
Comment thread lib/slack/authorize.ts
Comment thread lib/slack/handle-mention.ts Outdated
Comment thread app/api/slack/events/route.ts Outdated
Comment thread lib/slack/sql.ts Outdated
Comment thread lib/slack/sql.ts Outdated
Comment thread lib/slack/format.ts Outdated
Comment thread lib/slack/thread.ts Outdated
Comment thread lib/slack/handle-mention.ts Outdated
amyliiu and others added 3 commits September 14, 2026 19:07
… trust, and event handling.

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@amyliiu
amyliiu requested a review from hujalex September 14, 2026 23:50
@hujalex

hujalex commented Sep 15, 2026

Copy link
Copy Markdown
Contributor

Wait, looks good to me, only thing is wondering if the keys are in the prod environment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fragile to schema updates. can this be a simple query for schema instead

Comment thread lib/slack/sql.ts

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this isn't safe. can we do something tighter like a read only posgres role that the orm temp assumes?

Comment thread lib/slack/verify.ts

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is there a slack sdk or something. this feels a bit brute.

@pradhamk pradhamk left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Please use Slack SDK for typescript so the bot can be reusable in the future and is resilient against api changes from slack
  2. Query the general schema of each table in schema-prompt.ts rather than defining each table manually (this will break easily if we make a table change during the hackathon). Instead, just whitelist the columns that the bot can read maybe? (we will never remove columns, only add during the event)
  3. Unsafe transactions are a big no-no in sql.ts. Should be able to use safe transactions here and be fine since we are only doing reads.

Security Issues:

  1. SQL allowlist bypass via derived-table subquery — lib/slack/sql.ts:341
  • Severity: High
  • Category: authorization_bypass / sql_scope_bypass
  • Confidence: 9/10

Description: validateReadonlySelect() is the only thing constraining LLM-authored SQL before it is executed with tx.unsafe() on the application's privileged Postgres connection (lib/slack/sql.ts:447-451, pool from lib/db/index.ts:17). Its table allowlist is applied by extractTableNames(), which scans for from/join word tokens — but when a from/join is immediately followed by (, it calls skipParens() and advances the loop index past the closing parenthesis (lib/slack/sql.ts:341-348). Every token inside a derived table is therefore never examined: neither ALLOWED_TABLES (lib/slack/sql.ts:124-129) nor the public-only schema check in parseQualifiedName() (lib/slack/sql.ts:380-382) is reached. SELECT * FROM (SELECT * FROM auth.users) AS q passes validation. The same applies to JOIN (…) and to nesting inside CTE bodies. Note the non-derived forms are caught — SELECT (SELECT count(*) FROM auth.users) FROM users correctly throws — so the control looks like it works while being inert for the most natural subquery shape.

  1. SQL allowlist bypass via query-taking XML built-ins — lib/slack/sql.ts:48
  • Severity: High
  • Category: authorization_bypass / sql_scope_bypass
  • Confidence: 9/10

Description: tokenizeSql() reduces every string literal to a contentless { type: "string" } token with no value field (lib/slack/sql.ts:226; same for dollar-quoted strings at lib/slack/sql.ts:174-184), so nothing inside a literal is ever inspected. Postgres ships built-ins that take a SQL string or a regclass and execute it under the caller's privileges, and FORBIDDEN_FUNCS (lib/slack/sql.ts:48-56) does not list any of them. SELECT query_to_xml('SELECT * FROM auth.users', true, false, '') contains no from/join token outside the literal, so extractTableNames() returns [] and the allowlist loop never executes at all. checkForbidden() sees only select, query_to_xml, true, false. The outer wrapper SELECT * FROM () AS q LIMIT 25 is valid around a FROM-less select, and is appended after validation so it cannot re-trigger the scanner.

…list holes.

Co-authored-by: Cursor <cursoragent@cursor.com>
@amyliiu

amyliiu commented Sep 15, 2026

Copy link
Copy Markdown
Contributor Author

@pradhamk addressed in ac40d83:

  1. Slack Node SDK: request verification now uses @slack/bolt (isValidSlackRequest), events use @slack/types (AppMentionEvent), and the Web API client stays on @slack/web-api.
  2. Schema prompt is built from information_schema.columns for the allowlisted tables so added columns show up without a manual prompt edit.
  3. SET LOCAL runs as tagged-template queries. The validated SELECT still has to go through unsafe because postgres.js cannot interpolate a whole statement into a tagged template.

Security: extractTableNames now walks derived-table / subquery parens after FROM/JOIN, and query-taking XML / dblink-style functions are on the forbidden list.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants