ElMassimo / ElMassimo/vite_ruby
Sourcemaps enabled in production by default (security issue)
- Dominant language
- Ruby
- Stars
- 1.6k
- Forks
- 149
- Avg merge
- 5h 13m
- Merged PRs (30d)
- 2
Description
[troubleshooting section]: https://vite-ruby.netlify.app/guide/troubleshooting.html
- [x] I have tried upgrading by running `bundle update vite_ruby`.
- [x] 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`:
```typescript
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:
```typescript
// 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
}
})
```
3. Build for production:
```bash
rm -rf public/vite
RAILS_ENV=production NODE_ENV=production bin/vite build
```
4. Check for sourcemap exposure:
```bash
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
5. Check development build:
```bash
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):
```typescript
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:
```typescript
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`:
```typescript
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
- **Vite docs**: https://vitejs.dev/config/build-options.html#build-sourcemap (default: `false`)
- **vite-plugin-ruby source**: https://github.com/ElMassimo/vite_ruby/blob/main/vite-plugin-ruby/src/index.ts#L155
---
Happy to submit a PR if you'd like! This appears to be an unintentional logic inversion.
Contributor guide
Assessment
This issue has not been assessed yet.