Module: Parse::Agent::PipelineValidator

Extended by:
PipelineValidator
Included in:
PipelineValidator
Defined in:
lib/parse/agent/pipeline_validator.rb

Overview

Validates MongoDB aggregation pipelines to prevent security vulnerabilities.

Thin compatibility wrapper around PipelineSecurity. The actual stage allowlist, operator denylist, depth cap, and recursive walk live there; this module preserves the ‘Parse::Agent::PipelineValidator.validate!` entry point and the `PipelineSecurityError` exception class for callers that pin to them.

Examples:

Parse::Agent::PipelineValidator.validate!([
  { "$match" => { "status" => "active" } },
  { "$group" => { "_id" => "$category", "count" => { "$sum" => 1 } } }
])
# => true

Parse::Agent::PipelineValidator.validate!([{ "$out" => "hacked" }])
# => raises PipelineSecurityError

Defined Under Namespace

Classes: PipelineSecurityError

Constant Summary collapse

BLOCKED_STAGES =

Mirrors of the canonical constants in PipelineSecurity, preserved as constants here so external callers reading ‘Parse::Agent::PipelineValidator::BLOCKED_STAGES` continue to work.

Parse::PipelineSecurity::DENIED_OPERATORS
ALLOWED_STAGES =
Parse::PipelineSecurity::ALLOWED_STAGES
MAX_PIPELINE_DEPTH =
Parse::PipelineSecurity::MAX_DEPTH
MAX_STAGES =
Parse::PipelineSecurity::MAX_PIPELINE_STAGES

Instance Method Summary collapse

Instance Method Details

#refuse_stage0_only_atlas_stages!(pipeline) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/parse/agent/pipeline_validator.rb', line 80

def refuse_stage0_only_atlas_stages!(pipeline)
  return unless pipeline.is_a?(Array)
  pipeline.each do |stage|
    next unless stage.is_a?(Hash)
    stage.each_key do |k|
      key = k.to_s
      next unless Parse::PipelineSecurity::STAGE0_ONLY_ATLAS_STAGES.include?(key)
      raise PipelineSecurityError.new(
        "Stage #{key} is not allowed in caller-supplied agent pipelines. " \
        "Use the dedicated atlas_search / semantic_search agent tool instead.",
        stage: key,
        reason: :stage0_only_atlas_stage,
      )
    end
  end
end

#valid?(pipeline) ⇒ Boolean

Check if a pipeline is valid without raising.

Parameters:

  • pipeline (Array<Hash>)

    the aggregation pipeline

Returns:

  • (Boolean)

    true if valid, false otherwise



101
102
103
104
105
106
# File 'lib/parse/agent/pipeline_validator.rb', line 101

def valid?(pipeline)
  validate!(pipeline)
  true
rescue PipelineSecurityError
  false
end

#validate!(pipeline) ⇒ true

Validate an aggregation pipeline for security issues. Delegates to PipelineSecurity.validate_pipeline! and translates its error into PipelineSecurityError for backwards compatibility. Additionally refuses Atlas-stage-0-only operators (‘$search`, `$searchMeta`, `$vectorSearch`, `$listSearchIndexes`) which are legal SDK-emitted stages but must NOT appear in a caller-supplied agent pipeline — the agent surface for those is the dedicated `atlas_search` / `semantic_search` tools, and the Agent’s tenant-scope ‘$match` prepend would push them off stage 0 anyway. See PipelineSecurity::STAGE0_ONLY_ATLAS_STAGES.

Parameters:

  • pipeline (Array<Hash>)

    the aggregation pipeline stages

Returns:

  • (true)

    if pipeline is valid

Raises:



66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/parse/agent/pipeline_validator.rb', line 66

def validate!(pipeline)
  Parse::PipelineSecurity.validate_pipeline!(pipeline)
  refuse_stage0_only_atlas_stages!(pipeline)
  true
rescue Parse::PipelineSecurity::Error => e
  raise PipelineSecurityError.new(
    e.message,
    stage: e.stage,
    reason: e.reason,
    operator: e.operator,
  )
end