Skip to main content

ruso_runtime/runtime/
spec.rs

1use crate::contract::{HttpMethod, ObjectBody};
2
3#[derive(Debug, Clone, PartialEq)]
4pub struct HttpRequestSpec {
5    pub method: HttpMethod,
6    pub path: String,
7    pub timeout: Option<String>,
8    pub follow_redirect: Option<bool>,
9    pub verify_ssl: Option<bool>,
10    pub proxy: Option<String>,
11    pub user_agent: Option<String>,
12    pub headers: Vec<(String, String)>,
13    pub cookies: Vec<(String, String)>,
14    pub queries: Vec<(String, String)>,
15    pub data_body: Option<ObjectBody>,
16    pub json_body: Option<ObjectBody>,
17    pub raw_body: Option<String>,
18    pub body_bytes: Option<String>,
19    pub multipart_body: Option<ObjectBody>,
20}
21
22impl Default for HttpRequestSpec {
23    fn default() -> Self {
24        Self {
25            method: HttpMethod::Get,
26            path: "/".into(),
27            timeout: None,
28            follow_redirect: None,
29            verify_ssl: None,
30            proxy: None,
31            user_agent: None,
32            headers: Vec::new(),
33            cookies: Vec::new(),
34            queries: Vec::new(),
35            data_body: None,
36            json_body: None,
37            raw_body: None,
38            body_bytes: None,
39            multipart_body: None,
40        }
41    }
42}
43
44/// Generic socket options (shared by dns/tcp/udp probes).
45#[derive(Debug, Clone, PartialEq)]
46pub struct SocketProbeSpec {
47    /// Target host. Often `{{scan_host}}` so it follows the CLI `--target`.
48    pub host: String,
49    /// Target port. Required at runtime for `tcp`/`udp`; for `dns`, its
50    /// presence selects wire mode over the OS resolver.
51    pub port: Option<u16>,
52    /// Optional payload bytes to send on connect.
53    pub payload: Option<Vec<u8>>,
54    /// TLS handshake before application data (TCP only).
55    pub tls: bool,
56    /// Keep connection open across multiple `send` on the same probe name.
57    pub session: bool,
58    /// Maximum bytes to read per exchange (default 65536).
59    pub read_max: u32,
60    /// After first read, keep reading until idle for this many ms (0 = single read).
61    pub read_idle_ms: u32,
62}
63
64impl Default for SocketProbeSpec {
65    fn default() -> Self {
66        Self {
67            host: String::new(),
68            port: None,
69            payload: None,
70            tls: false,
71            session: false,
72            read_max: 65_536,
73            read_idle_ms: 0,
74        }
75    }
76}
77
78/// A probe definition, tagged by transport.
79#[derive(Debug, Clone, PartialEq)]
80pub enum ProbeKind {
81    /// HTTP/HTTPS request.
82    Http(HttpRequestSpec),
83    /// DNS probe — OS resolver or wire mode (see [`SocketProbeSpec`]).
84    Dns(SocketProbeSpec),
85    /// Raw TCP (optionally TLS).
86    Tcp(SocketProbeSpec),
87    /// Raw UDP.
88    Udp(SocketProbeSpec),
89}
90
91/// The `metadata { … }` block of a check — describes the finding it emits.
92///
93/// Only `name` is required to emit a finding; the rest enriches the report and
94/// is needed to publish to the registry.
95#[derive(Debug, Clone, Default)]
96pub struct CheckMetadata {
97    /// Short finding title (the registry slug derives from this).
98    pub name: Option<String>,
99    /// What the check does.
100    pub description: Option<String>,
101    /// The risk if the check is positive.
102    pub impact: Option<String>,
103    /// Finding severity (defaults to `Info` when unset).
104    pub severity: Option<crate::contract::Severity>,
105    /// Check author.
106    pub author: Option<String>,
107    /// Associated CVE identifiers.
108    pub cve: Vec<String>,
109    /// Associated CWE identifiers.
110    pub cwe: Vec<String>,
111    /// Reference URLs (advisories, docs).
112    pub references: Vec<String>,
113    /// CVSS vector strings (e.g. base + temporal).
114    pub cvss: Vec<String>,
115    /// CVSS numeric scores.
116    pub cvss_score: Vec<String>,
117    /// Single free-text remediation note. The language rejects more than one
118    /// `mitigation` line per script at compile time (unlike `cve`/`cwe`/
119    /// `references`/`tags`, which accumulate into lists).
120    pub mitigation: Option<String>,
121    /// Free-form discovery labels (many per check).
122    pub tags: Vec<String>,
123    /// SemVer string; required at publish time, optional for local use.
124    pub version: Option<String>,
125    /// Single curated category (e.g. `web`, `network`, `database`).
126    /// Distinct from `tags`: one-per-script, used for "scan everything
127    /// in this family" selection. The allowed set is enforced by the
128    /// registry at publish time, not here.
129    pub family: Option<String>,
130}
131
132/// The non-executable part of a compiled program: the probe table and the
133/// finding metadata. The instruction stream lives in [`BytecodeProgram`].
134///
135/// [`BytecodeProgram`]: crate::BytecodeProgram
136#[derive(Debug, Clone)]
137pub struct ProgramSpec {
138    /// Probes keyed by their script name (e.g. `home`, `redis`).
139    pub probes: std::collections::HashMap<String, ProbeKind>,
140    /// The check's finding metadata.
141    pub metadata: CheckMetadata,
142}
143
144impl SocketProbeSpec {
145    /// True when this spec uses the OS resolver (a `dns` probe with neither
146    /// `port` nor `payload`) rather than DNS wire mode.
147    pub fn is_dns_resolver_mode(&self) -> bool {
148        self.port.is_none() && self.payload.is_none()
149    }
150}