Skip to content

Establish Kubernetes context and runtime destination allowlists - #263

Merged
sodejm merged 1 commit into
mainfrom
codex/issue-214-runtime-allowlists
Oct 11, 2026
Merged

sodejm merged 1 commit into
mainfrom
codex/issue-214-runtime-allowlists

Conversation

@sodejm

@sodejm sodejm commented Oct 11, 2026

Copy link
Copy Markdown
Owner

Closes #214.

Acceptance evidence

  • Establishes an explicit Kubernetes context, cluster, and HTTPS API origin before routing a cluster handoff. Application handoffs route to the web specialist.
  • Adds exact allowlists for hosts, resolved IPs, repositories, images, runtimes, and clusters. Live collection requires a destination policy and checks the host before DNS and the resolved IP before opening a socket.
  • Adds an offline subprocess fixture with an allowed handoff and rejection controls for unapproved destination dimensions and Kubernetes context/API host. The fixture records outcomes and removes temporary evidence.
  • Updates the developer-interface skill and package guidance. The documentation distinguishes offline fixture isolation from a live container or Kubernetes test.

Validation and review

  • Focused developer-service tests: 30 passed on the final formatted revision.
  • ruff check ., ruff format --check for changed Python files, and git diff --check origin/main..HEAD: passed.
  • Outgoing gitleaks git --log-opts origin/main..HEAD --redact: no leaks.
  • make check and the repository's full pre-push gate: passed on the published revision.
  • Fresh automated diff critique found no material findings. An independent human review of this exact revision is still required before merge.

The local push gate required Ruff formatting of the touched Python files, which expands the diff. No live Kubernetes or container runtime was contacted in validation.

@sodejm
sodejm marked this pull request as ready for review October 11, 2026 15:50
@sodejm
sodejm merged commit c4d71cf into main Oct 11, 2026
24 of 26 checks passed
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 11, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-11T15:59:36.841239Z 07ad653 Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 07ad653942

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +171 to +172
valid_port = parsed.port is None or 1 <= parsed.port <= 65535
except ValueError as err:

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 Badge Bind the Kubernetes API port in the destination policy

When an allowed API hostname exposes multiple listeners, this accepts every port from 1 through 65535: for example, changing an approved https://api.cluster.internal:6443 server to :12345 still produces an approved handoff, and the output drops the port entirely. This permits an unapproved HTTPS origin to pass the scope check, so the policy should allowlist and emit the canonical origin, including its effective port, rather than authorizing only the hostname.

AGENTS.md reference: AGENTS.md:L103-L104

Useful? React with 👍 / 👎.

Comment on lines +186 to +190
namespace = context.get("namespace", "default")
if not isinstance(namespace, str) or not namespace:
raise DestinationScopeError("Kubernetes namespace is invalid")
try:
_exact(namespace, "Kubernetes namespace")

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 Badge Authorize the Kubernetes namespace before handoff

For a namespace-scoped engagement, changing the kubeconfig context from an authorized namespace to kube-system still succeeds because the namespace is checked only for syntax and there is no corresponding policy allowlist. The resulting handoff presents that namespace as selected for the approved cluster, so bind it to an exact authorized namespace and reject mismatches before routing the handoff.

AGENTS.md reference: AGENTS.md:L103-L104

Useful? React with 👍 / 👎.

Comment on lines +43 to +45
@dataclass(frozen=True)
class DeveloperDestinationPolicy:
"""Explicit exact-match allowlists for all developer workflow destinations."""

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 Badge Update the threat model for the new trust boundary

This new policy and kubeconfig parser establishes a security-sensitive DNS-to-socket authorization and Kubernetes handoff boundary, but the commit leaves docs/THREAT_MODEL.md at its earlier baseline without the new data flow, attacker-controlled inputs, controls, or residual risks. Update the threat model in this change so reviews and releases do not rely on a security model that predates this enforcement path.

AGENTS.md reference: AGENTS.md:L187-L191

Useful? React with 👍 / 👎.

"specialist": routes[kind],
"kind": kind,
"target_host": _host(target_host),
"repository": repository,

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 Badge Reject credential-bearing destination identifiers

When a repository identifier is supplied as a common authenticated URL such as https://user:token@example.test/team/repo.git, _exact accepts it and this field copies the credential verbatim into the generated JSON file or stdout. Validate repository and other destination identifiers into credential-free canonical forms, or reject/redact URL userinfo before serializing the handoff, so configuration mistakes do not turn the output into a secret-bearing artifact.

AGENTS.md reference: AGENTS.md:L101-L104

Useful? React with 👍 / 👎.

Comment on lines 808 to +812
def resolve_target(self, target_host: str) -> str:
return socket.gethostbyname(target_host)
self.destination_policy.authorize_host(target_host)
resolved_ip = socket.gethostbyname(target_host)
self.destination_policy.authorize_ip(resolved_ip)
return resolved_ip

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 Badge Bind each hostname to its approved resolved addresses

When the policy contains multiple approved hosts and IPs, DNS can resolve one allowed hostname to an IP intended for another host and both independent membership checks still succeed; the collector then connects to that other resource while attributing the assessment to the requested hostname. Represent and enforce host-to-address bindings so an approved IP is valid only for the hostname whose resolution was authorized.

AGENTS.md reference: AGENTS.md:L103-L104

Useful? React with 👍 / 👎.

Comment on lines +74 to +76
@classmethod
def load(cls, path: str | Path) -> DeveloperDestinationPolicy:
return cls.from_dict(json.loads(Path(path).read_text(encoding="utf-8")))

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 Badge Reject duplicate keys in destination policy JSON

A policy such as {"hosts":["approved.internal"],"hosts":["evil.internal"]} is accepted because json.loads silently keeps the final occurrence, allowing a visually reviewed restrictive allowlist to be replaced by a later duplicate key. Load this security policy with duplicate-key detection and fail closed on any repeated object member before constructing the allowlists.

AGENTS.md reference: AGENTS.md:L103-L104

Useful? React with 👍 / 👎.

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.

Establish Kubernetes context and runtime destination allowlists

1 participant