slash_console 0.1.6 → 0.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 00dad9f1dd2b860398d627127e7bd3df9b5596b0e9fc8c8e915de93c7229ceed
4
- data.tar.gz: 2f451ca16d04c7e89a008b1533b9ffcc355326689c3664fedeb8054fd37bfa85
3
+ metadata.gz: fe6fc75ab8103bf062f9a10eefdcc0385749f4c1889b04fb1c6ba0f1a99a939d
4
+ data.tar.gz: 6186eb67c87e30ebb7c0e09dca9cd4d38212d5186fd32571a0ee89aedaaea780
5
5
  SHA512:
6
- metadata.gz: af3ca9a32035629be4bcdc38b7e8808bc2a4b7f92635359a7781a4e622a566b09d68a4963855ac614f18590d124e0fb953e731c92cc8d5670357f6a20804ebdb
7
- data.tar.gz: 824164461e81532a821fdda656ff611e8ff6d662dc2fb8451fc030e7d1f79ee3adcf5f33230a475ab937318037e489937f48853cb40ab595150c8af567b237e9
6
+ metadata.gz: 611af64c4b066ec322875c66d9eac0a50ff0cc0102344240b24f1dd501ec60cd2241f3d19cd3f45fd593c0c63205685483bcdf79df23b18081e91e141618432d
7
+ data.tar.gz: 9f7f467142f12e16668899c9cb150e7b7165be1f2df1b099d93d2809bc2d5fb0ffb36f32d2befdd752be3c83cb2850331ad91bae944510704b76379c8400d6d1
data/CHANGELOG.md CHANGED
@@ -7,6 +7,31 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.1.7] - 2026-07-10
11
+
12
+ ### Security
13
+ - Authentication is now required in every environment except `development`
14
+ and `test`, instead of only `production`. The engine force-enables
15
+ web-console and allows all IPs everywhere, so a `staging`/`preview`
16
+ deployment previously served an unauthenticated console.
17
+ - Require web-console >= 4.2.1: versions before 4.1.0 do not put CSP
18
+ nonces on injected assets (silently breaking under a strict CSP), and
19
+ versions before 4.2.1 lack Rack 3 / Rails 7.1 support.
20
+ - Enabled `rubygems_mfa_required`, so future gem pushes and yanks require
21
+ a multi-factor-authenticated RubyGems session.
22
+
23
+ ### Fixed
24
+ - A malformed Basic Authorization header (credentials without a colon)
25
+ now gets a 401 on Rack 2 instead of raising.
26
+ - Stored console sessions are capped at 50 per process. web-console's
27
+ session store is never evicted otherwise, so each console page load
28
+ pinned a binding in memory until process restart.
29
+
30
+ ### Removed
31
+ - Deleted the engine's unused application layout, which referenced a
32
+ stylesheet that does not ship with the gem, and a no-op CSRF skip in
33
+ the console controller (the console page is GET-only).
34
+
10
35
  ## [0.1.6] - 2026-07-10
11
36
 
12
37
  ### Security
@@ -78,6 +103,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
78
103
  - Development mode with no authentication required
79
104
  - Standard Ruby style guide compliance
80
105
 
81
- [Unreleased]: https://github.com/firstdraft/slash_console/compare/v0.1.6...HEAD
106
+ [Unreleased]: https://github.com/firstdraft/slash_console/compare/v0.1.7...HEAD
107
+ [0.1.7]: https://github.com/firstdraft/slash_console/compare/v0.1.6...v0.1.7
82
108
  [0.1.6]: https://github.com/firstdraft/slash_console/compare/v0.1.0...v0.1.6
83
109
  [0.1.0]: https://github.com/firstdraft/slash_console/releases/tag/v0.1.0
data/README.md CHANGED
@@ -6,7 +6,7 @@ A Rails engine that provides a web-based console interface at `/rails/console`,
6
6
 
7
7
  - Only use this gem in applications where the security trade-offs are acceptable. Basically, only for toy apps/proofs-of-concept/portfolio projects that contain only sample data. Never use this gem when real user data is at risk.
8
8
  - For serious apps, SSH into the server and run `rails console` at the command-line. This may require upgrading your hosting from free to paid, but you should be doing that anyway if you have real users.
9
- - Make up a strong, unique `ADMIN_PASSWORD` for each app.
9
+ - Make up a strong, unique `ADMIN_PASSWORD` for each app. There is no rate limiting on the password prompt, so a short or guessable password can be brute-forced.
10
10
 
11
11
  ## Installation
12
12
 
@@ -30,9 +30,9 @@ That's it! Navigate to `/rails/console` in your browser.
30
30
 
31
31
  In development, no authentication is required. Simply visit `/rails/console`.
32
32
 
33
- ### Production
33
+ ### Deployed environments
34
34
 
35
- For production use, authentication is required. Set these environment variables:
35
+ In every environment other than `development` and `test` — production, staging, previews, anything — authentication is required. Set these environment variables:
36
36
 
37
37
  ```bash
38
38
  ADMIN_USERNAME="choose_your_own_username"
@@ -41,15 +41,19 @@ ADMIN_PASSWORD="choose_your_own_strong_password"
41
41
 
42
42
  Without these environment variables, you'll see an error message explaining what needs to be configured.
43
43
 
44
+ If your server runs multiple processes (e.g. Puma workers), console sessions live in the memory of whichever process rendered the page, so evaluating code may intermittently report that your session is no longer available. Run a single process (e.g. `WEB_CONCURRENCY=1`) for a reliable console.
45
+
44
46
  ## How It Works
45
47
 
46
48
  SlashConsole is a lightweight wrapper around [the excellent `web-console` gem](https://github.com/rails/web-console). It:
47
49
 
48
50
  1. Provides a dedicated route for console access (instead of only on error pages).
49
51
  2. Renders a full-page console interface, including in apps that enforce a strict nonce-based Content Security Policy.
50
- 3. In production, requires basic authentication via a Rack middleware that protects both the console page and web-console's code-evaluation endpoints (`/__web_console/repl_sessions/:id`).
52
+ 3. In every environment except development and test, requires basic authentication via a Rack middleware that protects both the console page and web-console's code-evaluation endpoints (`/__web_console/repl_sessions/:id`).
51
53
  4. Evaluates console input at the top level, so constants resolve the same way as in `bin/rails console`.
52
54
 
55
+ Note that SlashConsole configures web-console itself: it activates it in all environments and clears its IP allowlist (authentication replaces it). Any `config.web_console` settings in your app will be overridden.
56
+
53
57
  ## Development
54
58
 
55
59
  After checking out the repo, run `bundle install` to install dependencies.
@@ -2,17 +2,23 @@ module SlashConsole
2
2
  class ConsoleController < ApplicationController
3
3
  layout false
4
4
 
5
- skip_before_action :verify_authenticity_token, if: -> { defined?(verify_authenticity_token) }
5
+ # web-console stores every console session (and the binding it holds)
6
+ # in an in-memory hash that is never evicted, so each page load would
7
+ # otherwise pin memory until the process restarts. Old sessions are
8
+ # dropped once this many accumulate; an evicted session's tab shows
9
+ # web-console's normal "session is no longer available" message.
10
+ MAX_STORED_SESSIONS = 50
6
11
 
7
12
  # BasicAuthMiddleware is the primary guard: it protects both this page
8
13
  # and web-console's evaluator endpoints, but only at the engine's
9
14
  # standard /rails mount point. These filters remain as a second layer
10
15
  # so the page stays protected if an application mounts the engine at a
11
16
  # custom path.
12
- before_action :ensure_credentials_configured, if: -> { Rails.env.production? }
13
- before_action :authenticate_user, if: -> { Rails.env.production? }
17
+ before_action :ensure_credentials_configured, if: -> { BasicAuthMiddleware.authentication_required? }
18
+ before_action :authenticate_user, if: -> { BasicAuthMiddleware.authentication_required? }
14
19
 
15
20
  def index
21
+ prune_console_sessions
16
22
  console(SlashConsole.console_binding)
17
23
  render :index
18
24
  end
@@ -30,5 +36,10 @@ module SlashConsole
30
36
  BasicAuthMiddleware.authorized?(username, password)
31
37
  end
32
38
  end
39
+
40
+ def prune_console_sessions
41
+ storage = WebConsole::Session.inmemory_storage
42
+ storage.shift while storage.size >= MAX_STORED_SESSIONS
43
+ end
33
44
  end
34
45
  end
@@ -1,5 +1,5 @@
1
1
  module SlashConsole
2
- # Basic authentication for the console in production.
2
+ # Basic authentication for the console in deployed environments.
3
3
  #
4
4
  # Authentication must happen in the middleware stack, not in
5
5
  # ConsoleController: web-console's evaluator endpoints (PUT/POST
@@ -20,6 +20,14 @@ module SlashConsole
20
20
  CONSOLE_PATHS = %r{\A/rails(?:/(?:console)?(?:\.[^/]*)?/?)?\z}
21
21
 
22
22
  class << self
23
+ # Development and test are the only environments that get an open
24
+ # console. Any deployed environment -- production, staging, preview,
25
+ # or anything else -- must present credentials, because the engine
26
+ # force-enables web-console everywhere and allows all IPs.
27
+ def authentication_required?
28
+ !(Rails.env.development? || Rails.env.test?)
29
+ end
30
+
23
31
  def credentials_configured?
24
32
  ENV["ADMIN_USERNAME"].present? && ENV["ADMIN_PASSWORD"].present?
25
33
  end
@@ -35,14 +43,13 @@ module SlashConsole
35
43
  end
36
44
 
37
45
  def call(env)
38
- return @app.call(env) unless Rails.env.production? && protects?(env[Rack::PATH_INFO].to_s)
46
+ return @app.call(env) unless self.class.authentication_required? && protects?(env[Rack::PATH_INFO].to_s)
39
47
 
40
48
  unless self.class.credentials_configured?
41
49
  return [503, {"content-type" => "text/plain"}, [CREDENTIALS_MESSAGE]]
42
50
  end
43
51
 
44
- auth = Rack::Auth::Basic::Request.new(env)
45
- if auth.provided? && auth.basic? && self.class.authorized?(*auth.credentials)
52
+ if valid_credentials?(env)
46
53
  @app.call(env)
47
54
  else
48
55
  unauthorized
@@ -51,6 +58,17 @@ module SlashConsole
51
58
 
52
59
  private
53
60
 
61
+ # Destructures rather than splatting: Rack 2 (Rails 7.0 apps) does not
62
+ # validate credential arity in Request#basic?, so a header whose
63
+ # decoded value lacks a colon would otherwise raise instead of 401ing.
64
+ def valid_credentials?(env)
65
+ auth = Rack::Auth::Basic::Request.new(env)
66
+ return false unless auth.provided? && auth.basic?
67
+
68
+ username, password = auth.credentials
69
+ self.class.authorized?(username, password)
70
+ end
71
+
54
72
  def protects?(path)
55
73
  CONSOLE_PATHS.match?(path) || evaluator_path?(path)
56
74
  end
@@ -1,3 +1,3 @@
1
1
  module SlashConsole
2
- VERSION = "0.1.6"
2
+ VERSION = "0.1.7"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: slash_console
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.6
4
+ version: 0.1.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Raghu Betina
@@ -29,14 +29,14 @@ dependencies:
29
29
  requirements:
30
30
  - - ">="
31
31
  - !ruby/object:Gem::Version
32
- version: '4.0'
32
+ version: 4.2.1
33
33
  type: :runtime
34
34
  prerelease: false
35
35
  version_requirements: !ruby/object:Gem::Requirement
36
36
  requirements:
37
37
  - - ">="
38
38
  - !ruby/object:Gem::Version
39
- version: '4.0'
39
+ version: 4.2.1
40
40
  - !ruby/object:Gem::Dependency
41
41
  name: standard
42
42
  requirement: !ruby/object:Gem::Requirement
@@ -66,7 +66,6 @@ files:
66
66
  - app/assets/stylesheets/slash_console/application.css
67
67
  - app/controllers/slash_console/application_controller.rb
68
68
  - app/controllers/slash_console/console_controller.rb
69
- - app/views/layouts/slash_console/application.html.erb
70
69
  - app/views/slash_console/console/index.html.erb
71
70
  - config/routes.rb
72
71
  - lib/slash_console.rb
@@ -78,6 +77,7 @@ homepage: https://github.com/firstdraft/slash_console
78
77
  licenses:
79
78
  - MIT
80
79
  metadata:
80
+ rubygems_mfa_required: 'true'
81
81
  homepage_uri: https://github.com/firstdraft/slash_console
82
82
  source_code_uri: https://github.com/firstdraft/slash_console
83
83
  changelog_uri: https://github.com/firstdraft/slash_console/blob/main/CHANGELOG.md
@@ -1,17 +0,0 @@
1
- <!DOCTYPE html>
2
- <html>
3
- <head>
4
- <title>Slash console</title>
5
- <%= csrf_meta_tags %>
6
- <%= csp_meta_tag %>
7
-
8
- <%= yield :head %>
9
-
10
- <%= stylesheet_link_tag "slash_console/application", media: "all" %>
11
- </head>
12
- <body>
13
-
14
- <%= yield %>
15
-
16
- </body>
17
- </html>