11

I'm currently using the AWS javascript SDK to create pre-signed POST's. (note that this question is NOT about pre-signed PUTs/URLs, another s3 feature)

https://github.com/aws/aws-sdk-js/

When trying to create a pre-signed post I do something like the following:

const params = {
  Bucket: 'myuniques3bucket',
  Fields: {
    Key: 'key1.png',
    'Content-Type': 'image/png'
  },
  conditions: [
    {bucket: 'myuniques3bucket'},
    {key: 'key1.png'},
    {'Content-Type': 'image/png'},
    ['content-length-range', 1024, 1048576], // 1KB to 10MB
    {'x-amz-date': amzDate},
    {'x-amz-algorithm': 'AWS4-HMAC-SHA256'},
    {'x-amz-credential': `${process.env.AWS_ACCESS_KEY_ID}/20180820/us-east-2/s3/aws4_request`}
  ],
  Expires: 300  // 300 seconds
}

s3.createPresignedPost(params, (err, data) => {
  console.log(data);
});

And I'm wrapping tests around the upload processes that should not work. I'm finding that the content type is not enforced there as I can upload other file types with other content-type post params.

It's not clear to me whether the JS SDK manages the signing process for the user or if I need to do something special to get these various keys in the signature.

It's clear that I CAN do some of this, it's not clear if I NEED to. Not sure if the library is supposed to be handling that for me.

TLDR; What do I need to do to activate content-type validation with s3 pre-signed POST's using the js sdk?

Any help would be greatly appreciated.

Travis Glines
  • 403
  • 5
  • 8

2 Answers2

9

The policy document is only specifying what the form fields must contain in order for S3 to accept the signed request as valid -- in this case, that the form must claim that the content-type is image/png so that S3 will store the object with Content-Type: image/png. This mechanism doesn't actually validate the content-type of the object itself. S3 doesn't have a way of doing that, nor does the JS SDK.

You could do it in JS in the browser or you could do it after the upload, using an S3 event to notify a background process that the uploaded content needs to be validated. Post-processing images is probably a good practice, anyway, because you often want to strip out any inappropriate metadata, such as data included in some images identifying the location where the photo was taken.

Michael - sqlbot
  • 169,571
  • 25
  • 353
  • 427
  • 3
    To clarify, the form I'm submitting claims that the content type is something else. In this case I'm claiming that it's `text/plain` and the upload still works and I expect it not to. Understood that S3/sdk doesn't open the file and actually verify the type your form claims. This is why I'm wondering if it's ignoring content-type or if I'm just not signing the request correctly or something. – Travis Glines Aug 21 '18 at 13:01
  • 1
    Interesting. That should not be possible. What about the object? What content-type do you see if you inspect it in the console after the upload? – Michael - sqlbot Aug 21 '18 at 20:48
  • I noticed the same behaviour: as long as the `form` provides a field named `Content-Type` with the value required by the policy, `S3` will accept the file, whatever its contents. – Marcello Romani Sep 22 '20 at 13:01
-2

You can just set your S3 storage to just accept certain types of files. Look at the docs: https://aws.amazon.com/premiumsupport/knowledge-center/s3-allow-certain-file-types/

  • 1
    This link allows you to limit file names uploaded to only being those extensions. This will not check the actual content-type of the file. e.g. I upload a shell script with the extension shell-script.png, this would not fail. – max_ Feb 11 '21 at 15:06