Definition & Overview
Scope defines the authorized boundaries of a security assessment, penetration test, or OSINT investigation. It specifies which systems, networks, domains, IP ranges, and data types may be examined, and equally importantly, which are explicitly excluded. A well-defined scope prevents unauthorized access, legal liability, and unintended disruption to systems that were not intended to be tested.
Scope documentation typically includes: in-scope targets (domains, IP ranges, applications), out-of-scope targets (production systems, third-party services), permitted techniques (passive reconnaissance, active scanning, exploitation), time windows (when testing may occur), and escalation procedures (whom to contact if issues arise). The scope document is a legally binding agreement between the testing party and the system owner.
The Prismatic Platform formalizes scope as a first-class data structure in its Perimeter and Color Team subsystems. Every security assessment, EASM scan, or OSINT investigation operates within a defined scope that is enforced programmatically. The Red Team's adversarial simulations are strictly scoped to synthetic targets within the PrismaticDark.Sandbox, and the OSINT toolbox enforces rate limits and authorization checks based on the scope configuration of each tool execution.
Technical Deep Dive
Scope enforcement in the Prismatic Platform operates at the tool execution level. Before any OSINT tool or security scanner runs, the scope validator checks that the target falls within the authorized scope and that the requested technique is permitted.
defmodule PrismaticPerimeter.Scope do
@moduledoc """
Scope definition and enforcement for security assessments
and OSINT investigations. Programmatically prevents
out-of-scope operations.
"""
@type t :: %__MODULE__{
id: binary(),
name: String.t(),
targets: [target()],
exclusions: [target()],
techniques: [atom()],
time_window: time_window(),
authorization: authorization(),
created_at: DateTime.t()
}
@type target :: %{
type: :domain | :ip_range | :url | :email_domain | :organization,
value: String.t(),
wildcard: boolean()
}
@type time_window :: %{
start: DateTime.t(),
end: DateTime.t(),
timezone: String.t()
}
@type authorization :: %{
authorizer: String.t(),
document_ref: String.t(),
signed_at: DateTime.t()
}
defstruct [:id, :name, :targets, :exclusions, :techniques, :time_window, :authorization, :created_at]
@spec in_scope?(t(), String.t(), atom()) :: boolean()
def in_scope?(%__MODULE__{} = scope, target, technique) do
target_allowed?(scope, target) and
technique_allowed?(scope, technique) and
within_time_window?(scope) and
not excluded?(scope, target)
end
@spec validate_target(t(), String.t()) :: :ok | {:error, String.t()}
def validate_target(scope, target) do
cond do
not within_time_window?(scope) ->
{:error, "Assessment time window has expired"}
excluded?(scope, target) ->
{:error, "Target #{} is explicitly excluded from scope"}
not target_allowed?(scope, target) ->
{:error, "Target #{} is not in scope"}
true ->
:ok
end
end
defp target_allowed?(%{targets: targets}, target_value) do
Enum.any?(targets, fn t ->
case t.type do
:domain ->
if t.wildcard do
String.ends_with?(target_value, t.value)
else
target_value == t.value
end
:ip_range ->
ip_in_range?(target_value, t.value)
:url ->
String.starts_with?(target_value, t.value)
_ ->
target_value == t.value
end
end)
end
defp excluded?(%{exclusions: exclusions}, target_value) do
Enum.any?(exclusions, fn excl ->
target_value == excl.value or
(excl.wildcard and String.ends_with?(target_value, excl.value))
end)
end
defp technique_allowed?(%{techniques: techniques}, technique) do
technique in techniques
end
defp within_time_window?(%{time_window: %{start: start_time, end: end_time}}) do
now = DateTime.utc_now()
DateTime.compare(now, start_time) in [:gt, :eq] and
DateTime.compare(now, end_time) in [:lt, :eq]
end
defp within_time_window?(%{time_window: nil}), do: true
defp ip_in_range?(_ip, _range) do
# CIDR range check implementation
true
end
end
The scope enforcement is integrated into the OSINT tool execution pipeline as a mandatory pre-execution check.
defmodule PrismaticOsint.ScopeEnforcer do
@moduledoc """
Mandatory scope enforcement for all OSINT tool executions.
Blocks out-of-scope operations before they reach the tool adapter.
"""
@spec enforce(PrismaticPerimeter.Scope.t(), String.t(), map()) :: :ok | {:error, String.t()}
def enforce(scope, tool_slug, params) do
target = extract_target(params)
technique = tool_to_technique(tool_slug)
case PrismaticPerimeter.Scope.validate_target(scope, target) do
:ok ->
if PrismaticPerimeter.Scope.in_scope?(scope, target, technique) do
log_scoped_access(scope, tool_slug, target)
:ok
else
{:error, "Technique #{} not permitted in current scope"}
end
{:error, reason} ->
log_scope_violation(scope, tool_slug, target, reason)
{:error, reason}
end
end
defp extract_target(%{query: query}), do: query
defp extract_target(%{domain: domain}), do: domain
defp extract_target(%{target: target}), do: target
defp extract_target(_), do: ""
defp tool_to_technique("shodan-" <> _), do: :active_scanning
defp tool_to_technique("virustotal-" <> _), do: :passive_reconnaissance
defp tool_to_technique(_), do: :passive_reconnaissance
defp log_scoped_access(scope, tool, target) do
:telemetry.execute([:prismatic, :scope, :access], %{}, %{scope_id: scope.id, tool: tool, target: target})
end
defp log_scope_violation(scope, tool, target, reason) do
:telemetry.execute([:prismatic, :scope, :violation], %{reason: reason}, %{scope_id: scope.id, tool: tool, target: target})
end
endArchitecture & Implementation
Scope management is centralized in the Perimeter module with scopes stored in PostgreSQL. Each assessment session is associated with a scope, and all tool executions within that session are validated against the scope before execution. Scope violations are logged to an immutable audit trail and trigger immediate alerts.
The Color Team security operations maintain separate scopes. The Red Team scope is strictly limited to synthetic targets within the PrismaticDark.Sandbox. The Blue Team scope encompasses the entire platform for defensive monitoring. These scopes cannot be modified by the teams themselves -- only platform administrators can alter scope definitions.
Usage in Prismatic Platform
Scopes are created through the Perimeter dashboard and assigned to assessment sessions. The OSINT toolbox automatically enforces the active scope for all tool executions.
# Create an assessment scope
scope = %PrismaticPerimeter.Scope{
id: Ecto.UUID.generate(),
name: "Q1 2026 External Assessment",
targets: [
%{type: :domain, value: "example.com", wildcard: true},
%{type: :ip_range, value: "192.168.1.0/24", wildcard: false}
],
exclusions: [
%{type: :domain, value: "mail.example.com", wildcard: false}
],
techniques: [:passive_reconnaissance, :active_scanning],
time_window: %{
start: ~U[2026-01-01 00:00:00Z],
end: ~U[2026-03-31 23:59:59Z],
timezone: "UTC"
}
}Cross-References
- Permission - Access rights that scope enforcement relies on
- Sanctions - Screening operations requiring defined scope
- PEP - PEP investigations conducted within authorized scope
- Secrets - Credentials governing access to scoped resources
- Self-Registration - OSINT tools declaring scope requirements at registration
Created by Tomas Korcak (korczis) | GitHub