Skip to content

getSignedUrl stopped normalising input url from version 3.858.0 #7428

@save91

Description

@save91

Checkboxes for prior research

Describe the bug

@aws-sdk/[email protected] introduces a breaking change that is not properly described.

The changelog says

Bug Fixes
• cloudfront-signer: do not use URL Object ([#7237](https://github.com/aws/aws-sdk-js-v3/issues/7237)) ([5a421d4](https://github.com/aws/aws-sdk-js-v3/commit/5a421d48a47cb30c69803a23abfdd2714009efac))

while you stopped normalising the input url.

Why is this important?
If the url gets normalised after it is signed, the server will not be able to validate the signature. This is something that some libraries and browsers automatically does and could lead to unexpected 403 errors.

Regression Issue

  • Select this option if this issue appears to be a regression.

SDK version number

@aws-sdk/[email protected]

Which JavaScript Runtime is this issue in?

Node.js

Details of the browser/Node.js/ReactNative version

v20.19.4

Reproduction Steps

You just need to run the following script with different SDK versions

const { getSignedUrl } = require("@aws-sdk/cloudfront-signer");

// I copied the following keyPairId and privateKey from your unit tests
const keyPairId = "APKAEIBAERJR2EXAMPLE";
const privateKey = Buffer.from(`
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAuHfxvylv0IgfsJkualzZtCqwLyg19Gcsy+jVAAioVtWBOgxE
IYSsED+yzryecDnniJGokXiGTt6nlJk5o95jNSnKw9KOThWey95WudDnEcUWKJow
dlcA1B2iXBx4cmwwdekNxs/hHZjubY+kHuaDc0D/tJYyiN7t84wQA/slRHZ0tDBy
pGI4LeNFn3fmu4dvHcvSYFoa1sV/FDe0P6OHjrkG36XE6gh9+yHEFLAsGzuWZlIH
KmdPx8wuz/73GPnQ/P3+sGjwVjimtzEo5R6VoyMHWHRjenjxN/oFrtizXXuRDsKw
9Vvg8FO3MUsYAEWmKZM3DI9/+niZl/GCjgCIlQIDAQABAoIBAQCX1mKuLrVSuDkd
a3jBI9wuaFTM/BQtMB+3V9a7SGUH1IWh+ia6UDIwzb2oXaksRv1FdF+EHeivUqYt
slG3iH2wbM3xkYaAz1r+A+zu1fzcq5UppoDtZ3/PGPVjTCv4QwVAiKxGUSXC7vaS
SAGXTbY1T/Mp+dduwdCq/0bPgBGU32WzAGtx/JCnKD8brShrcwuGtirDq4c9Pq0T
FOApejyMoYwN0Z6jkErU1qSiEKp/SZrQTO+5BoyjwlZTe8dWjAw4srJ4jH9q1zxm
OZDT+80HnV6FiWqlitqDWQJvPhpW/PMTEmklZZw1WThqRxtm2Xee/KAD5grq+Xho
5xp30A4BAoGBAOXFrkOW65Z8GYzyCjw7XgFkSLA4Dhiwzebxdkv+s2NzHhzGz7pf
Dqe8pQ/bS1B6PLi9v+f8RjP9f1bY3QPxYwfYLwhL/JB4pvLNcGRUQ0fSzWcpmhWH
FN0V6K0kDswC9QL3vbEg9V/MM6EvwNxCPiZB6NQtOqhd48ErZ2cRQKBFAoGBAM2G
aqcWYpyDd06Vc7iVN1QqabpGkDfdk8XC/21ZTOZOQocplv9k+kzSxce8KMZxyQVm
K7D6Atx9uqEdqEutvgdYrJa+Br3VL2oLcBiYPOhuJROyl7Zl8bBeanYAhDraZWbL
tVP/6h9dzowPvcNm6e6SVl+uShqKJb4tv0fftpQRAoGAEXhpWpxEB2oiKzRQEOpW
qHZujG+Gqtvum+uqGfcgvqQHGxsGul316E0Qo9cBr/nLWiSbTdFBqTxSDVFp5J3a
8MLAOLpGVtnFn9p8/DPn9bMSiRCBtbdSn8jFqzx9n4duB668jpY58fG9zzipSlYD
EbebM17JAfo5kftx3kVSi50CgYBPXPd0PA2qOI3ql4WPIneyFYqsNrFcEUEN3cW6
mQA78r536RR43KpW3hEnlr38G1YvsotulKxkLlzR+FzTlGzL82756rk5tsfPYElS
Bf+HFXlVyOISuf0BSQQ9OufUvh7n+gO0Qx9KK3Ql27JAcU4mJPYbjnbpFq2Kaany
fC3JsQKBgANzZbf9D0lgQE1wsb45fzrAPAqRQHeVY7V8sZPQoJFcZ2Ymp/3L/UHc
NwfPmGXHQDQaK9I3XpHfbyOelD6ghHi/wZj0sKR3Uoo84n8sIpCdUvwitjlHlZBE
aoCHJ9c5Pnu6FwMAjP8aaKLQDvoHZKVWL2Ml6A6V3Ed95Itp/g2J
-----END RSA PRIVATE KEY-----`);

const url = "https://d111111abcdef8.cloudfront.net/private-content/private.jpeg?image-description=aws's%20image";
const signedUrl = getSignedUrl({
  url: url,
  keyPairId,
  privateKey,
  dateLessThan: "2026-01-01"
});

console.log(signedUrl);

Note: the relevant part is the ' in the query string parameter

Observed Behavior

With the script above you'll get two different outputs based on the @aws-sdk/cloudfront-signer version you have:

  • until version 3.821.0
https://d111111abcdef8.cloudfront.net/private-content/private.jpeg?image-description=aws%27s%20image&Expires=1767225600&Key-Pair-Id=APKAEIBAERJR2EXAMPLE&Signature=OhE-7F6Y1WVThusm8ZWJzlUWy2-cCMMbaxF4g3FpMsPTH-f-CvPJ90RxzpZhBATy90w3jDdJEJXkPAlK8Uzv7YPV0GVu7jdW0bm17Ppw3K91rbRx3u7cmXC1t7DiaAXWR~IrDRJUVxoq~p7sVmrPTNzmco6V~yRB6JD2Znt8sm46GUqUAO-KKdkr8fb7~vQV3oz8pcaB0EvaJHXaTWsWmmAf2d2wjUXWs0~lrPro2Jccoj7yOkvy4LWqZSRNfex2f-1eqIHf503Qo-xgczfwb3QAiq0At8NY6W5ogfmOxGxGRdnUpR3aLpY6WWQ0Gh3RlhmplMui0nX4wWVu99en7g__
  • from version 3.858.0
https://d111111abcdef8.cloudfront.net/private-content/private.jpeg?image-description=aws's%20image&Expires=1767225600&Key-Pair-Id=APKAEIBAERJR2EXAMPLE&Signature=sL7VoMlKHdf6kQY4e-oRluTmDBJiFbaCVZ~7S93sFzP~7maPzLPgfzWqv0An-ytQHlsQ6lV1dZMILFPpoEMuOmupCJwx8xmRwjdLbr7XAaXMbFRd2jZl0E4854NCYq4v3AihNKJjiftvostAPll3kalW6LpvsVCN8dFjPd2E1L3O8MLvUkzTMrv7Uki-VIA2RcqQL35KE9geneX74f~BtK5ej9H3LqUHxtSpKSo1t9KDowyibQ1vv1Fk8ML7yGoyRwpn2CIAETIfq4Tq7EfbBfIk5cJXLBPqWOOrAal0L2ND5YdFc2HDxDSZR3-3qDXrYCOPL0fsOZqq18FlijHnkg__

As you can see the ' in the query string is no longer normalised

Expected Behavior

The first url is always safe while the second one could get normalised and then, if that happens, the signature is no longer valid. For this reason I think the old behaviour should be the expected one.

Possible Solution

Re-introduce the url normalisation.

Additional Information/Context

No response

Metadata

Metadata

Assignees

Labels

bugThis issue is a bug.pending-releaseThis issue will be fixed by an approved PR that hasn't been released yet.potential-regressionMarking this issue as a potential regression to be checked by team member

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions