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: nil, label: nil, integrity: Label::DEFAULT_INTEGRITY, confidentiality: nil, capabilities: nil) ⇒ Cell

Returns a new instance of Cell.

Raises:

  • (ArgumentError)


225
226
227
228
229
230
231
232
233
234
235
# File 'lib/vangrail/origin.rb', line 225

def initialize(value, origins: nil, label: nil, integrity: Label::DEFAULT_INTEGRITY,
               confidentiality: nil, capabilities: nil)
  raise ArgumentError, 'pass origins: or label:, not both' if origins && label
  raise ArgumentError, 'origins are required' unless origins || label

  base = label || Label.new(provenance: origins, integrity: integrity,
                            confidentiality: confidentiality, capabilities: capabilities)
  @value = prepare(value, base)
  @label = child_labels.reduce(base) { |combined, child| combined.mix(child) }
  freeze
end

Instance Attribute Details

#labelObject (readonly)

Returns the value of attribute label.



223
224
225
# File 'lib/vangrail/origin.rb', line 223

def label
  @label
end

#valueObject (readonly)

Returns the value of attribute value.



223
224
225
# File 'lib/vangrail/origin.rb', line 223

def value
  @value
end

Class Method Details

.data(value, **label) ⇒ Object



245
246
247
# File 'lib/vangrail/origin.rb', line 245

def self.data(value, **label)
  new(value, origins: Origin.data, **label)
end

.system(value, **label) ⇒ Object



237
238
239
# File 'lib/vangrail/origin.rb', line 237

def self.system(value, **label)
  new(value, origins: Origin.system, **label)
end

.text_of(document) ⇒ Object



253
254
255
256
257
258
259
# File 'lib/vangrail/origin.rb', line 253

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

  text = document['text'] || document[:text]
  text.is_a?(self) ? text.raw.to_s : text.to_s
end

.tool(value, **label) ⇒ Object



249
250
251
# File 'lib/vangrail/origin.rb', line 249

def self.tool(value, **label)
  new(value, origins: Origin.tool, **label)
end

.user(value, **label) ⇒ Object



241
242
243
# File 'lib/vangrail/origin.rb', line 241

def self.user(value, **label)
  new(value, origins: Origin.user, **label)
end

Instance Method Details

#[](key) ⇒ Object



285
286
287
288
289
290
291
# File 'lib/vangrail/origin.rb', line 285

def [](key)
  selected = value[key]
  return selected if selected.is_a?(self.class)
  return nil if selected.nil?

  self.class.new(selected, label: label)
end

#capabilitiesObject



273
274
275
# File 'lib/vangrail/origin.rb', line 273

def capabilities
  label.capabilities
end

#confidentialityObject



269
270
271
# File 'lib/vangrail/origin.rb', line 269

def confidentiality
  label.confidentiality
end

#derive(derived_value) ⇒ Object

A parser, serializer, summarizer, or extractor supplies a new value but cannot change the security metadata attached to it.



306
307
308
# File 'lib/vangrail/origin.rb', line 306

def derive(derived_value)
  self.class.new(derived_value, label: label)
end

#integrityObject



265
266
267
# File 'lib/vangrail/origin.rb', line 265

def integrity
  label.integrity
end

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

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

Raises:

  • (ArgumentError)


312
313
314
315
316
# File 'lib/vangrail/origin.rb', line 312

def mix(other, value: self.value)
  raise ArgumentError, 'cells can only mix with cells' unless other.is_a?(self.class)

  self.class.new(value, label: label.mix(other.label))
end

#originsObject



261
262
263
# File 'lib/vangrail/origin.rb', line 261

def origins
  label.provenance
end

#privileged?Boolean

Returns:

  • (Boolean)


277
278
279
# File 'lib/vangrail/origin.rb', line 277

def privileged?
  label.privileged?
end

#quoteObject

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



320
321
322
# File 'lib/vangrail/origin.rb', line 320

def quote
  derive(value)
end

#rawObject



293
294
295
296
297
298
299
300
301
302
# File 'lib/vangrail/origin.rb', line 293

def raw
  case value
  when Hash
    value.transform_values(&:raw).freeze
  when Array
    value.map(&:raw).freeze
  else
    value
  end
end

#tainted?Boolean

Returns:

  • (Boolean)


281
282
283
# File 'lib/vangrail/origin.rb', line 281

def tainted?
  label.tainted?
end

#to_hObject



324
325
326
327
328
329
330
331
332
333
# File 'lib/vangrail/origin.rb', line 324

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