mcpField
S
security-vite

security-vite

github.com/igorwarzochaSecurity122105 installsUpdated 38w ago
Repository

About security-vite

A security-audit skill for Vite application developers, covering environment variables, build configuration, and common SPA vulnerabilities. It includes targeted checks and a hardening checklist.

Key features

  1. 01Check VITE_ environment variable exposure
  2. 02Review build-time secret injection
  3. 03Check development server network exposure
  4. 04Identify SPA client-side authentication risks
  5. 05Scan production bundles for secrets and source maps
  6. 06Provide audit commands and a hardening checklist

Use cases

  1. 01Audit sensitive variables in .env files
  2. 02Check vite.config.ts for injected secrets
  3. 03Assess unintended development server exposure

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/igorwarzocha/opencode-workflows --skill security-vite

After installing, type/security-vitein Claude Code to confirm it loaded.

Bundled filesscripts/scan.sh

Details

From the project README

Security audit patterns for Vite applications focusing on environment variable exposure, build-time secrets, and SPA-specific vulnerabilities.

Environment Variable Exposure

The VITE_ Footgun
VITE_*    → Bundled into client JavaScript → Visible to everyone
No prefix → Only available in vite.config.ts → Safe for secrets

Audit steps:

  1. grep -r "VITE_" . -g "*.env*"
  2. Check import.meta.env.VITE_* usage in source
  3. Common mistakes:
    • VITE_API_SECRET (SHOULD be server-only)
    • VITE_DATABASE_URL (MUST NOT use)
    • VITE_STRIPE_SECRET_KEY (only publishable keys)
Env Files Priority

Vite loads in this order (later overrides earlier):

.env                # Always loaded
.env.local          # Always loaded, gitignored
.env.[mode]         # e.g., .env.production
.env.[mode].local   # e.g., .env.production.local, gitignored

Check: Are .env.local and .env.*.local in .gitignore?

envPrefix Overrides

If envPrefix is configured, Vite exposes any variables with those prefixes. Treat envPrefix as a security-sensitive setting.

Build-Time vs Runtime

Dangerous: Secrets in vite.config.ts
// ❌ Secret in config (ends up in bundle)
export default defineConfig({
  define: {
    'process.env.API_KEY': JSON.stringify(process.env.API_KEY),
  },
});

// The above makes API_KEY available in client code!
Safe Pattern
// Only use VITE_ prefix for truly public values
export default defineConfig({
  define: {
    '__APP_VERSION__': JSON.stringify(process.env.npm_package_version),
  },
});

// Keep secrets on server (use a backend API)

Dev Server Security

Open to Network
// ❌ Exposes dev server to network
export default defineConfig({
  server: {
    host: '0.0.0.0',  // or host: true
  },
});

This is dangerous on shared networks. Check if intentional.

Proxy Misconfiguration
export default defineConfig({
  server: {
    proxy: {
      '/api': {
        target: 'http://localhost:3000',
        changeOrigin: true,
        // ❌ Missing secure options for production-like setup
      },
    },
  },
});

SPA Security Issues

Client-Side Auth Only
// ❌ "Protection" only in React Router
const ProtectedRoute = ({ children }) => {
  const { user } = useAuth();
  if (!user) return <Navigate to="/login" />;
  return children;
};

// API calls still need server-side auth!
// This is UI convenience, not security.
Secrets in Bundle
# Check the built bundle for secrets
rg -a "(sk_live|sk_test|AKIA|api[_-]?key)" dist/
Source Maps in Production
// Check vite.config.ts
export default defineConfig({
  build: {
    sourcemap: true,  // ❌ Exposes source code in production
  },
});

<severity_table>

Common Vulnerabilities

IssueWhere to LookSeverity
VITE_* secrets.env*, source filesCRITICAL
Secrets in definevite.config.tsCRITICAL
Source maps in prodvite.config.tsMEDIUM
Dev server exposedvite.config.ts server.hostMEDIUM
Client-only authRoute guards without API authHIGH
API keys in bundledist/ directoryCRITICAL

</severity_table>

Quick Audit Commands

# Find VITE_ secrets
grep -r "VITE_" . -g "*.env*"

# Find import.meta.env usage
rg 'import\.meta\.env' . -g "*.ts" -g "*.tsx" -g "*.vue"

# Check define in config
rg 'define:' vite.config.*

# Scan built bundle for secrets
rg -a "(sk_live|AKIA|ghp_|api[_-]?key['\"]?\s*[:=])" dist/

# Check for source maps
fd '\.map$' dist/

Hardening Checklist

  • No secrets in VITE_* variables
  • .env.local and .env.*.local in .gitignore
  • sourcemap: false in production build
  • server.host is not 0.0.0.0 or true (unless intentional)
  • All sensitive API calls go through a backend (not direct from browser)
  • No secrets in vite.config.ts define block

Comments

Markdown supported