Skip to content

Security Enhancements: Implement rate limiting, whitelist ORDER BY and filter fields, replace os.execute() - #483

Open
cycomachead wants to merge 1 commit into
mainfrom
cycomachead/9-security-enhancements-audit/3
Open

cycomachead wants to merge 1 commit into
mainfrom
cycomachead/9-security-enhancements-audit/3

Conversation

@cycomachead

Copy link
Copy Markdown
Member

Security Enhancements: Rate Limiting, SQL Injection Prevention, Shell Injection Removal

Implements four security fixes from a prior audit: rate limiting on login, whitelisting of ORDER BY and filter parameters to prevent SQL injection, and removal of shell-out calls in disk.lua.

Changes

  • Login rate limiting: added rate_limit(self) to the login action in controllers/user.lua, matching signup, password reset, and username reminder.
  • ORDER BY whitelisting: added a shared order_by_clause helper in validation.lua that parses "column [ASC|DESC]", only allows columns in a per-controller whitelist, and returns a 400 on anything else. Applied to controllers/project.lua, controllers/collection.lua, and controllers/user.lua, each with a whitelist matching the sort options actually used by the UI/views.
  • Filter field whitelisting: added a shared filter_clause helper in validation.lua replacing the old code that spliced any filter_* param name directly into SQL. Only verified, is_teacher, and role are accepted in controllers/user.lua; values remain bound parameters, and empty values (the "Any" dropdown option) are now skipped instead of generating = '' comparisons.
  • Shell-free disk.lua: replaced all os.execute calls and the io.popen-based stat timestamp lookup with LuaFileSystem (mkdir_p, copy_file preserving mtimes, lfs.attributes). Removed the now-unused stat_arguments config value and STAT_ARGS env passthrough in nginx.conf; added luafilesystem as an explicit rockspec dependency.
  • Field-selection hardening (bonus, in scope of the same lines): the run_query functions in project.lua, collection.lua, and user.lua previously spliced self.params.fields (a client-controllable request param) into the SELECT list. Changed these to use an internal self.fields set only by controller code, and updated the corresponding server-side setters. No client code sends fields today.

Notes for reviewers

  • locale.lua still contains one os.execute('cp ...'), but the interpolated value is hardcoded to en in a dev-only tool, so it's not exploitable — left untouched.
  • controllers/old/user.lua is unused/unloaded and was not touched.
  • No app-level test suite exists and the app requires Postgres to boot, so verification was done via standalone Lua scripts exercising the new helpers and disk.lua behavior (see commit history/conversation for details), not full end-to-end testing.

Superconductor Ticket Implementation | App Preview | Guided Review

…d replace os.execute

- Add rate limiting to the login endpoint to prevent brute-force attacks
- Whitelist ORDER BY parameters and filter fields across controllers to prevent SQL injection
- Replace shell-out `os.execute` and `io.popen` calls in `disk.lua` with LuaFileSystem to eliminate shell injection vectors
- Restrict query field selection to internal controller sets instead of trusting request parameters

https://www.superconductor.com/tickets/t7rHzQtzpFnH/implementations/KP7L7LQtmcNc#message_KtFCKpMk9tNH

Co-authored-by: Claude Code <noreply@anthropic.com>
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.

1 participant