@@ -168,6 +168,27 @@ private module Settings {
168168
169169 boolean getValue ( ) { result = valueLiteral .getValue ( ) }
170170 }
171+
172+ /**
173+ * A node that sets a Stringlike value.
174+ */
175+ class StringlikeSetting extends LiteralSetting {
176+ override StringlikeLiteral valueLiteral ;
177+ }
178+
179+ /**
180+ * A node that sets a Stringlike value, or `nil`.
181+ */
182+ class NillableStringlikeSetting extends LiteralSetting {
183+ NillableStringlikeSetting ( ) {
184+ valueLiteral instanceof StringlikeLiteral or
185+ valueLiteral instanceof NilLiteral
186+ }
187+
188+ string getStringValue ( ) { result = valueLiteral .( StringlikeLiteral ) .getValueText ( ) }
189+
190+ predicate isNilValue ( ) { valueLiteral instanceof NilLiteral }
191+ }
171192}
172193
173194/**
@@ -184,5 +205,72 @@ private class AllowForgeryProtectionSetting extends Settings::BooleanSetting,
184205 override boolean getVerificationSetting ( ) { result = this .getValue ( ) }
185206}
186207
208+ /**
209+ * Sets the cipher to be used for encrypted cookies. Defaults to "aes-256-gcm".
210+ * This can be set to any cipher supported by
211+ * https://ruby-doc.org/stdlib-2.7.1/libdoc/openssl/rdoc/OpenSSL/Cipher.html
212+ */
213+ private class EncryptedCookieCipherSetting extends Settings:: StringlikeSetting ,
214+ CookieSecurityConfigurationSetting:: Range {
215+ EncryptedCookieCipherSetting ( ) {
216+ this .getReceiver ( ) instanceof Config:: ActionDispatchNode and
217+ this .getMethodName ( ) = "encrypted_cookie_cipher="
218+ }
219+
220+ OpenSSLCipher getCipher ( ) { this .getValueText ( ) = result .getName ( ) }
221+
222+ OpenSSLCipher getDefaultCipher ( ) { result .getName ( ) = "aes-256-gcm" }
223+
224+ override string getSecurityWarningMessage ( ) {
225+ this .getCipher ( ) .isWeak ( ) and
226+ result = this .getValueText ( ) + " is a weak cipher."
227+ }
228+ }
229+
230+ /**
231+ * If true, signed and encrypted cookies will use the AES-256-GCM cipher rather
232+ * than the older AES-256-CBC cipher. Defaults to true.
233+ */
234+ private class UseAuthenticatedCookieEncryptionSetting extends Settings:: BooleanSetting ,
235+ CookieSecurityConfigurationSetting:: Range {
236+ UseAuthenticatedCookieEncryptionSetting ( ) {
237+ this .getReceiver ( ) instanceof Config:: ActionDispatchNode and
238+ this .getMethodName ( ) = "use_authenticated_cookie_encryption="
239+ }
240+
241+ boolean getDefaultValue ( ) { result = true }
242+
243+ override string getSecurityWarningMessage ( ) {
244+ this .getValue ( ) = false and
245+ result = this .getSettingString ( ) + " selects a weaker block mode for authenticated cookies."
246+ }
247+ }
248+
249+ // TODO: this may also take a proc that specifies how to handle specific requests
250+ /**
251+ * Configures the default value of the `SameSite` attribute when setting cookies.
252+ * Valid string values are `strict`, `lax`, and `none`.
253+ * The attribute can be omitted by setting this to `nil`.
254+ * The default if unset is `:lax`.
255+ * https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite#strict
256+ */
257+ private class CookiesSameSiteProtectionSetting extends Settings:: NillableStringlikeSetting ,
258+ CookieSecurityConfigurationSetting:: Range {
259+ CookiesSameSiteProtectionSetting ( ) {
260+ this .getReceiver ( ) instanceof Config:: ActionDispatchNode and
261+ this .getMethodName ( ) = "cookies_same_site_protection="
262+ }
263+
264+ string getDefaultValue ( ) { result = "lax" }
265+
266+ override string getSecurityWarningMessage ( ) {
267+ // Mark unset as being potentially dangerous, as not all browsers default to "lax"
268+ this .getStringValue ( ) .toLowerCase ( ) = "none" and
269+ result = "Setting 'SameSite' to 'None' may make an application more vulnerable to CSRF attacks."
270+ or
271+ this .isNilValue ( ) and
272+ result = "Unsetting 'SameSite' can disable same-site cookie restrictions in some browsers."
273+ }
274+ }
187275// TODO: initialization hooks, e.g. before_configuration, after_initialize...
188276// TODO: initializers
0 commit comments