Sourcemaps enabled in production by default (security issue)

Open Beginner friendly
#588 4 comments 2 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
68/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Quiet
Tech stack
ruby, typescript, vite

Research direction

Start in vite-plugin-ruby/src/index.ts around the build configuration near line 155, and compare the sourcemap behavior in the production and development reproduction commands from the issue. Done means production builds have no sourcemap files or sourceMappingURL comments by default, while development builds produce sourcemaps, without preventing explicit user overrides.

Written by the indexing model from the issue text.

Description

bug: pending triage
  • 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:
metarina@0.1.0
├─┬ vite-plugin-ruby@5.1.1
│ └── vite@5.4.21 deduped
└── vite@5.4.21

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.

Dominant language
Ruby
Stars
1.6k
Forks
151
Avg merge
4d 7h
Merged PRs (30d)
5

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from ElMassimo/vite_ruby

All issues in ElMassimo/vite_ruby

Similar issues

More Ruby issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.