Validate SeiNode.spec.chainId with a Pattern regex (shell injection sink in seid-init)

Open
#236 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
3/5
Estimated time
1-2 days
Newbie friendliness
72/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Quiet
Tech stack
bash, go, kubernetes

Research direction

Start in api/v1alpha1/seinode_types.go at SeiNodeSpec.ChainID, then inspect the referenced init-container builders in internal/noderesource/noderesource.go and internal/task/bootstrap_resources.go. Run make manifests generate and review the changes under config/crd/ and manifests/. Confirm the existing-chain audit and admission test reject shell-metacharacter ChainID values without breaking current valid IDs.

Written by the indexing model from the issue text.

Description

Problem

`SeiNodeSpec.ChainID` is validated only with `MinLength=1` (seinode_types.go:14-16). The value is interpolated unquoted via `%s` into bash `-c` scripts at:

  • `internal/noderesource/noderesource.go::buildSeidInitContainer` (the seid-init script)
  • `internal/task/bootstrap_resources.go::bootstrapSeidInitContainer` (the bootstrap variant)

A ChainID like `foo --home /etc; rm -rf /; echo ` passes admission and lands inside `bash -c` as an injection sink.

Surfaced during cross-review of #234 by the security-specialist agent. The PR doesn't widen this surface; it touches adjacent code, which is the moment to flag.

Impact

Anyone with `create/update seinodes` RBAC can execute arbitrary commands inside the seid-init container (uid 65532, with write access to the data PVC and any projected signing-key volumes in the bootstrap variant). The blast radius is the data PVC + any projected secrets mounted into the bootstrap pod.

Today, `create seinodes` is gated to platform operators on harbor. Engineer-cell namespaces have admin via `engineer-service-account` but typically don't author SeiNode CRs directly (they go through seictl + Flux). Risk is bounded but real — RBAC misconfiguration would open the path.

Relevant experts

  • security-specialist (threat model owner)
  • kubernetes-specialist (CRD validation marker authorship)

Proposed approach

Add a kubebuilder validation marker to `SeiNodeSpec.ChainID`:

```go
// +kubebuilder:validation:Pattern=^[a-zA-Z0-9_.-]+$
// +kubebuilder:validation:MaxLength=50
```

Pattern mirrors cosmos-sdk's accepted chain-ID character class. Length cap is conservative; real chain IDs are <30 chars.

Regenerate CRDs via `make manifests generate`. Existing chains: audit production for any chain ID that wouldn't match (`kubectl get seinodes -A -o jsonpath=...`). None expected — current convention is lowercase-alphanumeric.

Acceptance criteria

  • Pattern + MaxLength markers added to `ChainID`
  • CRD regenerated; `config/crd/` and `manifests/` updated
  • Existing chains audit confirms no breakage
  • Test: SeiNode with shell-metacharacter ChainID is rejected at admission

Out of scope

  • Quoting the ChainID inside the bash script (defense-in-depth, separate consideration)
  • Migrating the init scripts away from `bash -c` (larger refactor)

References

  • #234 cross-review (security-specialist) — surfaced this
Dominant language
Go
Stars
1
Forks
2
Avg merge
2h 29m
Merged PRs (30d)
56

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from sei-protocol/sei-k8s-controller

All issues in sei-protocol/sei-k8s-controller

Similar issues

More Go issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.