Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions storage-resize-images/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## Version 0.3.8

fixed - bump sharp to ^0.35.5, which carries libvips 8.18.7, libheif 1.23.5 and librsvg 2.63.2 (sharp advisories GHSA-f88m-g3jw-g9cj, GHSA-rgj7-g3m4-5g8c, GHSA-wq5f-xc86-pv6w).

fixed - restrict libvips to the loaders for the supported formats. The contentType gate reads uploader-set metadata while libvips picks the loader from the bytes, so an SVG, PDF or other decodable file uploaded under a supported contentType was still decoded by the loader for its real format.

## Version 0.3.7

fix: fix broken `getDownloadURL` link in docs
Expand Down
2 changes: 1 addition & 1 deletion storage-resize-images/extension.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
# limitations under the License.

name: storage-resize-images
version: 0.3.7
version: 0.3.8
specVersion: v1beta

displayName: Resize Images
Expand Down
79 changes: 79 additions & 0 deletions storage-resize-images/functions/__tests__/loaders.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/**
* Copyright 2026 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import mockedEnv from "mocked-env";
import * as path from "path";
import sharp from "sharp";

const restoreEnv = mockedEnv({
LOCATION: "us-central1",
IMG_BUCKET: "extensions-testing.appspot.com",
IMG_SIZES: "200x200",
DELETE_ORIGINAL_FILE: "false",
});

import { resize } from "../src/resize-image";
import { shouldResize } from "../src/filters";
import { allowedLoaders } from "../src/loaders";

afterAll(() => restoreEnv());

// SVG bytes stored under a .png name, the shape of an upload whose
// contentType metadata says image/png.
const SVG_AS_PNG = path.join(__dirname, "svg-bytes-as.png");

describe("loader restriction", () => {
test("the contentType gate alone admits SVG bytes labelled image/png", () => {
expect(
shouldResize({
name: "uploads/svg-bytes-as.png",
bucket: "extensions-testing.appspot.com",
contentType: "image/png",
metadata: {},
} as any)
).toBe(true);
});

test("resize rejects bytes for a format outside supportedContentTypes", async () => {
await expect(resize(SVG_AS_PNG, "200x200")).rejects.toThrow(
/unsupported image format/
);
});

test("resize still handles every supported format", async () => {
const png = await sharp({
create: { width: 64, height: 48, channels: 3, background: "#3b35ae" },
})
.png()
.toBuffer();
const inputs = {
jpeg: await sharp(png).jpeg().toBuffer(),
png,
tiff: await sharp(png).tiff().toBuffer(),
webp: await sharp(png).webp().toBuffer(),
gif: await sharp(png).gif().toBuffer(),
avif: await sharp(png).avif().toBuffer(),
};
for (const [format, buffer] of Object.entries(inputs)) {
const out = await resize(buffer, "20x20");
expect(out.length).toBeGreaterThan(0);
expect((await sharp(buffer).metadata()).format).toBe(
format === "avif" ? "heif" : format
);
}
expect(allowedLoaders).toHaveLength(6);
});
});
5 changes: 5 additions & 0 deletions storage-resize-images/functions/__tests__/svg-bytes-as.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading