Skip to content

Instantly share code, notes, and snippets.

@patricksimpson
Created March 15, 2026 17:46
Show Gist options
  • Select an option

  • Save patricksimpson/6565ea0fd9674234cad3219779957ba3 to your computer and use it in GitHub Desktop.

Select an option

Save patricksimpson/6565ea0fd9674234cad3219779957ba3 to your computer and use it in GitHub Desktop.
izerop audit - remaining findings (2026-03-15)

izerop Audit — Remaining Findings (2026-03-15)

Items not yet fixed from the full audit. Organized by repo.

izerop (Server)

MEDIUM

  • N+1 in directory_json file_count — Each directory triggers a separate COUNT query in index. Fix: counter_cache or preloaded counts with subquery. (app/controllers/api/v1/directories_controller.rb)
  • N+1 in UserDirectory#path_display — Recursive parent loading for path construction. O(depth × N) queries on manifest endpoint. Fix: materialized path column. (app/models/user_directory.rb:33-43)
  • changes API limit logic bug — fetch_file_changes queries both active AND deleted with same limit, so actual count can be up to 2× limit. has_more can give false positives causing sync clients to loop. (app/controllers/api/v1/sync_controller.rb:10-23)
  • No Content-Type validation on upload — Only extension denylist enforced. .html/.svg files could contain scripts. Consider Content-Disposition: attachment on S3 objects. (app/uploaders/file_uploader.rb)

LOW

  • No resolve_sync_client key format validation — Any string accepted for X-Client-Key header. Not exploitable but could lead to junk data. (app/controllers/api/v1/base_controller.rb:52-57)
  • Missing pagination on files#index and directories#index — Returns ALL records with no limit/offset. (app/controllers/api/v1/files_controller.rb:10, directories_controller.rb:8)
  • parse_timestamp fallback — Invalid timestamps silently fall back to 1 year ago, returning huge volume of changes. Consider returning error. (app/controllers/api/v1/sync_controller.rb:85)

izerop-cli (CLI)

MEDIUM

  • remoteToLocal no Unicode normalization — macOS NFD vs Linux NFC decomposition could create duplicate sync entries cross-platform. (pkg/sync2/engine.go:686-701)
  • PID file race — Two daemon starts can race on PID file write. No flock. (cmd/izerop/main.go:929)
  • filepath.Walk TOCTOU on symlink check — info from Walk uses os.Stat (follows symlinks), then os.Lstat is called separately. Symlink could be swapped between calls. Low practical risk. (pkg/sync2/engine.go:299-308)
  • Binary update delete+create non-atomic — Updating binary files deletes remote first then re-uploads. Crash between = file lost on server. Fix: upload with temp name, delete old, rename. (pkg/sync2/engine.go:519-521)

LOW

  • Download timeout fixed at 120s — Not configurable, could be insufficient for large files on slow connections. (pkg/api/client.go:285)
  • SyncPull uses recursion for pagination — HasMore triggers recursive call. Many pages could stack overflow. Use iteration. (pkg/sync2/engine.go:232-245)
  • addWatchRecursive can hit inotify limits — Error from fsw.Add(path) is returned but walk continues. Some dirs silently unwatched. (pkg/sync2/watcher.go:278-290)
  • Config tokens stored as plaintext — File permissions are 0600 (good) but visible to same-user processes. Consider OS keychain. (pkg/config/config.go:16)
  • If-Match header quoting — Set as "hash" (quoted). Works if server strips quotes per RFC 7232, but could fail on strict implementations. (pkg/api/client.go:439)
  • Test cleanup via init() fragile — Should use t.Cleanup() per-test. (pkg/sync2/engine_test.go:893-907)

Missing Test Coverage (CLI)

  • No tests for SyncPull (cursor-based changes API path)
  • No tests for SyncPush (only full Sync tested)
  • No tests for path traversal (safePath validation)
  • No tests for conflict resolution (ResolveConflict)
  • No tests for v1→v2 migration (MigrateFromV1)
  • No tests for the watcher (fsnotify → push cycle)
  • No tests for symlink handling in buildLocalTree
  • No tests for concurrent sync (two engines on same profile)
  • No tests for binary file upload (delete+create path)
  • No tests for error recovery (API failures mid-sync)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment