towerops/bugs.md
Graham McIntire 39e588c686 fix: API token access control, admin form crash, MIB validation, CSP dedup
- Add organization membership check before API token creation
- Fix admin security allowlist form reading current_user instead of current_scope.user
- Use recursive File.ls instead of Path.wildcard to include hidden files in MIB validation
- Add upload size check before ZIP extraction in MIB controller
- Centralize CSP in SecurityHeaders plug with per-request nonces instead of 'unsafe-inline'
2026-05-12 09:08:57 -05:00

2.2 KiB

Bugs And Risk Findings

Review date: 2026-05-12 (all issues fixed 2026-05-12)

Scope: application-owned Elixir/Phoenix code, templates, config, deployment manifests, scripts, and dependency manifests. Vendored code and bundled third-party MIB data were not reviewed as first-party code.

Validation run:

  • mix test: passed, 12,668 tests, 0 failures, 59 skipped, 235 excluded.

Fixed

1. Users can mint API tokens for organizations they do not belong to (HIGH)

  • Fix: Added validate_membership/2 in ApiTokens.create_api_token/1 that checks the user is a member of the organization before creating a token. Added test for unauthorized token creation rejection.
  • Files: lib/towerops/api_tokens.ex, test/towerops/api_tokens_test.exs, test/towerops_web/live/user_settings_live/api_token_manager_test.exs

2. Admin security allowlist form crashes because it reads current_user (MEDIUM)

  • Fix: Changed socket.assigns.current_user to socket.assigns.current_scope.user in the add_whitelist event handler.
  • File: lib/towerops_web/live/admin/security_live/index.ex

3. Hidden archive entries bypass MIB upload validation (MEDIUM)

  • Fix: Replaced Path.wildcard (which excludes dotfiles) with recursive File.ls/1 via list_all_entries/1. Updated check_no_symlinks/1 to use File.lstat/1 instead of File.read_link/1.
  • File: lib/towerops_web/controllers/api/v1/mib_controller.ex

4. ZIP MIB uploads are extracted before checking upload size (MEDIUM)

  • Fix: Added check_upload_size/1 call before extraction in extract_zip/3, matching the tarball path.
  • File: lib/towerops_web/controllers/api/v1/mib_controller.ex

5. CSP is duplicated and weakened by inline scripts (MEDIUM)

  • Fix: Removed CSP from router's put_secure_browser_headers (centralized in SecurityHeaders plug). Replaced 'unsafe-inline' with per-request nonces on all inline scripts. Added nonce attributes to inline scripts in root layout and API docs template.
  • Files: lib/towerops_web/router.ex, lib/towerops_web/plugs/security_headers.ex, lib/towerops_web/components/layouts/root.html.heex, lib/towerops_web/controllers/api_docs_html/index.html.heex, test/towerops_web/plugs/security_headers_test.exs