Skip to content

Sourcemaps enabled in production by default (security issue) #588

@lentrup

Description

@lentrup
  • I have tried upgrading by running bundle update vite_ruby.
  • I have read the troubleshooting section before opening an issue.

Description

vite-plugin-ruby has a backwards sourcemap default that enables sourcemaps in production and disables them in development. This is a security vulnerability that exposes application source code in production builds.

The plugin sets build.sourcemap: !isLocal in src/index.ts (~line 155), which results in:

  • Production mode (!isLocal = true): ✗ Sourcemaps ENABLED - exposes source code
  • Development mode (!isLocal = false): ✗ Sourcemaps DISABLED - breaks debugging
  • Test mode (!isLocal = false): ✗ Sourcemaps DISABLED

This is the opposite of Vite's secure default (build.sourcemap: false).

Security Impact:

  • .js.map and .css.map files publicly accessible in production
  • sourceMappingURL comments present in minified bundles
  • Complete unminified source code visible in browser DevTools
  • Business logic, API endpoints, and implementation details exposed

Root Cause:

In vite-plugin-ruby/src/index.ts:

const isLocal = config.mode === "development" || config.mode === "test";
const build = {
  emptyOutDir: ...,
  sourcemap: !isLocal,  // ← BUG: true in production, false in dev!
  ...userConfig.build,
  // ...
}

The logic appears inverted - !isLocal enables sourcemaps when NOT in local development.

Reproduction

Minimal reproduction:

  1. Create a fresh Rails app with vite_ruby (default config)
  2. Use default vite.config.ts with NO explicit build.sourcemap setting:
// vite.config.ts - using plugin defaults
import { defineConfig } from 'vite'
import RubyPlugin from 'vite-plugin-ruby'

export default defineConfig({
  plugins: [RubyPlugin()],
  build: {
    // NO sourcemap config - inherits plugin default
  }
})
  1. Build for production:
rm -rf public/vite
RAILS_ENV=production NODE_ENV=production bin/vite build
  1. Check for sourcemap exposure:
find public/vite/assets -name "*.js.map"
grep -r "sourceMappingURL" public/vite/assets/*.js

Expected: No sourcemap files, no sourceMappingURL comments
Actual: Sourcemap files present, comments pointing to them

  1. Check development build:
rm -rf public/vite-dev
RAILS_ENV=development NODE_ENV=development bin/vite build
find public/vite-dev/assets -name "*.js.map"

Expected: Sourcemap files present for debugging
Actual: No sourcemap files (debugging broken)

Vite Ruby Info
bin/vite present?: true
vite_ruby: 3.9.1
vite_rails: 3.0.19
rails: 7.2.2.1
ruby: ruby 3.3.7 (2025-01-15 revision be31f993d7) [arm64-darwin24]
node: v20.12.2
yarn: 4.1.1

installed packages:
[email protected]
├─┬ [email protected]
│ └── [email protected] deduped
└── [email protected]

Proposed Fix

Option 1: Remove the default (recommended)

Let Vite's default apply (sourcemap: false):

const isLocal = config.mode === "development" || config.mode === "test";
const build = {
  emptyOutDir: ...,
  // REMOVE: sourcemap: !isLocal,
  ...userConfig.build,  // User can still override
  // ...
}

Option 2: Invert the logic

Enable sourcemaps only in development:

const isLocal = config.mode === "development" || config.mode === "test";
const build = {
  emptyOutDir: ...,
  sourcemap: config.mode === 'development',  // Only in dev
  ...userConfig.build,
  // ...
}

Current Workaround

Users must explicitly override in vite.config.ts:

export default defineConfig(({ mode }) => ({
  build: {
    sourcemap: mode === 'development'  // Override plugin default
  }
}))

Impact

This affects all vite_ruby users who don't explicitly set build.sourcemap in their config. Production applications unknowingly expose their complete source code.

References


Happy to submit a PR if you'd like! This appears to be an unintentional logic inversion.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bug: pending triageSomething doesn't seem to be working, but hasn't been verified

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions