• v0.5.8 1fbb143a3e

    MyFSIO v0.5.8 Beta Pre-Release

    kqjy released this 2026-08-12 06:24:11 +00:00 | 0 commits to main since this release

    Security

    Authorization & Authentication

    • Fixed P0 bucket-name path escape: full S3 bucket-name syntax plus canonical containment is now enforced inside the storage backend (require_bucket, bucket_exists, create_bucket, multipart paths, versioning checks) — a percent-encoded absolute path in the bucket position can no longer replace STORAGE_ROOT.
    • Fixed P0 query-selector precedence mismatch at both bucket and object level: one shared BucketSubresource/ObjectSubresource parser is used by the auth middleware and every dispatcher. Multiple selectors are rejected with InvalidArgument at authorization time; non-dispatchable selectors return MethodNotAllowed instead of falling through. Closes an authenticated list-to-policy escalation, its unauthenticated variant on public-read buckets, and read-only principals writing/deleting via ?attributes/?select/?uploads/?retention.
    • The auth middleware percent-decodes bucket, key, and copy-source so it authorizes the same strings the handlers act on.
    • Every key in DeleteObjects is re-authorized individually — a prefix-scoped principal can no longer delete outside its prefix.
    • Presigned requests must sign every x-amz-* header (except content-sha256/date/decoded-content-length), closing copy-source, ACL, SSE, and governance-bypass header injection by URL bearers.
    • Bucket policies fail closed on unsupported Condition/NotPrincipal/NotAction/NotResource elements at evaluation, and reject them at both write paths.
    • is_admin now requires an unrestricted policy prefix — a prefix-scoped wildcard policy no longer short-circuits every authorization check.
    • Bucket-policy Resource keys match case-sensitively; bucket and Action matching stay case-insensitive.
    • An unreadable .bucket.json is treated as fail-closed across policy evaluation, object write/delete, and all config writes (previously acted as an empty config).
    • x-amz-bypass-governance-retention is honored only for admins or principals granted the new bypass_governance IAM action (or s3:BypassGovernanceRetention in a bucket policy), evaluated per key on bulk delete.
    • New IAM actions: system:gc_read/gc_run/integrity_read/integrity_run replace admin-only gating of GC and integrity on both the admin API and UI; ownershipControls/publicAccessBlock gain dedicated ownership_controls/public_access_block actions; action_matches generalized from hardcoded iam:* to any namespace:*.
    • Added missing bucket authorization to 11 UI handlers.

    Path Traversal & Input Validation

    • Multipart uploadId/segment ids are validated as 32-hex before any filesystem join — abort_multipart previously remove_dir_all'd caller-controlled paths, capable of destroying .myfsio.sys/config in one request.
    • Reserved __/x-amz- metadata keys are rejected at all five ingress points, including CopyObject, UI multipart init, and peer pull (x-amz-meta-__segments__ could reach recursive segment deletion and redirect segment reads).
    • UI restore version_id is validated to a single path component.
    • PutBucketLogging TargetBucket and website-domain mappings reject invalid bucket names; ListBuckets and --rebuild-listing skip invalid-named directories with a warning instead of failing.

    Secrets & Encryption

    • First-run and reset admin credentials are written encrypted, with a one-time plaintext-to-encrypted migration at startup; env-provided secrets are no longer echoed to stdout.
    • SECRET_KEY auto-generation persists to .myfsio.sys/config/.secret; the literal value dev-secret-key is rejected from both env and file.
    • iam.json, KMS master keys, kms_keys.json, .connections_key, connections.json, and .secret are all written owner-only through shared atomic helpers (myfsio_common::fs_util).
    • The server exits non-zero when ENCRYPTION_ENABLED/KMS_ENABLED init fails, and fails closed on bucket-default encryption instead of silently storing plaintext.
    • IAM disable-user/create-key/delete-key are routed through load_config/save_config so revocation works against an encrypted iam.json.
    • IAM mutations are serialized behind a mutation lock and persisted atomically (tmp + fsync + rename).

    Web UI

    • Fixed XSS via data-carrying inline onclick handlers — replaced with delegated data-* listeners (verified in-browser).
    • Anonymous requests use ephemeral sessions that never enter the session store; capacity eviction prefers unauthenticated sessions.
    • GET/POST /login is rate limited per IP (RATE_LIMIT_UI_LOGIN, default 20/minute) with a styled 429 page and Retry-After.

    S3 API

    • Object lock: PutBucketObjectLockConfiguration validates the XML and requires versioning (409 InvalidBucketState); DefaultRetention is now actually applied at every user-facing object-creation path (explicit headers win; replication/peer-pull/restore untouched). Retention and legal-hold updates are check-and-set under the per-object stripe lock via new update_object_retention/update_object_legal_hold trait methods — concurrent requests can no longer shorten COMPLIANCE retention, and legal-hold writes no longer clobber concurrent metadata. Same-mode extension needs no bypass; shortening, removal, and mode changes keep the bypass rules.
    • Static website hosting streams through the new handlers/object_read data plane: SSE-S3/SSE-KMS assets that were served as ciphertext are decrypted, HEAD reports plaintext Content-Length, 206 ranges use plaintext offsets, SSE-C assets return 403, and no path buffers whole objects in memory.
    • Ranged S3 GETs validate SSE-C keys like the whole-object path (400/403 instead of 500).
    • Unknown encoding-type values are rejected; max-keys is capped at 1000.
    • Date-based lifecycle rules are a no-op until the date passes, instead of using the configured date as an age cutoff.
    • Request-body limits on every config/XML/JSON ingress (1 MiB config XML and Select, 8 MiB CompleteMultipartUpload/DeleteObjects, 1–2 MiB JSON, bounded relay-outbound, 1 MiB non-file multipart form fields) with a new MaxMessageLengthExceeded error code.

    Storage & Durability

    • A failed PUT commit rolls back the archived version and metadata sidecar; the archived-null purge runs after the rename, so a failed commit can never destroy the prior null version.
    • Fixed quarantine GC protection reading the wrong metadata root, multipart corruption false positives in the integrity scanner, and issue-count reporting; removed the legacy heal path.
    • GC skips a bucket's segment sweep whenever the reference scan hit a read error, and reports the skip — an incomplete scan can no longer delete live segment data.

    Background Services & Reliability

    • Site sync aborts the cycle on any remote-listing failure instead of treating NoSuchBucket/404 as an empty bucket (sync_deletions could previously erase every locally synchronized object), and records last_error/last_error_at per bucket, surfaced on the Sites page.
    • The process exits non-zero when either listener task dies, so systemd restarts it.

    Web UI

    • UI part upload streams to disk with a 5 GiB cap instead of buffering each part twice in memory.
    • Failed uploads surface the real S3 error reason in the toast and upload dialog instead of a bare failure count.
    • Fixed dead cluster-page JavaScript, copy/move destination bucket default, audio preview stage height, and assorted polish.
    • Each System dashboard card names the specific missing permission when access is denied.

    Installer

    • install.sh/uninstall.sh canonicalize and refuse system paths, guard foreign data directories behind --adopt-data-dir, track installer-created users in a manifest so uninstall preserves pre-existing accounts, and re-installs preserve myfsio.env (--overwrite-env backs up then regenerates).

    Added

    • handlers/object_read.rs (shared streaming object-read data plane), myfsio_common::fs_util (atomic owner-only file helpers), login_rate_limited.html.
    • IAM actions: bypass_governance, system:gc_read/gc_run/integrity_read/integrity_run, ownership_controls, public_access_block.
    • Error codes: S3ErrorCode::MaxMessageLengthExceeded, S3ErrorCode::InvalidBucketState, StorageError::InvalidArgument.
    • Config: RATE_LIMIT_UI_LOGIN (default 20 per minute).
    • Validation helpers: is_valid_multipart_id, is_reserved_metadata_key, is_reserved_user_metadata_key, is_safe_path_segment, bucket_name_rejection; BucketConfig::unreadable.

    Removed

    • Dead has_query_key helper and the legacy integrity heal path.
    Downloads