Skip to content

Vulcan v2.3.1

Release Date: February 2026

This release includes DISA process documentation, SRG ID display in satisfaction relationships, DRY refactors (UnifiedRuleForm, satisfaction text), export system improvements, authorization safety net, and infrastructure hardening.

Upgrades

  • Ruby 3.4.9 - Upgraded from 3.3.9 (latest patch release with security fixes)
  • Puma 7.2.0 - Upgraded from 5.6.9 for Heroku Router 2.0 compatibility and performance
  • parallel_tests - Added for faster local test execution
  • Vitest CI integration - Frontend tests (1114 tests) now run in GitHub Actions
  • Rails 8.0.4 - Patch update with security and compatibility fixes
  • axios 1.13 - Dependency update
  • sass 1.97 - Dependency update

Security

  • Updated rexml and rack gems (CVE-2025-58767, GHSA-625h)
  • Resolved all ESLint errors and warnings (20 errors, 6 warnings to 0)
  • Configurable SSL for Docker deployments (#700, #702)
  • YAML.safe_load replaces YAML.load_file in SearchAbbreviationService (deserialization safety)
  • Database deployment safety: removed dangerous DISABLE_DATABASE_ENVIRONMENT_CHECK from Docker entrypoint; flag now only used in Heroku review app postdeploy where it's needed for db:schema:load
  • XXE prevention: removed NOENT flag from XML parser, added NONET to block external entity expansion and network DTD fetching
  • Upload validation: file size limits (50 MB XML, 100 MB ZIP, 50 MB spreadsheet) and content-type checks on all upload endpoints
  • Rate limiting via rack-attack: login throttling (5/min/IP, 5/min/email), upload throttling (10/min/IP)
  • Configurable input length limits on all text fields across 9 models (18 VULCAN_LIMIT_* env vars)
  • Content Security Policy headers (script-src, style-src, frame-src, etc.)
  • HappyMapper NONET patch prevents SSRF via external DTD URIs in XCCDF parsing
  • Rack-attack flaky test isolation (fresh cache per test, unique IPs/emails)
  • Authorization scoping: based_on_same_srg now scoped to user-accessible projects and released STIGs only
  • Nil guard on compare action for invalid component IDs (prevents unhandled exceptions)
  • params[:sections] type safety: Array coercion in rules and reviews controllers
  • project_visibility enum allowlist validation to reject unexpected values
  • HappyMapper XXE patch extended to handle IO and StringIO inputs, not just file paths
  • JSON::ParserError rescue on component_filter param (malformed JSON no longer raises 500)
  • Password generation characters shuffled (eliminates predictable character-class ordering)
  • Locked users query capped at 100 results (prevents unbounded admin queries)

Features

Security and Access Control

  • Account lockout (Devise :lockable) with admin unlock UI, AC-07 compliance
  • Configurable concurrent session limits (AC-10) with session history tracking via devise-security fork
  • PBKDF2-SHA512 password hashing (FIPS 140-2 compliant) with transparent bcrypt migration
  • Devise hardening: paranoid mode, DELETE logout (CSRF protection), cookie security (secure + httponly + SameSite), email/password change notifications, 2-hour password reset window
  • Classification banner and consent modal
  • Per-section rule field locking (lock individual rule sections independently)
  • Password complexity policy (configurable DoD 2222 defaults)
  • Last-admin protection (prevents demoting/deleting only admin)
  • Admin user management (create, edit, delete, lock/unlock accounts)
  • AC-8 server-side consent tracking with configurable TTL (VULCAN_CONSENT_TTL)
  • Consent modal renders before login (AC-8 compliant: acknowledgement before authentication)

API and Version Infrastructure

  • GET /api/version endpoint (public, returns version, Rails version, Ruby version, environment)
  • lib/vulcan/version.rb as single source of truth for application version
  • Health check endpoint includes version in response
  • Navbar receives version from server rather than reading from package.json
  • rake version:sync keeps VERSION file in sync with package.json

Infrastructure

  • Unified multi-stage Dockerfile with CLI and improved .dockerignore
  • Admin bootstrap with first-user-admin and env var support
  • Health check endpoints for Kubernetes and Docker deployments
  • DB_SUFFIX environment variable for worktree database isolation
  • Database deployment safety: db:prepare (Docker), db:migrate (Heroku prod/staging), db:schema:load (review apps) with 13 regression tests
  • CSP dynamically whitelists OIDC provider domain and api.github.com based on configuration
  • Auto parallel:prepare runs after db:migrate and db:reset (no manual step needed)
  • rake spec:parallel and bin/parallel_rspec wrapper with 8-processor cap
  • .foreman sets port: 3000 for consistent Okta/OIDC redirect URI
  • Tag-triggered releases using git-cliff to generate changelogs in Keep a Changelog format
  • release-please replaced with simpler tag-based release workflow
  • Global search infrastructure with pg_search gem
  • Query transformation service with abbreviation expansion
  • Search results across projects, components, rules, SRGs, and STIGs

UI Improvements

  • Command bars for view and edit pages
  • Redesigned MembersModal with tabbed interface
  • Redesigned RuleActionsToolbar with two-row layout
  • Severity filter buttons as connected button group with CAT I/II/III labels
  • UnifiedRuleForm replacing Basic and Advanced forms
  • CSV export with configurable column picker
  • NYD (Not Yet Determined) tooltip guidance on disabled fields
  • NYD section locking disabled (locking is meaningless before a determination is made)

Data Handling

  • Postel's Law applied to satisfaction parsing and session timeout config
  • CSV header aliases for import compatibility
  • SRG auto-detect from spreadsheet import
  • VULCAN_SEED_DEMO_DATA guard prevents demo seeding in production

Fixes

  • Fix nested attributes not saving in rules controller (#692)
  • Fix Also Satisfies resetting parent rule status
  • Fix Vue reactivity for satisfied_by relationship field visibility
  • Fix SRG search result links to use /srgs/ route
  • Database config with DATABASE_URL support
  • Consolidate Devise modules into single call in User model
  • RuleList severity counts moved to computed property (now reactive to prop changes)
  • ComponentCard: added resetDelete() method for error recovery after failed delete
  • MembersModal: scoped element IDs to prevent DOM collisions, replaced form.submit with axios for all operations
  • App.vue signOut: replaced form.submit with axios using FormMixin CSRF token handling
  • ProjectComponent: replaced toRef(plainObject) with computed() for correct Vue 2.7 reactivity
  • RuleList initialSelectedRule: marked required: false and added watcher for prop sync
  • UpdateFromSpreadsheetModal: memoized diffWords LCS computation (performance fix for large diffs)
  • GlobalSearch: encodeURIComponent applied to URL params, removed dead code paths
  • ConsentModal: migrated to FormMixin for consistent CSRF handling
  • Idempotent seeds: fixed missing Component titles that caused re-seed failures
  • Remove explicit secure: cookie flag — Rails SSL middleware handles it automatically (prevented dev/test breakage)
  • Replace thread-unsafe @@components_to_export class variable with session storage (fixes Puma race condition)
  • Fix config ENV var parsing, connection pool mismatch, and dead configuration keys
  • Remove redundant ENV fallbacks and UserMailer default-from override
  • Fix consent modal crash on first render before consent state is loaded

Infrastructure

  • Vitest testing infrastructure for Vue 2 components
  • Centralized terminology constants (BENCHMARK_TERM, EXPORT_FORMATS)
  • Comprehensive import/export and deployment documentation
  • Parallel test execution in CI with parallel_tests gem
  • frozen_string_literal: true added to all 65 migration files
  • Config verification specs and orphaned settings table cleanup
  • Security regression specs for authorization, input validation, and XXE fixes
  • Deployment blocker regression specs (13 tests covering db:prepare, db:migrate, db:schema:load paths)

Changes Since v2.2.1

  • 362 commits
  • 762 files changed

Version: v2.3.1 Type: Feature Release

Part of the MITRE Security Automation Framework (SAF)