ElMassimo / ElMassimo/vite_ruby

Sourcemaps enabled in production by default (security issue)

Open
#588 4 comments 2 reactions 0 assignees View on GitHub
bug: pending triage
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.