Skip to content

Phase B remainder: daemon scoping, limits identity, staging tests, attestation, CI image - #40

Merged
txmed82 merged 3 commits into
mainfrom
feat/phase-b-remainder
Sep 8, 2026
Merged

Phase B remainder: daemon scoping, limits identity, staging tests, attestation, CI image#40
txmed82 merged 3 commits into
mainfrom
feat/phase-b-remainder

Conversation

@txmed82

@txmed82 txmed82 commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

What: closes the review gaps — DOCKER_HOST scoped to container spawns; container limits in digest-covered identity; confinement tests; HMAC attestation contract (OSS verify side); CI builds + live-tests the sandbox image digest-pinned.

Why: limits outside identity, CI-skipped container test, untested staging checks, and absent B5 contract.

Verify: full suite green; ruff + format + mypy clean; live container test passes locally digest-pinned. CI + review pending. Remaining B5: cloud executor minting (private tree).

…ing tests, attestation, CI image

- DOCKER_HOST only for docker spawns, never plugin inheritance.
- RuntimeDescriptor carries container limits (digest-covered).
- package_file/entrypoint confinement tests (traversal, symlink,
  absolute path).
- or_audit.eval.attestation: HMAC stamp + verify contract for
  hosted executor (minting lives in cloud tree).
- plugin-image.yml: CI builds sandbox image, live-tests backend
  digest-pinned.
@factory-droid

factory-droid Bot commented Sep 8, 2026

Copy link
Copy Markdown

Droid finished @txmed82's task —— View job


Security Review

This PR tightens sandbox execution and adds CI coverage for the digest-pinned container path. The main risks are (1) the workflow’s digest resolution can produce @<none> instead of a pinned sha256 digest, and (2) container resource caps are now read from untrusted agent packages unless separately enforced by trusted policy.

Comment thread .github/workflows/plugin-image.yml Outdated
Comment on lines +59 to +62
DIGEST=$(docker images --digests --format '{{.Repository}}@{{.Digest}}' | grep '^localhost:5000/surgeval-plugin@' | head -n 1)
test -n "$DIGEST"
echo "value=$DIGEST" >> "$GITHUB_OUTPUT"
echo "Sandbox image: $DIGEST" >> "$GITHUB_STEP_SUMMARY"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] Ensure CI resolves a real image digest

docker images --digests can yield localhost:5000/surgeval-plugin@<none> even after a push, which is non-empty but fails the SURGEVAL_TEST_PLUGIN_IMAGE=image@sha256:... contract that the live backend test enforces; resolve the pushed image’s RepoDigest via docker inspect and validate it’s @sha256: before exporting.

Suggested change
DIGEST=$(docker images --digests --format '{{.Repository}}@{{.Digest}}' | grep '^localhost:5000/surgeval-plugin@' | head -n 1)
test -n "$DIGEST"
echo "value=$DIGEST" >> "$GITHUB_OUTPUT"
echo "Sandbox image: $DIGEST" >> "$GITHUB_STEP_SUMMARY"
DIGEST=$(docker inspect --format='{{index .RepoDigests 0}}' localhost:5000/surgeval-plugin:ci)
case "$DIGEST" in
localhost:5000/surgeval-plugin@sha256:*) ;;
*) echo "Unexpected RepoDigest: $DIGEST" >&2; exit 1 ;;
esac
echo "value=$DIGEST" >> "$GITHUB_OUTPUT"
echo "Sandbox image: $DIGEST" >> "$GITHUB_STEP_SUMMARY"

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in this branch: digest resolved via docker inspect RepoDigests with @sha256: validation; container limits clamped executor-side (64m..16g, 0.1..16, 16..4096) with refusal tests.

sandbox_policy_digest: str = ""
#: Container resource envelope, part of the digest-covered identity so a
#: run cannot claim different limits than it executed under (B4).
container_memory: str = "2g"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] [security] Validate container limits from untrusted packages

RuntimeDescriptor is loaded from agent.toml, so untrusted submissions can now set container_memory/container_cpus/container_pids_limit to values that disable or greatly expand resource caps (for example container_pids_limit="-1"), enabling host DoS when the container runtime is used; enforce these limits via trusted policy (clamp/validate to safe ranges, or require they match executor-configured limits) before passing them into docker run.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in this branch: digest resolved via docker inspect RepoDigests with @sha256: validation; container limits clamped executor-side (64m..16g, 0.1..16, 16..4096) with refusal tests.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Already implemented in this branch: _clamp_container_limits is invoked in _container_command (plugins.py) with executor-side bounds and refusal tests. No change made.

@txmed82
txmed82 merged commit e43b3da into main Sep 8, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants