Skip to content

karmadactl: FileToBytes uses a single file.Read and ignores the byte count, risking truncated cert/key data #7765

Description

@Anand-240

What happened:

karmadactl init reads Karmada component certificate and key files into memory using a single file.Read call and discards the number of bytes returned.

pkg/karmadactl/cmdinit/utils/format.go:

func FileToBytes(path, name string) ([]byte, error) {
	filename := filepath.Join(path, name)
	file, err := os.Open(filename)
	if err != nil {
		return nil, err
	}
	defer file.Close()

	stats, err := file.Stat()
	if err != nil {
		return nil, err
	}

	data := make([]byte, stats.Size())

	_, err = file.Read(data)   // returned byte count is ignored
	if err != nil {
		return nil, err
	}

	return data, nil
}

io.Reader.Read is not guaranteed to fill the whole buffer in one call. It may return fewer bytes than len(data) with err == nil. Because the count is ignored, the returned slice can contain trailing zero bytes (truncated content) without any error being reported.

This function is used to read the component .crt and .key files in pkg/karmadactl/cmdinit/kubernetes/deploy.go:

certs, err := utils.FileToBytes(i.KarmadaPkiPath, fmt.Sprintf("%s.crt", v))
...
key, err := utils.FileToBytes(i.KarmadaPkiPath, fmt.Sprintf("%s.key", v))

The returned bytes are then stored and written into Karmada secrets.

What you expected to happen:

The full file contents should be read reliably. A short read should either be completed or reported as an error, never silently produce truncated cert/key bytes.

How to reproduce it (as minimally and precisely as possible):

This is a latent correctness bug rather than something that reproduces on every run: os.File.Read usually returns small files in a single call, but the code relies on that undefined behavior instead of the io.Reader contract. When Read returns fewer bytes than the file size (which the contract allows), FileToBytes returns a truncated buffer with no error, and that truncated cert/key gets written into the secret.

Anything else we need to know?:

The fix is small: replace the manual Open/Stat/Read with os.ReadFile(filepath.Join(path, name)), or use io.ReadFull. os.ReadFile is the idiomatic, correct replacement and also simplifies the function. I'd like to work on this.

Environment:

  • Karmada version: master
  • kubectl-karmada or karmadactl version (the result of kubectl-karmada version or karmadactl version): built from master
  • Others: affects karmadactl init (reads component cert/key files)

Metadata

Metadata

Assignees

Labels

kind/bugCategorizes issue or PR as related to a bug.

Type

No type

Projects

Status
No status

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions