[BUG] flytekit: _dnsify can return node IDs over 63 characters or ending in '-', violating the DNS_LABEL contract
- Dominant language
- Go
- Stars
- 7.5k
- Forks
- 886
- Avg merge
- 1d 14h
- Merged PRs (30d)
- 120
Description
### Flyte & Flytekit version
flytekit: master @ `d69b3fb` (also present in 1.16.x)
Python: 3.12
### Describe the bug
`flytekit.core.utils._dnsify` is the only place flytekit enforces the Kubernetes DNS_LABEL contract. Its own docstring states the result:
> must only consist of alphanumeric (lower-case a-z, and 0-9) and not exceed 63 characters. It's permitted to have '-' character as long as it's not in the first or last positions.
It violates both halves of that contract.
**1. The 63-character cap is applied to the input, not the output.**
The hash-and-truncate step runs *before* the character conversion:
```python
if len(value) >= MAX: # MAX = 63
h = _sha224(value.encode("utf-8")).hexdigest()[:HASH_LEN]
value = "{}-{}".format(h, value[-(MAX - HASH_LEN - 1):])
for ch in value:
...
```
But the conversion *grows* the string: every upper-case character gets a `-` inserted before it. A 62-character camelCase name passes the input check and comes out at 70 characters.
There is a `len(res) < 62` guard on the two places a `-` is appended, but it only suppresses the *separator* — the character itself is still appended unconditionally, so `res` keeps growing well past 63. The guard also silently corrupts the tail of the name: `...SweepStage` becomes `...sweepstage`, with the separator dropped.
**2. Consecutive separators can leave a trailing `-`.**
Each of `_`, `-`, `.` appends a `-` without checking whether the previous character is already a `-`, and only a *single* trailing `-` is stripped at the end. Two adjacent separators at the end of a name therefore produce a label ending in `-`, which is not a valid DNS_LABEL.
**Why it matters:** `_dnsify` is applied to every node ID in `flytekit/tools/translator.py`, to `node_name` overrides in `flytekit/core/node.py`, and to eager execution names in `flytekit/core/worker_queue.py`. Nothing downstream re-validates length or shape, so an over-long or trailing-`-` identifier is serialized into the workflow spec and registered as-is. This is the same class of problem as #7607.
### Expected behavior
`_dnsify` returns a valid DNS_LABEL — at most 63 characters, lower-case alphanumerics and `-`, never leading or trailing with `-` — for every input.
### Additional context to reproduce
```python
from flytekit import task, workflow
from flytekit.core.utils import _dnsify
@task
def t(x: int) -> int:
return x
NAME = "TrainImageClassifierOnLargeDatasetWithHyperparameterSweepStage" # 62 chars
@workflow
def wf(x: int) -> int:
return t(x=x).with_overrides(node_name=NAME)
node_id = wf.nodes[0].id
print(len(node_id), node_id)
# 70 train-image-classifier-on-large-dataset-with-hyperparameter-sweepstage
# ^^^^^^^^^^^ separator dropped
# Length, directly:
print(len(_dnsify("A" * 70))) # 88
print(len(_dnsify("aB" * 40))) # 80
print(len(_dnsify("MyTaskName" * 10))) # 75
# Trailing '-':
print(repr(_dnsify("test.."))) # 'test-' <- invalid DNS_LABEL
print(repr(_dnsify("a.."))) # 'a-' <- invalid DNS_LABEL
```
A fuzz sweep over 300k random inputs drawn from `[A-Za-z0-9_-.$ ]` produces 431 outputs that are not valid DNS_LABELs (over-length or trailing `-`) on current master, and 0 after the fix.
### Screenshots
_No response_
### Are you sure this issue hasn't been raised already?
- [x] Yes
### Have you read the Code of Conduct?
- [x] Yes
Contributor guide
Research direction
Start in flytekit/core/utils.py at _dnsify and reproduce the documented long camelCase and trailing-separator examples. Check its callers in flytekit/tools/translator.py, flytekit/core/node.py, and flytekit/core/worker_queue.py; done means every output is a lowercase Kubernetes DNS_LABEL of at most 63 characters with no leading or trailing hyphen.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- kubernetes, python
- Domain
- backend
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 78/100