Skip to content

Instantly share code, notes, and snippets.

@g-k
Created July 14, 2018 01:45
Show Gist options
  • Save g-k/aa53e41a0ce6815d76189e8dead00d77 to your computer and use it in GitHub Desktop.
Save g-k/aa53e41a0ce6815d76189e8dead00d77 to your computer and use it in GitHub Desktop.
extracted mozilla screenshots image validation logic for https://github.com/mozilla-services/screenshots/pull/4615
#!/usr/bin/env node
`
example usage:
node ./screenshots_img_validation.js 'data:image/png;base64,R0k'
testing: data:image/png;base64,R0k
invalid-data-image { msg: 'Invalid PNG image submitted',
prefix: 'data:image/png;base64,R0k' }
/home/gguthe/screenshots_img_validation.js:24
throw new Error("invalid image");
^
Error: invalid image
at assertPngOrJpeg (/home/gguthe/screenshots_img_validation.js:24:13)
at Object.<anonymous> (/home/gguthe/screenshots_img_validation.js:46:1)
at Module._compile (module.js:652:30)
at Object.Module._extensions..js (module.js:663:10)
at Module.load (module.js:565:32)
at tryModuleLoad (module.js:505:12)
at Function.Module._load (module.js:497:3)
at Function.Module.runMain (module.js:693:10)
at startup (bootstrap_node.js:191:16)
at bootstrap_node.js:612:3
`
mozlog = console;
const PNG_HEADER_BASE64 = "iVBORw0KGgo=";
const PNG_HEADER = Buffer.from(PNG_HEADER_BASE64, "base64");
const JPEG_HEADER_BASE64 = "/9g=";
const JPEG_HEADER = Buffer.from(JPEG_HEADER_BASE64, "base64").slice(0, 2);
function assertPngOrJpeg(dataUrl) {
const pngHeader = "data:image/png;base64,";
const jpegHeader = "data:image/jpeg;base64,";
if (!(dataUrl.startsWith(pngHeader) || dataUrl.startsWith(jpegHeader))) {
mozlog.warn("invalid-data-url", {msg: "Invalid data: URL submitted", prefix: dataUrl.substr(0, jpegHeader.length + 10)});
throw new Error("invalid data url");
}
// only decode enough to get the header
// we're lucky that 9 bytes is exactly 12 base64 characters
if (dataUrl.startsWith(pngHeader)) {
const base64Header = dataUrl.substr(pngHeader.length, PNG_HEADER_BASE64.length);
if (base64Header.length < PNG_HEADER_BASE64.length) {
mozlog.warn("invalid-data-image", {msg: "Invalid PNG image submitted", prefix: dataUrl.substr(0, pngHeader.length + PNG_HEADER_BASE64.length)});
throw new Error("invalid image");
}
const header = Buffer.from(base64Header, "base64"); // 9 bytes
if (!PNG_HEADER.equals(header.slice(0, PNG_HEADER.length))) {
mozlog.warn("invalid-data-image-decoded", {msg: "Invalid PNG image (after base64 decoding)"});
throw new Error("invalid png");
}
} else {
const base64Header = dataUrl.substr(jpegHeader.length, JPEG_HEADER_BASE64.length);
if (base64Header.length < JPEG_HEADER_BASE64.length) {
mozlog.warn("invalid-data-image", {msg: "Invalid JPEG image submitted", prefix: dataUrl.substr(0, jpegHeader.length + JPEG_HEADER_BASE64.length)});
throw new Error("invalid image");
}
const header = Buffer.from(base64Header, "base64"); // 9 bytes
if (!JPEG_HEADER.equals(header.slice(0, JPEG_HEADER.length))) {
mozlog.warn("invalid-data-image-decoded", {msg: "Invalid JPEG image (after base64 decoding)"});
throw new Error("invalid jpeg");
}
}
}
mozlog.info('testing:', process.argv[2])
assertPngOrJpeg(process.argv[2]);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment