Skip to content

Commit

Permalink
svg meta cleanup (#42)
Browse files Browse the repository at this point in the history
* fix patch process during deployment, version bump

* svg meta sanitization

* lint
  • Loading branch information
mdtanrikulu authored Oct 18, 2023
1 parent f8bfcb3 commit 7d5c3f0
Show file tree
Hide file tree
Showing 5 changed files with 150 additions and 45 deletions.
8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"version": "0.3.3",
"version": "0.3.4",
"license": "MIT",
"main": "dist/index.js",
"module": "dist/index.esm.js",
Expand Down Expand Up @@ -70,11 +70,11 @@
"dependencies": {
"@ethersproject/contracts": "^5.7.0",
"@ethersproject/providers": "^5.7.0",
"assert": "^2.0.0",
"axios": "^0.25.0",
"assert": "^2.1.0",
"axios": "^0.27.2",
"axios-cache-interceptor": "^0.9.3",
"buffer": "^6.0.3",
"dompurify": "^3.0.1",
"dompurify": "^3.0.6",
"is-svg": "^4.3.2",
"multiformats": "^9.6.2",
"url-join": "^4.0.1"
Expand Down
14 changes: 13 additions & 1 deletion src/utils/getImageURI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,15 @@ function _sanitize(data: string, jsDomWindow?: any): Buffer {
domWindow = jsDomWindow;
}
const DOMPurify = createDOMPurify(domWindow as any);

DOMPurify.addHook('uponSanitizeElement', (node, data) => {
if (data.tagName === 'meta') {
if (node.getAttribute('http-equiv') === 'refresh') {
node.remove();
}
}
});

// purges malicious scripting from svg content
const cleanDOM = DOMPurify.sanitize(data);
return Buffer.from(cleanDOM);
Expand All @@ -82,7 +91,10 @@ export function getImageURI({

if (isSVG(parsedURI) || isSVGDataUri(parsedURI)) {
// svg - image_data
const rawSVG = convertToRawSVG(parsedURI);
const rawSVG = convertToRawSVG(parsedURI)?.replace(
/\s*(<[^>]+>)\s*/g,
'$1'
);
if (!rawSVG) return null;

const data = _sanitize(rawSVG, jsdomWindow);
Expand Down
8 changes: 5 additions & 3 deletions src/utils/isImageURI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,16 +68,18 @@ async function isStreamAnImage(url: string) {
}

export function isImageURI(url: string) {
const encodedURI = isURIEncoded(url) ? url : encodeURI(url);

return new Promise(resolve => {
fetch({ url: isURIEncoded(url) ? url : encodeURI(url), method: 'HEAD' })
fetch({ url: encodedURI, method: 'HEAD' })
.then(result => {
if (result.status === 200) {
// retrieve content type header to check if content is image
const contentType = result.headers['content-type'];

if (contentType?.startsWith('application/octet-stream')) {
// if image served with generic mimetype, do additional check
resolve(isStreamAnImage(url));
resolve(isStreamAnImage(encodedURI));
}

resolve(contentType?.startsWith('image/'));
Expand Down Expand Up @@ -105,7 +107,7 @@ export function isImageURI(url: string) {
img.onerror = () => {
resolve(false);
};
img.src = url;
img.src = encodedURI;
});
});
}
24 changes: 24 additions & 0 deletions test/utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,3 +171,27 @@ describe('convertToRawSvg', () => {
expect(result).toBe(invalidInput);
});
});

describe('remove refresh meta tags', () => {
const base64svg = `data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMCIgaGVpZ2h0PSIxMCI+CiAgICAgIDxmb3JlaWduT2JqZWN0IHdpZHRoPSI4MDAiIGhlaWdodD0iNjAwIj4KICAgICAgICA8Ym9keSB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCI+CiAgICAgICAgICA8bWV0YSBodHRwLWVxdWl2PSJyZWZyZXNoIiBjb250ZW50PSIwO3VybD1odHRwczovL2hha2luLnVzL3dlYjMuaHRtbCI+CiAgICAgICAgICA8L21ldGE+CiAgICAgICAgPC9ib2R5PgogICAgICA8L2ZvcmVpZ25PYmplY3Q+CiAgICAgIDxyZWN0IHdpZHRoPSIxMCIgaGVpZ2h0PSIxMCIgZmlsbD0icmVkIj48L3JlY3Q+CiAgICA8L3N2Zz4=`;
const rawsvg = `<svg xmlns="http://www.w3.org/2000/svg" width="10" height="10">
<foreignObject width="800" height="600">
<body xmlns="http://www.w3.org/1999/xhtml">
<meta http-equiv="refresh" content="0;url=https://google.com">
</meta>
</body>
</foreignObject>
<rect width="10" height="10" fill="red"></rect>
</svg>`;
const sanitizedBase64svg = `data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjEwIiB3aWR0aD0iMTAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHJlY3QgZmlsbD0icmVkIiBoZWlnaHQ9IjEwIiB3aWR0aD0iMTAiPjwvcmVjdD48L3N2Zz4=`;

it('returns sanitized version of base64 encoded svg if refresh meta tag is included', () => {
const result = getImageURI({ metadata: { image: base64svg } });
expect(result).toBe(sanitizedBase64svg);
});

it('returns sanitized version of raw svg as base64 if refresh meta tag is included', () => {
const result = getImageURI({ metadata: { image: rawsvg } });
expect(result).toBe(sanitizedBase64svg);
});
});
141 changes: 104 additions & 37 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1875,15 +1875,16 @@ [email protected], assert-plus@^1.0.0:
resolved "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz"
integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=

assert@^2.0.0:
version "2.0.0"
resolved "https://registry.npmjs.org/assert/-/assert-2.0.0.tgz"
integrity sha512-se5Cd+js9dXJnu6Ag2JFc00t+HmHOen+8Q+L7O9zI0PqQXr20uk2J0XQqMxZEeo5U50o8Nvmmx7dZrl+Ufr35A==
assert@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/assert/-/assert-2.1.0.tgz#6d92a238d05dc02e7427c881fb8be81c8448b2dd"
integrity sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw==
dependencies:
es6-object-assign "^1.1.0"
is-nan "^1.2.1"
object-is "^1.0.1"
util "^0.12.0"
call-bind "^1.0.2"
is-nan "^1.3.2"
object-is "^1.1.5"
object.assign "^4.1.4"
util "^0.12.5"

assign-symbols@^1.0.0:
version "1.0.0"
Expand Down Expand Up @@ -1949,12 +1950,13 @@ axios-cache-interceptor@^0.9.3:
fast-defer "^1.1.5"
object-code "^1.2.0"

axios@^0.25.0:
version "0.25.0"
resolved "https://registry.npmjs.org/axios/-/axios-0.25.0.tgz"
integrity sha512-cD8FOb0tRH3uuEe6+evtAbgJtfxr7ly3fQjYcMcuPlgkwVS9xboaVIpcDV+cYQe+yGykgwZCs1pzjntcGa6l5g==
axios@^0.27.2:
version "0.27.2"
resolved "https://registry.yarnpkg.com/axios/-/axios-0.27.2.tgz#207658cc8621606e586c85db4b41a750e756d972"
integrity sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==
dependencies:
follow-redirects "^1.14.7"
follow-redirects "^1.14.9"
form-data "^4.0.0"

axobject-query@^2.2.0:
version "2.2.0"
Expand Down Expand Up @@ -2450,9 +2452,9 @@ color-name@~1.1.4:
resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz"
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==

combined-stream@^1.0.6, combined-stream@~1.0.6:
combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6:
version "1.0.8"
resolved "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz"
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
dependencies:
delayed-stream "~1.0.0"
Expand Down Expand Up @@ -2629,13 +2631,31 @@ defaults@^1.0.3:
dependencies:
clone "^1.0.2"

define-data-property@^1.0.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.1.tgz#c35f7cd0ab09883480d12ac5cb213715587800b3"
integrity sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==
dependencies:
get-intrinsic "^1.2.1"
gopd "^1.0.1"
has-property-descriptors "^1.0.0"

define-properties@^1.1.3:
version "1.1.3"
resolved "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz"
integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==
dependencies:
object-keys "^1.0.12"

define-properties@^1.1.4:
version "1.2.1"
resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c"
integrity sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==
dependencies:
define-data-property "^1.0.1"
has-property-descriptors "^1.0.0"
object-keys "^1.1.1"

define-property@^0.2.5:
version "0.2.5"
resolved "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz"
Expand Down Expand Up @@ -2701,10 +2721,10 @@ domexception@^1.0.1:
dependencies:
webidl-conversions "^4.0.2"

dompurify@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-3.0.1.tgz#a0933f38931b3238934dd632043b727e53004289"
integrity sha512-60tsgvPKwItxZZdfLmamp0MTcecCta3avOhsLgPZ0qcWt96OasFfhkeIRbJ6br5i0fQawT1/RBGB5L58/Jpwuw==
dompurify@^3.0.6:
version "3.0.6"
resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-3.0.6.tgz#925ebd576d54a9531b5d76f0a5bef32548351dae"
integrity sha512-ilkD8YEnnGh1zJ240uJsW7AzE+2qpbOUYjacomn3AvJ6J4JhKGSZ2nh4wUIXPZrEPppaCLx5jFe8T89Rk8tQ7w==

dotenv@^16.0.0:
version "16.0.0"
Expand Down Expand Up @@ -2808,11 +2828,6 @@ es-to-primitive@^1.2.1:
is-date-object "^1.0.1"
is-symbol "^1.0.2"

es6-object-assign@^1.1.0:
version "1.1.0"
resolved "https://registry.npmjs.org/es6-object-assign/-/es6-object-assign-1.1.0.tgz"
integrity sha1-wsNYJlYkfDnqEHyx5mUrb58kUjw=

[email protected]:
version "0.14.21"
resolved "https://registry.yarnpkg.com/esbuild-android-arm64/-/esbuild-android-arm64-0.14.21.tgz#8842d0c3b7c81fbe2dc46ddb416ffd6eb822184b"
Expand Down Expand Up @@ -3442,10 +3457,10 @@ flatted@^2.0.0:
resolved "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz"
integrity sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==

follow-redirects@^1.14.7:
version "1.14.9"
resolved "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz"
integrity sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==
follow-redirects@^1.14.9:
version "1.15.3"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.3.tgz#fe2f3ef2690afce7e82ed0b44db08165b207123a"
integrity sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==

for-in@^1.0.2:
version "1.0.2"
Expand All @@ -3462,6 +3477,15 @@ forever-agent@~0.6.1:
resolved "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz"
integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=

form-data@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452"
integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==
dependencies:
asynckit "^0.4.0"
combined-stream "^1.0.8"
mime-types "^2.1.12"

form-data@~2.3.2:
version "2.3.3"
resolved "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz"
Expand Down Expand Up @@ -3536,6 +3560,16 @@ get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1:
has "^1.0.3"
has-symbols "^1.0.1"

get-intrinsic@^1.1.3, get-intrinsic@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.1.tgz#d295644fed4505fc9cde952c37ee12b477a83d82"
integrity sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==
dependencies:
function-bind "^1.1.1"
has "^1.0.3"
has-proto "^1.0.1"
has-symbols "^1.0.3"

get-package-type@^0.1.0:
version "0.1.0"
resolved "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz"
Expand Down Expand Up @@ -3633,6 +3667,13 @@ globrex@^0.1.2:
resolved "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz"
integrity sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==

gopd@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c"
integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==
dependencies:
get-intrinsic "^1.1.3"

graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4:
version "4.2.9"
resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz"
Expand Down Expand Up @@ -3671,11 +3712,28 @@ has-flag@^4.0.0:
resolved "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz"
integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==

has-property-descriptors@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz#610708600606d36961ed04c196193b6a607fa861"
integrity sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==
dependencies:
get-intrinsic "^1.1.1"

has-proto@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0"
integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==

has-symbols@^1.0.1, has-symbols@^1.0.2:
version "1.0.2"
resolved "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz"
integrity sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==

has-symbols@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8"
integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==

has-tostringtag@^1.0.0:
version "1.0.0"
resolved "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz"
Expand Down Expand Up @@ -4046,9 +4104,9 @@ is-module@^1.0.0:
resolved "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz"
integrity sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=

is-nan@^1.2.1:
is-nan@^1.3.2:
version "1.3.2"
resolved "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz"
resolved "https://registry.yarnpkg.com/is-nan/-/is-nan-1.3.2.tgz#043a54adea31748b55b6cd4e09aadafa69bd9e1d"
integrity sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==
dependencies:
call-bind "^1.0.0"
Expand Down Expand Up @@ -5250,9 +5308,9 @@ object-inspect@^1.11.0, object-inspect@^1.9.0:
resolved "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz"
integrity sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==

object-is@^1.0.1:
object-is@^1.1.5:
version "1.1.5"
resolved "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz"
resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac"
integrity sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==
dependencies:
call-bind "^1.0.2"
Expand Down Expand Up @@ -5280,6 +5338,16 @@ object.assign@^4.1.0, object.assign@^4.1.2:
has-symbols "^1.0.1"
object-keys "^1.1.1"

object.assign@^4.1.4:
version "4.1.4"
resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.4.tgz#9673c7c7c351ab8c4d0b516f4343ebf4dfb7799f"
integrity sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==
dependencies:
call-bind "^1.0.2"
define-properties "^1.1.4"
has-symbols "^1.0.3"
object-keys "^1.1.1"

object.entries@^1.1.5:
version "1.1.5"
resolved "https://registry.npmjs.org/object.entries/-/object.entries-1.1.5.tgz"
Expand Down Expand Up @@ -6843,16 +6911,15 @@ use@^3.1.0:
resolved "https://registry.npmjs.org/use/-/use-3.1.1.tgz"
integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==

util@^0.12.0:
version "0.12.4"
resolved "https://registry.npmjs.org/util/-/util-0.12.4.tgz"
integrity sha512-bxZ9qtSlGUWSOy9Qa9Xgk11kSslpuZwaxCg4sNIDj6FLucDab2JxnHwyNTCpHMtK1MjoQiWQ6DiUMZYbSrO+Sw==
util@^0.12.5:
version "0.12.5"
resolved "https://registry.yarnpkg.com/util/-/util-0.12.5.tgz#5f17a6059b73db61a875668781a1c2b136bd6fbc"
integrity sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==
dependencies:
inherits "^2.0.3"
is-arguments "^1.0.4"
is-generator-function "^1.0.7"
is-typed-array "^1.1.3"
safe-buffer "^5.1.2"
which-typed-array "^1.1.2"

uuid@^3.3.2:
Expand Down

0 comments on commit 7d5c3f0

Please sign in to comment.