Skip to content

fix(cli): reject a project slug that cannot be typed back - #6879

Open
Chessing234 wants to merge 1 commit into
block:mainfrom
Chessing234:cli-project-slug-control-chars
Open

fix(cli): reject a project slug that cannot be typed back#6879
Chessing234 wants to merge 1 commit into
block:mainfrom
Chessing234:cli-project-slug-control-chars

Conversation

@Chessing234

Copy link
Copy Markdown
Contributor

Found by reading validate_project_slug against validate_repo_id; no issue filed.

validate_project_slug checks emptiness and length and nothing else:

fn validate_project_slug(slug: &str) -> Result<(), CliError> {
    if slug.is_empty() { ... }
    if slug.len() > PROJECT_D_MAX_LEN { ... }
    Ok(())
}

The slug is the d tag. It identifies the project (fetch_project filters {"kinds":[KIND_PROJECT],"authors":[..],"#d":[slug]}), it is the value every later --slug is matched on, and it is what projects list prints.

So a slug can carry a newline, a tab, a NUL, or a leading space, and nothing downstream ever recovers it:

$ buzz projects create --slug ' platform'   # leading space
$ buzz projects show --slug platform
project "platform" not found

The project is right there in the listing, rendered as platform, and every command that names it fails. Two projects that differ only by an untypeable character are indistinguishable in a listing and can only be told apart by reading the raw event. Because kind:30621 is addressable, the bad slug is also durable — it is the address, so there is no way to rename it, only to create the correct one alongside and delete the other.

The change

Reject control characters and surrounding whitespace.

This is deliberately narrower than validate_repo_id's [a-zA-Z0-9._-] allowlist. Project slugs are meant to be more permissive — the existing test asserts platform:v2 is legal, with the comment "colons allowed — more permissive than repo-id" — so this rejects only what cannot be typed back, not everything unusual. platform:v2, my project, équipe and team_x.2 all stay legal, and a test pins that so the rule can't quietly tighten into a repo-id clone later.

Testing

  • cargo test -p buzz-cli --lib — 366 passed, 0 failed (three new cases: control characters rejected, surrounding whitespace rejected, permissive interior characters still accepted)
  • cargo clippy -p buzz-cli --all-targets — clean
  • cargo fmt --all -- --check — clean

Not run against a live relay. I have not checked whether the relay independently rejects a d tag containing a control character — if it does, the effect today is a confusing relay-side error rather than a durable bad project, and this still moves the rejection to the argument where the message can name the actual problem.

Related

Independent of #6877 and #6878 (UUID canonicalization in the same crate) — different function, different files, no shared symbols.

validate_project_slug checked emptiness and length and nothing else, so a
slug could carry a newline, a NUL, or a leading space. The slug is the d
tag: it identifies the project, it is the value every later command filters
#d on, and it is what projects list prints.

A slug that differs from another only by an untypeable character therefore
creates a second project that is indistinguishable from the first in a
listing, and every later --slug on the visible spelling reports "not found"
for a project the caller can see.

Reject control characters and surrounding whitespace. Deliberately narrower
than validate_repo_id's allowlist: project slugs are meant to be more
permissive than repo ids (platform:v2 is a valid one), so this rejects only
what cannot be typed back, not everything unusual. Interior spaces, colons
and non-ASCII stay legal, and a test pins that.

Signed-off-by: Taksh <takshkothari09@gmail.com>
@Chessing234
Chessing234 requested a review from a team as a code owner August 26, 2026 12:46
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.

1 participant