Class CodeProbeExecutor

Namespace
Kuestenlogik.Bowire.Security.Scanner
Assembly
Kuestenlogik.Bowire.Security.Scanner.dll

Runs a translated Nuclei code: template (#491, #35 Phase 2g) in a child process.

public static class CodeProbeExecutor
Inheritance
CodeProbeExecutor
Inherited Members

Remarks

This executes attacker-authored code on the machine running the scan. Nuclei's corpus is community-supplied and a code: template is a program, not a request — running one is materially different from sending a packet. Nothing here happens unless the operator passes --allow-code-templates; the scan loop refuses first and this type is never reached otherwise.

What the child process actually buys. A separate process bounds the blast radius of a hang or a crash, lets the timeout be enforced by killing something, and keeps the scanner's own memory out of reach. It is not a sandbox: the child inherits the caller's user, filesystem access and network. Saying otherwise would be worse than saying nothing. What is enforced here is an interpreter allow-list, a wall-clock kill, an output cap, and a scratch working directory.

Fields

DefaultEngines

Interpreters a template may name when the operator has not said otherwise. Covers what the corpus uses.

public static readonly IReadOnlySet<string> DefaultEngines

Field Value

IReadOnlySet<string>

Remarks

This is a guardrail, not a security boundary, and it is worth being exact about which. Once --allow-code-templates is on, the entries here already run arbitrary code with the caller's rights — bash and python3 are on the list. What the list actually prevents is a template naming some other binary and getting it launched with our scratch script as its single argument. The boundary is the opt-in flag; this just keeps the set of launched programs predictable, which is why the operator may replace it (--code-template-interpreters) without that being a hole in anything.

MaxOutputChars

Output cap. A template that prints without end would otherwise take the scanner's memory with it.

public const int MaxOutputChars = 262144

Field Value

int

Methods

ExecuteAsync(BowireRecordingStep, int, IReadOnlySet<string>?, Func<string, string?>?, CancellationToken)

Run the step's program and shape its output for the matchers.

public static Task<AttackProbeResponse> ExecuteAsync(BowireRecordingStep probe, int timeoutSeconds = 30, IReadOnlySet<string>? allowedEngines = null, Func<string, string?>? resolveEngine = null, CancellationToken ct = default)

Parameters

probe BowireRecordingStep

Service holds the engine list, Body the program.

timeoutSeconds int

Wall-clock budget; the child is killed past it.

allowedEngines IReadOnlySet<string>

Interpreters this run may launch. Null uses DefaultEngines. Replacing rather than extending is deliberate: it lets an operator NARROW the set (only python3 here, thanks) as easily as widen it, and narrowing is the direction an additive switch could not express.

resolveEngine Func<string, string>

Maps an engine name to an executable path, or null when it is not installed. Injected so the decision logic is testable without depending on which interpreters the test machine happens to have.

ct CancellationToken

Cancels the probe.

Returns

Task<AttackProbeResponse>

ExtensionFor(string)

File extension for the scratch script. Some interpreters pick their mode from it, and Windows refuses to launch an extensionless script through several of them.

public static string ExtensionFor(string engine)

Parameters

engine string

Returns

string

FindOnPath(string)

Locate an interpreter on PATH, honouring PATHEXT on Windows.

public static string? FindOnPath(string engine)

Parameters

engine string

Returns

string