RepoPilot

carrierwaveuploader/carrierwave

Classier solution for file uploads for Rails, Sinatra and other Ruby web frameworks

Mixed

Missing license — unclear to depend on

ConcernsDependency

no license — legally unclear

ConcernsFork & modify

no license — can't legally use code

HealthyLearn from

Documented and popular — useful reference codebase to read through.

ConcernsDeploy as-is

no license — can't legally use code

  • Concentrated ownership — top contributor handles 59% of recent commits
  • No license — legally unclear to depend on
  • Last commit today
  • 19 active contributors
  • CI configured
  • Tests present

What would improve this?

  • Use as dependency ConcernsMixed if: publish a permissive license (MIT, Apache-2.0, etc.)
  • Fork & modify ConcernsMixed if: add a LICENSE file
  • Deploy as-is ConcernsMixed if: add a LICENSE file

Computed from maintenance signals — commit recency, contributor breadth, bus factor, license, CI, tests

Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.

Embed the "Great to learn from" badge

Paste into your README — live-updates from the latest cached analysis.

RepoPilot: Great to learn from
[![RepoPilot: Great to learn from](https://repopilot.app/api/badge/carrierwaveuploader/carrierwave?axis=learn)](https://repopilot.app/r/carrierwaveuploader/carrierwave)

Paste at the top of your README.md — renders inline like a shields.io badge.

Preview social card

This card auto-renders when someone shares https://repopilot.app/r/carrierwaveuploader/carrierwave on X, Slack, or LinkedIn.

Ask AI about carrierwaveuploader/carrierwave

Grounded in the actual source code. Pick a starter question or write your own.

Or write your own question →

Onboarding doc

Onboarding: carrierwaveuploader/carrierwave

Generated by RepoPilot · 2026-06-24 · Source

🎯Verdict

WAIT — Missing license — unclear to depend on

  • Last commit today
  • 19 active contributors
  • CI configured
  • Tests present
  • ⚠ Concentrated ownership — top contributor handles 59% of recent commits
  • ⚠ No license — legally unclear to depend on

<sub>Computed from maintenance signals — commit recency, contributor breadth, bus factor, license, CI, tests</sub>

TL;DR

CarrierWave is a Ruby gem that provides a flexible file upload abstraction layer for Rails, Sinatra, and other Ruby web frameworks. It handles storing files (locally or to cloud services), processing/converting files (via ImageMagick), generating multiple versions of uploads, and caching during form submission—without tying your application to a specific storage backend. Single-gem monolith structure: lib/carrierwave/ contains core uploader logic, storage backends, downloader utilities, and locale files; features/ holds Cucumber integration tests with step definitions for Rails, DataMapper, caching, and file operations; gemfiles/ lists Rails version compatibility matrices for CI testing.

👥Who it's for

Rails and Ruby web developers who need to add file upload functionality to their applications with support for image processing, cloud storage integrations, and form-based workflows. Both application developers using the gem and gem maintainers contribute to this project.

🌱Maturity & risk

Highly mature and production-ready. The project is actively maintained with CI/CD configured via GitHub Actions (see .github/workflows/test.yml), supports Rails 6.0–8.0+ across multiple gemfiles, and shows consistent recent activity. Version 3.0 is stable with well-documented breaking changes for extension handling in file conversions.

Low risk overall. The gem has a single primary maintainer model typical of long-standing open-source projects, but active CI and comprehensive feature tests (Cucumber suite in features/) mitigate this. Breaking changes are documented explicitly (see CHANGELOG.md and upgrade notes in README). No evident dependency explosion—the gem focuses on core upload logic with optional storage/processor integrations.

Active areas of work

Active maintenance of version 3.x with focus on Rails 8.0 compatibility (gemfiles/rails-8-0.gemfile present). Recent work includes file extension handling improvements (v3.0 change mentioned in README), downloader enhancements (remote_file.rb), and ongoing test coverage. GitHub Actions CI is configured and running.

🚀Get running

git clone https://github.com/carrierwaveuploader/carrierwave.git
cd carrierwave
bundle install
bundle exec rake test
# Or run Cucumber features: bundle exec cucumber

Daily commands:

# Run unit tests
bundle exec rake test

# Run Cucumber feature tests
bundle exec cucumber

# Run against specific Rails version
BUNDLE_GEMFILE=gemfiles/rails-7-2.gemfile bundle exec rake test

🗺️Map of the codebase

  • lib/carrierwave.rb — Main entry point that initializes and loads all CarrierWave modules; every contributor must understand this to know what gets loaded.
  • lib/carrierwave/uploader.rb — Core Uploader class that serves as the abstract base for all upload behavior; defines the primary API every developer extends.
  • lib/carrierwave/mount.rb — Integration layer that mounts uploaders onto ORM models; critical for understanding how uploaders attach to Rails models.
  • lib/carrierwave/storage/abstract.rb — Abstract storage interface defining the contract all storage backends must implement (file, fog, etc.).
  • lib/carrierwave/mounter.rb — Handles the mechanics of mounting an uploader to a model instance and managing state; essential for lifecycle understanding.
  • lib/carrierwave/uploader/versions.rb — Implements version management (e.g., thumbnails); a major feature area frequently customized by users.
  • lib/carrierwave/orm/activerecord.rb — Rails ActiveRecord integration layer; must read to understand model-level uploader mounting.

🛠️How to make changes

Add a Custom Uploader Class

  1. Generate a new uploader using the Rails generator (lib/generators/uploader_generator.rb (run rails generate uploader MyField))
  2. Edit the generated uploader to configure storage, versions, and validations (app/uploaders/my_field_uploader.rb (customize lib/carrierwave/uploader/configuration.rb DSL))
  3. Add processing directives for image manipulation (app/uploaders/my_field_uploader.rb (use lib/carrierwave/processing/mini_magick.rb methods))
  4. Mount the uploader on your model using mount_uploader (app/models/my_model.rb (uses lib/carrierwave/mount.rb))

Implement a Custom Storage Backend

  1. Create a new class inheriting from the abstract storage interface (lib/carrierwave/storage/abstract.rb (extend CarrierWave::Storage::Abstract))
  2. Implement required methods: store!, retrieve!, delete!, and url (your_custom_storage.rb (follow contract defined in lib/carrierwave/storage/abstract.rb))
  3. Register the storage in an initializer (config/initializers/carrierwave.rb (configure via lib/carrierwave/uploader/configuration.rb))
  4. Reference the storage in your uploader class (app/uploaders/my_uploader.rb (set storage with storage :my_custom_storage))

Add Custom File Validation

  1. Create custom validation logic in your uploader (app/uploaders/my_uploader.rb (extend validation from lib/carrierwave/uploader/*.rb))
  2. Use built-in validators or add custom validate methods (lib/carrierwave/uploader/extension_allowlist.rb, content_type_allowlist.rb, file_size.rb as templates)
  3. Integrate with ActiveModel validations for error messages (lib/carrierwave/validations/active_model.rb (hooks into Rails validation system))

Create Image Versions (Thumbnails, Resizes)

  1. Define versions in your uploader class (app/uploaders/my_uploader.rb (use lib/carrierwave/uploader/versions.rb DSL: version :thumb))
  2. Apply image processing to each version (app/uploaders/my_uploader.rb (use lib/carrierwave/processing/mini_magick.rb methods like resize_to_fit))
  3. Access versions in views via version accessor methods (your_template.erb (call @model.uploader_field.thumb.url))

🔧Why these technologies

  • Ruby on Rails ActiveRecord ORM integration — Rails is the dominant Ruby web framework; tight ORM integration (lib/carrierwave/orm/activerecord.rb) makes uploader mounting seamless in models.
  • Rack compatibility abstraction — Multiple Ruby web frameworks (Rails, Sinatra) use Rack; building on Rack makes CarrierWave framework-agnostic.
  • Fog gem for cloud storage — Fog abstracts multiple cloud providers (S3, GCS, Azure); lib/carrierwave/storage/fog.rb leverages this to support many backends with one implementation.
  • MiniMagick / RMagick / VIPS image libraries — Multiple image processing libraries available; CarrierWave supports all three (lib/carrierwave/processing/*.rb) so users choose based on dependencies and performance needs.

⚖️Trade-offs already made

  • Uploader as abstract class vs. composition pattern
    • Why: Inheritance is simpler for users (mount_uploader DSL in lib/carrierwave/mount.rb
    • Consequence: undefined

🪤Traps & gotchas

CarrierWave 3.0 changed file extension handling during format conversion—cached files from 2.x are incompatible with 3.x and vice versa; blue-green deployments must account for this (use force_extension false to preserve 2.x behavior). Version-based file extension changes require calling #recreate_versions! on existing records. Cucumber tests require ActiveRecord/DataMapper setup and database fixtures (see features/support/); not all ORMs are auto-detected. Image processing requires ImageMagick installed on the system, not included by the gem.

🏗️Architecture

💡Concepts to learn

  • Storage Backend Abstraction — CarrierWave decouples upload logic from storage implementation (file system vs. S3 vs. GCS); understanding how storage backends swap is essential to the gem's flexibility and extension model
  • File Versioning & Processors — CarrierWave can generate multiple derivatives of an uploaded file (e.g., thumb, medium, large from a single image); this requires understanding the processor pipeline and version configuration syntax
  • Form Caching & Persistence — CarrierWave caches uploaded files temporarily during form resubmission failures; understanding the cache lifecycle is critical for handling form errors without losing user uploads
  • ORM Integration via Mixins — CarrierWave extends Rails models via mount_uploader, which dynamically adds accessors and lifecycle hooks; understanding the mixin pattern is needed to extend or debug model integration
  • Rack Multipart File Objects — CarrierWave consumes Rack's multipart upload API (UploadedFile objects); understanding the Rack multipart contract is essential for handling file input from web forms and APIs
  • Remote File Downloading — CarrierWave can fetch and cache remote files (e.g., from URLs in form inputs); the downloader module handles HTTP requests, redirects, and streaming for large files
  • shrinerb/shrine — Direct modern alternative to CarrierWave; newer, more modular file upload architecture with same Rails/Rack ecosystem support
  • thoughtbot/paperclip — Legacy predecessor to CarrierWave; CarrierWave includes Paperclip compatibility layer (lib/carrierwave/compatibility/paperclip.rb) for migration paths
  • rails/rails — Core Rails dependency; CarrierWave integrates via ActiveRecord mount_uploader and form file handling; Rails version compatibility tested across gemfiles/
  • ruby-vips/ruby-vips — Alternative to ImageMagick for image processing in CarrierWave uploaders; modern replacement for processor chains

🪄PR ideas

To work on one of these in Claude Code or Cursor, paste: Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.

Add comprehensive test coverage for lib/carrierwave/downloader/remote_file.rb

The downloader module exists but there are no dedicated unit tests in the test suite for remote file downloading functionality. Given that remote file handling is critical for security and reliability, this needs explicit test coverage for edge cases like timeout handling, invalid URLs, redirects, and error scenarios.

  • [ ] Create spec/lib/carrierwave/downloader/remote_file_spec.rb with tests for valid/invalid URLs
  • [ ] Add tests for HTTP error handling (4xx, 5xx responses)
  • [ ] Add tests for redirect following and redirect limit boundaries
  • [ ] Add tests for timeout scenarios and network failures
  • [ ] Verify integration with lib/carrierwave/sanitized_file.rb in tests

Add GitHub Action workflow for testing against multiple Ruby versions

The .github/workflows/test.yml exists but the current setup likely targets a single Ruby version. CarrierWave supports a wide range of Ruby versions and Rails versions (6.0-8.0 shown in gemfiles/). A matrix-based workflow would catch version-specific incompatibilities early.

  • [ ] Extend .github/workflows/test.yml to use strategy.matrix for Ruby versions (3.0, 3.1, 3.2, 3.3)
  • [ ] Add matrix testing across the existing gemfiles (rails-6-0 through rails-8-0)
  • [ ] Configure the matrix to fail-fast on critical versions but allow failures on edge cases like rails-main.gemfile
  • [ ] Document the Ruby/Rails compatibility matrix in CONTRIBUTING.md

Add integration tests for lib/carrierwave/storage/fog.rb with multiple backends

The fog storage adapter is a major feature but lacks dedicated integration tests. The features/ directory has file_storage.feature but no equivalent for cloud storage (S3, Azure, GCS). This is critical for production users relying on fog backends.

  • [ ] Create features/fog_storage.feature with S3, Azure, and GCS backend scenarios
  • [ ] Add features/step_definitions/fog_steps.rb with setup for fog mocking/stubbing
  • [ ] Test key scenarios: upload, retrieve, delete, public/private URLs for each backend
  • [ ] Document fog configuration requirements in features/support/env.rb
  • [ ] Verify compatibility with lib/carrierwave/downloader/remote_file.rb for fog-backed downloads

🌿Good first issues

  • Add missing RSpec test coverage for lib/carrierwave/downloader/remote_file.rb and lib/carrierwave/downloader/base.rb—currently only Cucumber features exist; write unit tests for URL validation, timeout handling, and error cases
  • Expand Cucumber feature coverage for storage backends—add features/cloud_storage.feature with step definitions for S3 and GCS integrations to document expected cloud storage behavior
  • Document processor plugin architecture—lib/carrierwave has image processing hooks but no detailed Cucumber features showing how to write custom processors (e.g., video transcoding, PDF optimization)

Top contributors

Click to expand

📝Recent commits

Click to expand
  • fee4fb7 — Bump actions/checkout from 5 to 6 (#2797) (dependabot[bot])
  • a56bb0e — Fix broken CI (#2816) (y-yagi)
  • a015f02 — Update build matrix (mshibuya)
  • b53a725 — Bump actions/checkout from 4 to 5 (#2790) (dependabot[bot])
  • 2d14664 — Add content_type_allowlist example to uploader template (#2785) (coloradosazulyanaranjados)
  • 4b797ef — Cope with the change in MiniMagick 5.3 (mshibuya)
  • a51a970 — Provide a 'Changelog' link on rubygems.org/gems/carrierwave (#2774) (mark-young-atg)
  • e76e860 — ci: update Ubuntu runner to 24.04 LTS (mshibuya)
  • 8e5db8c — Version 3.1.2 (mshibuya)
  • 7b2ce50 — Fix failing to remove existing files on updating by #remove_#{column}=, ##{column}_cache=, and `#remote_#{column}_ur (mshibuya)

🔒Security observations

  • High · Potential Path Traversal in File Upload Handling — lib/carrierwave/sanitized_file.rb, lib/carrierwave/storage/. CarrierWave handles file uploads and storage. The presence of files like sanitized_file.rb and storage modules suggests file path manipulation. Without reviewing the actual implementation, path traversal vulnerabilities are common in upload handlers when user-supplied filenames aren't properly sanitized. Fix: Ensure all user-supplied filenames are validated and sanitized. Use allowlists for valid characters. Implement strict path normalization and prevent directory traversal sequences (../, ., etc.). Review sanitized_file.rb for complete filename validation logic.
  • High · Potential XXE/XML Injection in Image Processing — lib/carrierwave/processing/mini_magick.rb, lib/carrierwave/processing/rmagick.rb, lib/carrierwave/processing/vips.rb. The presence of image processing modules (rmagick.rb, mini_magick.rb, vips.rb) that handle external files could be vulnerable to XML External Entity (XXE) attacks if processing untrusted SVG or XML-based image formats. Fix: Disable XXE processing in image libraries. For ImageMagick/MiniMagick, use delegates policy restrictions. For VIPS, ensure SVG processing is disabled for untrusted inputs. Validate file types before processing.
  • High · Potential Command Injection in Image Processing — lib/carrierwave/processing/mini_magick.rb, lib/carrierwave/processing/rmagick.rb, lib/carrierwave/processing/vips.rb. Image processing libraries (ImageMagick, VIPS) can execute shell commands. If user input is passed unsanitized to these processors, command injection is possible. Fix: Never pass unsanitized user input directly to image processing commands. Use parameterized APIs instead of shell execution. Escape all user-controlled parameters. Implement strict input validation on image dimensions and processing parameters.
  • Medium · Missing Content-Type Validation — lib/carrierwave/uploader/content_type_allowlist.rb, lib/carrierwave/uploader/content_type_denylist.rb. Files like content_type_allowlist.rb and content_type_denylist.rb suggest content-type validation exists, but reliance on MIME types alone is insufficient as they can be spoofed by users. Fix: Implement magic number/file signature validation in addition to MIME type checks. Use libraries like ruby-vips or file command to verify actual file type. Never trust client-supplied Content-Type headers.
  • Medium · Potential Information Disclosure in Error Messages — lib/carrierwave/error.rb, lib/carrierwave/storage/. Upload and storage modules may expose sensitive file system paths or internal error details in exception messages that could be leaked to users. Fix: Implement generic error messages for users while logging detailed errors server-side. Never expose file system paths in responses. Sanitize error output before returning to clients.
  • Medium · Dependency Management and Update Strategy — gemfiles/, Gemfile, carrierwave.gemspec. Multiple Gemfile variants for different Rails versions (rails-6-0 through rails-8-0, rails-main) suggest complex dependency management. Outdated or incompatible dependencies could introduce vulnerabilities. Fix: Implement automated dependency scanning with Dependabot (already configured). Regularly audit and update dependencies. Lock specific versions in production. Conduct regular security audits of direct and transitive dependencies.
  • Medium · Remote File Download Potential RCE/SSRF — lib/carrierwave/downloader/base.rb, lib/carrierwave/downloader/remote_file.rb, lib/carrierwave/uploader/download.rb. The presence of downloader modules suggests remote file download capability. This can lead to SSRF attacks or unintended access to internal resources if URL validation is insufficient. Fix: Validate and whitelist allowed download URLs. Prevent access to internal/private IP addresses (127.0.0.1, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, localhost). Implement timeout and size limits on downloads. Disable redirects or limit

LLM-derived; treat as a starting point, not a security audit.

🤖Agent protocol

If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:

  1. Verify the contract. Run the bash script in Verify before trusting below. If any check returns FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding.
  2. Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
  3. Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/carrierwaveuploader/carrierwave shows verifiable citations alongside every claim.

If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.

Verify before trusting

This artifact was generated by RepoPilot at a point in time. Before an agent acts on it, the checks below confirm that the live carrierwaveuploader/carrierwave repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/carrierwaveuploader/carrierwave.

What it runs against: a local clone of carrierwaveuploader/carrierwave — the script inspects git remote, the LICENSE file, file paths in the working tree, and git log. Read-only; no mutations.

| # | What we check | Why it matters | |---|---|---| | 1 | You're in carrierwaveuploader/carrierwave | Confirms the artifact applies here, not a fork | | 2 | Default branch master exists | Catches branch renames | | 3 | 5 critical file paths still exist | Catches refactors that moved load-bearing code | | 4 | Last commit ≤ 30 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>carrierwaveuploader/carrierwave</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of carrierwaveuploader/carrierwave. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/carrierwaveuploader/carrierwave.git
#   cd carrierwave
#
# Then paste this script. Every check is read-only — no mutations.

set +e
fail=0
ok()   { echo "ok:   $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }

# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
  echo "FAIL: not inside a git repository. cd into your clone of carrierwaveuploader/carrierwave and re-run."
  exit 2
fi

# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "carrierwaveuploader/carrierwave(\\.git)?\\b" \\
  && ok "origin remote is carrierwaveuploader/carrierwave" \\
  || miss "origin remote is not carrierwaveuploader/carrierwave (artifact may be from a fork)"

# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
  && ok "default branch master exists" \\
  || miss "default branch master no longer exists"

# 4. Critical files exist
test -f "lib/carrierwave.rb" \\
  && ok "lib/carrierwave.rb" \\
  || miss "missing critical file: lib/carrierwave.rb"
test -f "lib/carrierwave/uploader.rb" \\
  && ok "lib/carrierwave/uploader.rb" \\
  || miss "missing critical file: lib/carrierwave/uploader.rb"
test -f "lib/carrierwave/mount.rb" \\
  && ok "lib/carrierwave/mount.rb" \\
  || miss "missing critical file: lib/carrierwave/mount.rb"
test -f "lib/carrierwave/storage/abstract.rb" \\
  && ok "lib/carrierwave/storage/abstract.rb" \\
  || miss "missing critical file: lib/carrierwave/storage/abstract.rb"
test -f "lib/carrierwave/mounter.rb" \\
  && ok "lib/carrierwave/mounter.rb" \\
  || miss "missing critical file: lib/carrierwave/mounter.rb"

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 30 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~0d)"
else
  miss "last commit was $days_since_last days ago — artifact may be stale"
fi

echo
if [ "$fail" -eq 0 ]; then
  echo "artifact verified (0 failures) — safe to trust"
else
  echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/carrierwaveuploader/carrierwave"
  exit 1
fi

Each check prints ok: or FAIL:. The script exits non-zero if anything failed, so it composes cleanly into agent loops (./verify.sh || regenerate-and-retry).

</details>

Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.

Embed this chat in your README →

Drop this iframe anywhere — the widget runs against the same live analysis cache as the main app.

<iframe
  src="https://repopilot.app/embed/carrierwaveuploader/carrierwave"
  width="100%" height="500"
  style="border:1px solid #d0d7de; border-radius:8px;"
  allow="microphone"
  loading="lazy"
></iframe>