#7994·flyte

[BUG] flytekit: _dnsify can return node IDs over 63 characters or ending in '-', violating the DNS_LABEL contract

Author: Daksha1611Created Sep 7, 2026Updated Sep 9, 2026

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?

  • Yes

Have you read the Code of Conduct?

  • Yes