Class: Vangrail::Cell

Inherits:
Object
  • Object
show all
Defined in:
lib/vangrail/origin.rb

Overview

A value tagged with every origin that produced it.

Mixing is a union: concatenate a user question with a retrieved page and the result carries both origins. Any untrusted origin taints the cell. Taint does not wash off by quoting, summarising, or extracting a field. That is a policy over tagged cells, not CaMeL.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(value, origins:, capabilities: nil) ⇒ Cell

Returns a new instance of Cell.

Raises:

  • (ArgumentError)


121
122
123
124
125
126
127
# File 'lib/vangrail/origin.rb', line 121

def initialize(value, origins:, capabilities: nil)
  @value = value
  @origins = Array(origins).map { |origin| Origin.coerce(origin) }.uniq.freeze
  raise ArgumentError, 'a cell needs at least one origin' if @origins.empty?

  @capabilities = capabilities.nil? ? nil : Array(capabilities).map(&:to_sym).uniq.freeze
end

Instance Attribute Details

#capabilitiesObject (readonly)

Returns the value of attribute capabilities.



119
120
121
# File 'lib/vangrail/origin.rb', line 119

def capabilities
  @capabilities
end

#originsObject (readonly)

Returns the value of attribute origins.



119
120
121
# File 'lib/vangrail/origin.rb', line 119

def origins
  @origins
end

#valueObject (readonly)

Returns the value of attribute value.



119
120
121
# File 'lib/vangrail/origin.rb', line 119

def value
  @value
end

Class Method Details

.data(value, capabilities: nil) ⇒ Object



137
138
139
# File 'lib/vangrail/origin.rb', line 137

def self.data(value, capabilities: nil)
  new(value, origins: Origin.data, capabilities: capabilities)
end

.system(value, capabilities: nil) ⇒ Object



129
130
131
# File 'lib/vangrail/origin.rb', line 129

def self.system(value, capabilities: nil)
  new(value, origins: Origin.system, capabilities: capabilities)
end

.text_of(document) ⇒ Object



145
146
147
148
149
150
# File 'lib/vangrail/origin.rb', line 145

def self.text_of(document)
  return document.value.to_s if document.is_a?(self)
  return document.to_s unless document.is_a?(Hash)

  (document['text'] || document[:text]).to_s
end

.tool(value, capabilities: nil) ⇒ Object



141
142
143
# File 'lib/vangrail/origin.rb', line 141

def self.tool(value, capabilities: nil)
  new(value, origins: Origin.tool, capabilities: capabilities)
end

.user(value, capabilities: nil) ⇒ Object



133
134
135
# File 'lib/vangrail/origin.rb', line 133

def self.user(value, capabilities: nil)
  new(value, origins: Origin.user, capabilities: capabilities)
end

Instance Method Details

#mix(other, value: self.value) ⇒ Object

Union of origins. The value is the caller's combination; this only tracks what touched it.



162
163
164
165
166
# File 'lib/vangrail/origin.rb', line 162

def mix(other, value: self.value)
  self.class.new(value,
                 origins: origins + other.origins,
                 capabilities: merge_capabilities(other))
end

#privileged?Boolean

Returns:

  • (Boolean)


152
153
154
# File 'lib/vangrail/origin.rb', line 152

def privileged?
  origins.all?(&:privileged?)
end

#quoteObject

A quoted or extracted form still carries every origin and every remaining capability. Quoting is not a privilege escalation.



170
171
172
# File 'lib/vangrail/origin.rb', line 170

def quote
  self.class.new(value, origins: origins, capabilities: capabilities)
end

#tainted?Boolean

Returns:

  • (Boolean)


156
157
158
# File 'lib/vangrail/origin.rb', line 156

def tainted?
  origins.any?(&:untrusted?)
end

#to_hObject



174
175
176
177
178
179
180
181
# File 'lib/vangrail/origin.rb', line 174

def to_h
  {
    'value' => value,
    'origins' => origins.map(&:to_s),
    'tainted' => tainted?,
    'capabilities' => capabilities,
  }.compact
end