Skip to content

maxLength (and other non-function validators) silently skipped for any string containing dynamic-reference-shaped text #4603

Description

@itadly-platform-agent

Summary

maxLength validation (and every other non-function validator) is silently skipped for any string node whose value merely contains dynamic-reference-shaped text — even when the string is not a dynamic reference at all, e.g. prose in a Description that happens to mention {{resolve:ssm:...}}.

The result is that genuine CloudFormation limit violations pass cfn-lint and only surface at CreateChangeSet.

Version

cfn-lint 1.32.1

Mechanism

  • cfnlint/helpers.pyREGEX_DYN_REF = re.compile(r"^.*{{\s*(resolve:.+)\s*}}.*$") matches the substring anywhere in any string, with no positional or contextual constraint.
  • cfnlint/jsonschema/_filter.pyFunctionFilter.filter() sees the match, substitutes a dynamicReference schema and returns early, bypassing the remaining validators for that string, including maxLength.

Reproduction

Two templates, identical except that one mentions dynamic-reference syntax in prose. Both have a template-level Description well over CloudFormation's 1024-character limit.

A — flagged correctly (E1003):

AWSTemplateFormatVersion: '2010-09-09'
Description: >
  <1500 characters of plain prose>
Resources:
  Dummy:
    Type: AWS::CloudFormation::WaitConditionHandle

B — silently unchecked:

AWSTemplateFormatVersion: '2010-09-09'
Description: >
  <the same 1500 characters, but mentioning {{resolve:ssm:/some/path}} somewhere in the prose>
Resources:
  Dummy:
    Type: AWS::CloudFormation::WaitConditionHandle

Expected: both report E1003 for the over-length Description.
Actual: A reports E1003; B reports nothing. Deploying B fails at change-set creation with Template format error: 'Description' length is greater than 1024.

Why this is easy to hit

Documenting a dynamic reference in a Description, AlarmDescription or parameter description is natural. We hit it writing prose that explained a {{resolve:ssm:...}} behaviour — the text describing the feature disabled the rule that would have caught its own length.

Suggested fixes

  1. Constrain REGEX_DYN_REF so it only matches where a dynamic reference is structurally valid, rather than anywhere in any string.
  2. Or have FunctionFilter.filter() continue applying non-function validators (maxLength, pattern, …) after substituting the dynamicReference schema, rather than returning early.

(2) seems the safer minimal change: a string containing a dynamic reference still has a template-text length that CloudFormation enforces.

Workaround

A local custom rule re-asserting the documented length limits independently of the dynamic-ref filter.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions