Skip to content

Validate the size of the value for instance level variables

Summary

Instance level variables have a limit of 1024 characters for the encrypted_value attribute, set at the database level, but no validation on the Rails side for the size of the value:

Ci::InstanceVariable.validators
# => [#<ActiveRecord::Validations::PresenceValidator:0x00007fef077ba270 @attributes=[:key], @options={}>,
 #<ActiveRecord::Validations::LengthValidator:0x00007fef077b9668 @attributes=[:key], @options={:maximum=>255}>,
 #<ActiveModel::Validations::FormatValidator:0x00007fef077b8c18 @attributes=[:key], @options={:with=>/\A[a-zA-Z0-9_]+\z/, :message=>"can contain only letters, digits and '_'."}>,
 #<ActiveRecord::Validations::UniquenessValidator:0x00007feee5827518
  @attributes=[:key],
  @klass=Ci::InstanceVariable(id: integer, variable_type: integer, masked: boolean, protected: boolean, key: text, encrypted_value: text, encrypted_value_iv: text, value: ),
  @options={:message=>"(%{value}) has already been taken"}>,
 #<ActiveModel::Validations::InclusionValidator:0x00007fef077f8318 @attributes=[:masked], @delimiter=[true, false], @options={:in=>[true, false]}>,
 #<ActiveModel::Validations::FormatValidator:0x00007feee580f008 @attributes=[:value], @options={:if=>:masked?, :with=>/\A[a-zA-Z0-9_+=\/@:.-]{8,}\z/}>]

Trying to save any encrypted_value above 1024 characters is going to result in a 500 error.

Steps to reproduce

curl --header "PRIVATE-TOKEN: token" "http://localhost:3000/api/v4/admin/ci/variables" --request POST --form "key=NEW_VARIABLE"  --form "value=$(openssl rand -hex 512)"

{"message":"500 Internal Server Error"}

Possible fixes

We must add a validation for value size and make sure that the encrypted_value size for the value is under the database limit.

The size of encrypted_value is the size of value plus the size of the initialization vector(16) plus the overhead of base64 serialization, so the maximum value that we can store is about 735 characters. We could set the validation limit to 700 as extra precaution.

I think the best long term solution is to use a bytea column to store the encrypted attributes. I think this would yield ~35% in storage reduction.