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
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
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
probeBowireRecordingStepService holds the engine list, Body the program.
timeoutSecondsintWall-clock budget; the child is killed past it.
allowedEnginesIReadOnlySet<string>Interpreters this run may launch. Null uses DefaultEngines. Replacing rather than extending is deliberate: it lets an operator NARROW the set (only
python3here, thanks) as easily as widen it, and narrowing is the direction an additive switch could not express.resolveEngineFunc<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.
ctCancellationTokenCancels the probe.
Returns
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
enginestring
Returns
FindOnPath(string)
Locate an interpreter on PATH, honouring PATHEXT on Windows.
public static string? FindOnPath(string engine)
Parameters
enginestring