Мені 18, я будую Zero-Knowledge сховище і борюся з Microsoft Partner Center. Прошу брутального код-рев’ю

Кожен лист від Microsoft із темою «Action Required», це нагадування, наскільки тернистим є шлях від пет-проєкту до релізу реального продукту.

Мене звати Андрій Шумко, мені 18 років. Замість звичних розваг, моїм основним квестом останнього місяця стало проходження верифікації в Microsoft Partner Center для релізу FABY Cloud.

Чи це втомлює? О так.
Чи воно того варте? Однозначно.

Що таке FABY Cloud? Це спроба створити справжнє Zero-Knowledge середовище. Я не просто роблю «чергову хмару», я будую систему, де сервер фізично не може прочитати файли користувача.

Технічні деталі:

  • Шифрування: AES-256-GCM на клієнті. Ключі ніколи не залишають пристрій.
  • Архітектура: Direct-to-Cloud через Presigned URLs. Файли (навіть зашифровані) йдуть в Edge-сховище в обхід мого бекенду.
  • Відновлення: 12-слівна Seed-фраза для шифрування майстер-ключа.
  • Стек: FastAPI, Python, асинхронна обробка чанків для Multipart завантаження.

Зараз я на фінішній прямій перед виходом у Store, але мені критично потрібен погляд зі сторони. Я звертаюся до спільноти DOU: мені потрібен фідбек від Senior-розробників та експертів із кібербезпеки.

Я розумію, що в 18 років замахуватися на «екосистему» (у планах ще P2P-браузер та Faby Grid-мережа, детальніше на сайті) — це зухвало. Саме тому я прошу найжорсткішої критики мого коду. Я прийшов за досвідом.

Мій GitHub тут: github.com/Ashixi/FABY-Cloud.git

Заздалегідь дякую за фідбек)

Підписуйтеся на Telegram-канал «DOU #tech», щоб не пропустити нові технічні статті

👍ПодобаєтьсяСподобалось3
До обраногоВ обраному0
LinkedIn
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

Привіт,

Найтяжча частина це перемога над Partner Center :)

Я не експерт в вашому стеці, але натравив Claude Code на проект, ось що він видав:

Critical Issues

1. IDOR on Storage Usage — Client Controls Billing (storage_route.py:698-714)

The PATCH /usage/update endpoint lets the authenticated user send an arbitrary delta_bytes value. A malicious user can send a large negative delta to set their storage_used_bytes to 0 while keeping all files, effectively bypassing
storage limits. This endpoint should be removed or made internal-only — storage accounting should only be done server-side (as confirm-upload already does).

2. No file_id Input Validation — Path Traversal (storage_route.py:146)

file_id is used directly in S3 key construction: f"user_storage/{public_id}/files/{request.file_id}". A crafted file_id like ../../other_user/files/secret could traverse the S3 key namespace and access another user’s files. All IDs
(file_id, node_id, board_id, manifest_id) need validation — e.g., enforce UUID format or reject values containing /, .., etc.

3. Board Access Check Bypass (storage_route.py:646-648)

board = db.query(Board).filter(Board.id == request.board_id).first()
if board:
# ... access check ...
If the board doesn’t exist in the DB (board is None), the access check is skipped entirely, and a presigned URL is generated for an arbitrary board_id path. This allows uploading/downloading to any board storage path. Fix: return 404
when board is None.

4. Trash Restore Doesn’t Re-add Storage for Logical Items (storage_route.py:339-347)

logical_restore removes the trash record but never adds the freed bytes back to storage_used_bytes. Compare with restore_trash (line 407) which does. Users could exploit this: delete files (frees quota), restore them (quota not
re-added), upload more files — exceeding their actual storage limit.

5. Race Condition on confirm-upload (storage_route.py:188-214)

The “check marker → create marker → update bytes” sequence is not atomic. Two concurrent confirm requests for the same file could both pass the marker check and double-count the storage bytes. Use a DB-level unique constraint or S3
conditional write instead.

6. Share ID Brute-Force (storage_route.py:467)

share_id = uuid.uuid4().hex[:16] gives 64 bits of entropy. The download endpoint (/share/download/{share_id}) has no rate limiting and no authentication. This makes share links enumerable with sufficient effort. Consider using the
full UUID (128 bits) or adding rate limiting.

---
Moderate Issues

7. Bare except: Swallows All Errors (storage_route.py:233-234)

except:
pass
This catches KeyboardInterrupt, SystemExit, etc. Use except Exception: instead.

8. TrashItem Model Missing from models.py

TrashItem is imported and used extensively but not defined in the provided models.py. If it lacks a deleted_at default timestamp or proper indexing on owner_public_id, the trash cleanup job won’t work correctly.

9. Hardcoded device_id (auth_http_client.dart:103)

’device_id’: ’boardly_drive_client’,
All clients share the same device ID. If the server enforces per-device token revocation, this means revoking one device revokes all.

10. SQLite DB Not Encrypted (vfs_manager.dart:46-48)

The README claims “stored locally in an encrypted SQLite database” but the code uses plain openDatabase with no encryption. If local-at-rest encryption is a requirement, use sqflite_sqlcipher or equivalent.

11. _loadToMemory() on Every Mutation (vfs_manager.dart:358)

Every _saveNode, deleteNodes, toggleFavorite call does a full SELECT * from the DB and rebuilds the entire in-memory list. This is O(n) per operation and will degrade with large file trees. Update the in-memory cache directly instead.

12. Deprecated datetime.utcnow (models.py:38,48)

datetime.utcnow is deprecated in Python 3.12+. Use datetime.now(datetime.UTC) instead.

---
Summary

The two most urgent fixes are #1 (client-controlled billing) and #2 (path traversal via file_id). Issue #3 (board access bypass) is also high priority. These are all server-side and could be exploited by any authenticated user with a
modified client.

Є справді критичні дірки в логіці, котрі я прогледів, особливо з лімітами сховища, буду вирішувати це першим ділом. Також дякую, що нагадали про локальну базу. Архітектура проєкту Zero-Knowledge, тож шифрування SQLite там має бути обов’язково, вже шукаю рішення для реалізації.
Занесу це все у список задач на GitHub. Дякую за допомогу!

Підписатись на коментарі