Skip to content

feat(config): add DOCKER_IMAGE_SELECTION_MODE=fixed for deterministic pentest image - #400

Open
LuckVd wants to merge 1 commit into
vxcontrol:mainfrom
LuckVd:fix/392-enforce-pentest-image
Open

feat(config): add DOCKER_IMAGE_SELECTION_MODE=fixed for deterministic pentest image#400
LuckVd wants to merge 1 commit into
vxcontrol:mainfrom
LuckVd:fix/392-enforce-pentest-image

Conversation

@LuckVd

@LuckVd LuckVd commented Sep 1, 2026

Copy link
Copy Markdown

Description

Fixes #392

DOCKER_DEFAULT_IMAGE_FOR_PENTEST (and the DefaultImageForPentest template variable) was documented and configured as if it constrains which Docker image a flow's terminal container uses. In practice it was only injected as text into the image_chooser prompt (backend/pkg/templates/prompts/image_chooser.tmpl), and the LLM's raw text response was used directly as the image name (backend/pkg/providers/providers.go, NewFlowProvider) with no validation and no deterministic fallback. The issue reporter demonstrated that weaker/local models (e.g. qwen2.5:7b-instruct) reliably ignore the pentest-image guidance and return e.g. node:latest, silently running pentest flows in the wrong environment.

This PR implements the issue's preferred option 1 (deterministic mode switch) as an opt-in setting, keeping the default behavior unchanged:

Change

  • backend/pkg/config/config.go: new DockerImageSelectionMode field (env DOCKER_IMAGE_SELECTION_MODE, default "llm").
  • backend/pkg/providers/providers.go:
    • NewFlowProvider now selects the image deterministically when DOCKER_IMAGE_SELECTION_MODE=fixed: it skips the LLM call entirely and uses the configured pentest image.
    • New small helper resolvePentestImage(pentestImage, defaultImage) — lowercases/trims the configured pentest image and falls back to the default docker image when it is unset (mirrors the empty-value handling in pkg/docker/client.go).
    • Any mode value other than "fixed" keeps the existing LLM-based selection, so existing deployments are unaffected.
  • backend/pkg/providers/image_selection_test.go: new unit tests covering the helper (configured image, case/whitespace normalization, empty fallback).
  • backend/pkg/config/config_test.go: DOCKER_IMAGE_SELECTION_MODE added to the hermetic env-clearing list.
  • .env.example: new documented setting.

Scope note

The LLM path itself is intentionally unchanged (no allow-list validation, no behavior change for default deployments); operators who want a hard guarantee set DOCKER_IMAGE_SELECTION_MODE=fixed. The issue's suggested option 2 (response allow-list validation) would be a behavioral change for existing deployments and is deliberately not included.

Type of Change

  • 🐛 Bug fix (opt-in deterministic enforcement)

Related Issue

Testing

  • go test ./pkg/providers/ ./pkg/config/ -count=1 — ok, both packages pass (includes the 4 new TestResolvePentestImage cases: configured image, case/whitespace normalization, empty-pentest fallback to default image, normalized fallback).
  • go vet ./pkg/providers/ ./pkg/config/ — clean
  • gofmt -l pkg/providers/ pkg/config/ — no output
  • git diff --check — clean
  • Resource notes: full-repository go test ./... was not run in this environment (resource-constrained sandbox, 4 cores / 3.6GB RAM; build limited via GOMAXPROCS=2 GOFLAGS=-p=1 GOMEMLIMIT=1000MiB). The change is confined to pkg/providers + pkg/config + .env.example; both affected packages and their tests are exercised.
  • Behavior verification of fixed mode is by code review (mode branch skips the only LLM call between image selection and container creation; image is stored on the flow provider and used verbatim, matching the previous path).

Checklist

  • git diff --check origin/main...HEAD passes
  • Changed source files are formatted
  • Targeted tests for the changed packages/components pass
  • Diff-scoped lint passes where applicable (go vet)
  • Full-repository checks were run, or any unrelated/environment-dependent failures are documented above (documented: only affected packages tested due to sandbox resource limits)
  • Self-reviewed the code
  • Added/updated tests covering the change
  • Breaking changes are clearly called out in the description above (none — new setting defaults to the existing behavior)

… pentest image

DOCKER_DEFAULT_IMAGE_FOR_PENTEST was only injected into the image_chooser
prompt; the LLM's raw response was used as the terminal image with no
validation and no deterministic fallback. With weaker local models the
pen-test image guidance is routinely ignored (e.g. returning node:latest),
silently running flows in the wrong environment (issue vxcontrol#392).

Add an opt-in DOCKER_IMAGE_SELECTION_MODE setting: 'llm' (default)
preserves the current behavior; 'fixed' skips the LLM call entirely and
deterministically uses the configured pentest image, falling back to the
default docker image when unset.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant