Skip to content

sts: build_sts_error_response writes caller-controlled text into XML unescaped #160

Description

@alukach

multistore_sts::build_sts_error_response interpolates the error message into the <Message> element unescaped:

let xml = format!("...<Code>{}</Code><Message>{}</Message>...", code, message);

Several messages carry caller-controlled text:

  • ProxyError::RoleNotFound(role_arn) → role not found: {role_arn}
  • find_key → key '{kid}' not found in JWKS, where kid comes from the unverified JWT header
  • verify_token errors that echo header fields such as alg

The body is served as application/xml. A host's CORS layer may add access-control-allow-origin: *.

Impact:

  • Script injection: a RoleArn such as <x:script xmlns:x="http://www.w3.org/1999/xhtml">alert(document.domain)</x:script> returns a document that browsers render as XHTML, running script on the proxy's origin.
  • Unparseable errors: any & in a RoleArn makes the error body malformed XML, so SDKs fail to parse it.

This is reachable through the STS route that Router::with_sts mounts. A host can escape errors it builds itself, but not this route's.

Suggested fix: escape &, < and > (and " if attributes are ever added) in message before formatting. The Code values are fixed strings.

Found in review of source-cooperative/data.source.coop#237. Its own exchange paths now build escaped bodies (source-cooperative/data.source.coop#246); the person route still goes through this builder.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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