Skip to content

Bug: generated goose recipe YAML fails to parse when the command body contains control characters or a bare CR #3382

Description

@marcelsafin

Description

YamlIntegration._render_yaml in src/specify_cli/integrations/base.py writes the command body verbatim into a |2 literal block scalar. YAML forbids C0 control characters (everything below U+0020 except tab and newline) and DEL in every scalar form, and treats a bare CR as a line break inside a block scalar. A body containing any of these produces a goose recipe that the YAML parser rejects, so the generated command file cannot be loaded back.

This is the YAML sibling of #3340: the TOML renderers got escaping in #3341, the YAML renderer did not. The body reaches this renderer from command templates and from extension/preset command files via CommandRegistrar.render_yaml_command.

Reproduction

import yaml
from specify_cli.integrations.base import YamlIntegration

rendered = YamlIntegration._render_yaml("Title", "desc", "a\x08b", "src")
yaml.safe_load(rendered)
# yaml.reader.ReaderError: unacceptable character #x0008: special characters are not allowed

Confirmed failing inputs: \x08, \x0c, \x1b, \x7f, and a bare \r not part of CRLF (while scanning a simple key).

Expected behavior

The generated recipe parses and the prompt round-trips, whatever bytes the body contains.

Proposed fix

Detect block-scalar-unsafe characters and fall back to an escaped double-quoted scalar rendered by yaml.safe_dump, mirroring the fallback strategy the TOML renderer uses. I have a patch with regression tests ready and will open a PR.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions