Module: Otto::Security::CSP
- Defined in:
- lib/otto/security/csp/nonce.rb,
lib/otto/security/csp/parser.rb,
lib/otto/security/csp/policy.rb,
lib/otto/security/csp/report.rb,
lib/otto/security/csp/writer.rb,
lib/otto/security/csp/emit_middleware.rb,
lib/otto/security/csp/report_middleware.rb
Overview
Content-Security-Policy support. The framework-owned lazy nonce accessor lives directly on this module (CSP.nonce / CSP.nonce?), beside the Policy builder, the Writer apply core, the Parser, and the report/emit middlewares.
Defined Under Namespace
Modules: Parser, Policy Classes: EmitMiddleware, Report, ReportMiddleware, Writer
Constant Summary collapse
- DEFAULT_NONCE_KEY =
Default Rack env key the per-request nonce is memoized under. Registered as documentation in EnvKeys::NONCE; per that module’s convention the string literal (not the constant) is what the codebase passes around, so this DEFAULT_NONCE_KEY exists for the CSP code’s own use and the two are kept identical.
'otto.nonce'
Class Method Summary collapse
-
.nonce(env, key: nil) ⇒ String
Framework-owned, request-scoped, LAZY CSP nonce.
-
.nonce?(env, key: nil) ⇒ Boolean
Whether a nonce was already minted for this request, WITHOUT minting one.
-
.nonce_key(env) ⇒ String
The env key the nonce lives under: the app’s configured convention (Otto::Security::Config#csp_nonce_key) when a security config is present on the env, else the framework default.
Class Method Details
.nonce(env, key: nil) ⇒ String
Framework-owned, request-scoped, LAZY CSP nonce.
Generates a fresh base64 nonce on first access and memoizes it into the
request env under the resolved key, so every later reader observes ONE
value: the views that stamp nonce="…" onto <script>/<link> tags and
the EmitMiddleware that writes the script-src
'nonce-…' header both read it here. The header’s nonce matching the
views’ nonce is therefore a STRUCTURAL property, not a convention each app
re-implements (Rails’ request.content_security_policy_nonce model).
An untouched request never generates a nonce and pays nothing — which is also why the emit-if-consumed middleware is safe: it only emits a nonce-only policy for a request whose views actually consumed the nonce.
A value already present under the key (e.g. an app that still mints its own under the same convention) is honored, not overwritten.
44 45 46 47 48 49 50 |
# File 'lib/otto/security/csp/nonce.rb', line 44 def nonce(env, key: nil) resolved = key || nonce_key(env) existing = env[resolved] return existing if existing && !existing.empty? env[resolved] = SecureRandom.base64(16) end |
.nonce?(env, key: nil) ⇒ Boolean
Whether a nonce was already minted for this request, WITHOUT minting one. This is the emit-if-consumed predicate.
58 59 60 61 |
# File 'lib/otto/security/csp/nonce.rb', line 58 def nonce?(env, key: nil) value = env[key || nonce_key(env)] !value.nil? && !value.empty? end |
.nonce_key(env) ⇒ String
The env key the nonce lives under: the app’s configured convention
(Otto::Security::Config#csp_nonce_key) when a security config is present
on the env, else the framework default. Lets an app with an existing
convention (e.g. onetime.nonce) adopt the accessor without renaming its
env key.
71 72 73 74 75 |
# File 'lib/otto/security/csp/nonce.rb', line 71 def nonce_key(env) config = env['otto.security_config'] configured = config.csp_nonce_key if config.respond_to?(:csp_nonce_key) configured && !configured.empty? ? configured : DEFAULT_NONCE_KEY end |