Skip to content

Cloud Storage Security Rules: File-Level Access Control Guide

DodaTech Updated 2026-06-28 4 min read

In this tutorial, you will learn about Cloud Storage Security Rules: File. We cover key concepts, practical examples, and best practices to help you master this topic.

Cloud Storage Security Rules control who can read and write files in your storage bucket, with conditions based on authentication, file path, content type, size, and custom metadata.

What You'll Learn

How to write Storage Security Rules that restrict file access to document owners, validate upload types and sizes, prevent unauthorized downloads, and implement admin overrides.

Why It Matters

Without storage rules, any authenticated user can access any file in your bucket. DodaTech's Antivirus Pro stores user-uploaded malware samples — rules ensure users only see their own submissions.

Real-World Use

A threat sample Repository where users upload suspicious files. Rules restrict read/write to the file owner, limit uploads to 100MB, block executable files, and allow admins full access.

flowchart LR
    A["File Request"] --> B{"Authenticated?"}
    B -->|No| C["DENY"]
    B -->|Yes| D{"Path matches\nuser ID?"}
    D -->|No| E{"Is Admin?"}
    E -->|No| C
    E -->|Yes| F["ALLOW"]
    D -->|Yes| G{"File type/size\nallowed?"}
    G -->|No| C
    G -->|Yes| F
    style C fill:#fecaca,stroke:#dc2626
    style F fill:#bbf7d0,stroke:#16a34a

Basic Auth Check

rules_version = '2';
service firebase.storage {
  match /b/{bucket}/o {

    // Only authenticated users can read files
    match /{allPaths=**} {
      allow read: if request.auth != null;
      allow write: if request.auth != null;
    }
  }
}

User-Owned Files Pattern

rules_version = '2';
service firebase.storage {
  match /b/{bucket}/o {

    // Files stored at: users/{userId}/samples/{filename}
    match /users/{userId}/{allPaths=**} {
      allow read, write: if request.auth != null
                       && request.auth.uid == userId;
    }

    // Admin access to all files
    match /{allPaths=**} {
      allow read: if request.auth != null
               && request.auth.token.isAdmin == true;
    }
  }
}

File Type and Size Validation

rules_version = '2';
service firebase.storage {
  match /b/{bucket}/o {

    match /users/{userId}/samples/{filename} {

      // Validate on create
      allow create: if request.auth != null
                 && request.auth.uid == userId
                 // Block executable files
                 && !request.resource.contentType.matches('application/x-*')
                 // Limit file size to 100 MB
                 && request.resource.size < 100 * 1024 * 1024
                 // Allow only specific types
                 && request.resource.contentType.matches('image/.*')
                 || request.resource.contentType.matches('text/.*')
                 || request.resource.contentType.matches('application/pdf');

      // Owner can read and update
      allow read, update: if request.auth != null
                        && request.auth.uid == userId;

      // Owner can delete
      allow delete: if request.auth != null
                 && request.auth.uid == userId;
    }
  }
}

Custom Metadata Validation

rules_version = '2';
service firebase.storage {
  match /b/{bucket}/o {

    match /users/{userId}/reports/{reportId} {

      allow create: if request.auth != null
                 && request.auth.uid == userId
                 // Require custom metadata
                 && request.resource.contentType == 'application/pdf'
                 && request.resource.size < 10 * 1024 * 1024
                 && request.resource.customMetadata.keys().hasAll(
                      ['threatLevel', 'deviceId']);
    }
  }
}

Time-Limited Access

rules_version = '2';
service firebase.storage {
  match /b/{bucket}/o {

    match /shared/{allPaths=**} {

      // Expire shared files after 24 hours
      allow read: if request.auth != null
               && request.time < resource.timeCreated +
                  duration.value(24, 'h');

      allow write: if request.auth != null
                && request.auth.uid == userId;
    }
  }
}

Common Mistakes

1. Using allow read, write When Granular Rules Are Needed

Broad read/write rules expose files unnecessarily. Separate read, create, update, and delete rules with specific conditions.

2. Forgetting request.resource for Write Validation

Write rules validate against request.resource (the incoming file). Without request.resource.size and request.resource.contentType checks, users can upload any file type.

3. Not Handling File Type Safety

Users can upload files with fake content types. The contentType comes from the client and can be spoofed. For security-critical apps, verify content type server-side with Cloud Functions.

4. Path Traversal Vulnerabilities

User-controlled paths like {filename} can include ../ to escape their directory. Sanitize file names on the client and validate in rules.

5. Ignoring Deletion Rules

Without explicit allow delete: if false, users who have write access can delete files. Use separate delete rules to control removal.

Practice Questions

  1. How do Storage Rules differ from Firestore Rules?
  2. What is request.resource in Storage Rules?
  3. How do you restrict uploads to image files only?
  4. How do you implement admin overrides in Storage Rules?

Answers:

  1. Storage Rules operate on file metadata (size, content type, path). Firestore Rules operate on document data and fields. Both use request.auth for authentication.
  2. request.resource represents the file being uploaded, with properties like size, contentType, and customMetadata.
  3. Use request.resource.contentType.matches('image/.*') in the allow create condition.
  4. Store admin status in request.auth.token.isAdmin using custom claims, and add allow read: if request.auth.token.isAdmin == true for all paths.

Challenge: Write Storage Rules for Durga Antivirus Pro's sample submission system: user-owned paths, PDF/images only, max 50MB, block executables, require threat-level metadata, and give security analysts read access to all samples.

FAQ

Can Storage Rules call Firestore data?

No, Storage Rules cannot access Firestore. For rules that depend on database state, use Cloud Functions to verify access before returning signed URLs.

How do I test Storage Rules?

Use the Rules Playground in Firebase Console under Storage > Rules. Simulate uploads and downloads with different auth states and file properties.

Do Storage Rules affect file listing?

Yes. When a user calls listAll(), only files readable by that user are returned based on the Storage Rules.

Can I set rules on specific file extensions?

Storage Rules don't have native extension matching. Use contentType validation or match patterns in the file path.

What happens to rules after a file is uploaded?

Rules apply to every access attempt. Even after upload, read, update, and delete operations are evaluated against the rules.

Mini Project

Write and test Storage Rules for a user file system: user-scoped paths, image-only uploads (JPEG, PNG), max 10MB, with a public shared/ folder where files expire after 7 days.

What's Next

Cloud Functions for Firebase — run backend code in response to events and HTTP requests.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro