Skip to content

Commit 89844ba

Browse files
authored
Merge pull request #38 from mempool/knorrium/refactor_validator
2 parents 537f5c7 + 15f9ca9 commit 89844ba

File tree

6 files changed

+938
-22
lines changed

6 files changed

+938
-22
lines changed

.github/workflows/validate-logos.yml

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,13 @@ jobs:
1515
- name: Checkout
1616
uses: actions/checkout@v2
1717

18-
- name: Check for script in SVG logos
19-
run : |
20-
sh check_logos.sh
18+
- name: Setup Node.js
19+
uses: actions/setup-node@v4
20+
with:
21+
node-version: '20'
22+
23+
- name: Install dependencies
24+
run: npm install
25+
26+
- name: Check for unsafe content in SVG logos
27+
run: node check_logos.js

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
node_modules/

check_logos.js

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
#!/usr/bin/env node
2+
3+
import fs from 'fs';
4+
import path from 'path';
5+
import { JSDOM } from 'jsdom';
6+
import createDOMPurify from 'dompurify';
7+
8+
let foundUnsafe = false;
9+
10+
const files = fs.readdirSync('.')
11+
.filter(file => file.endsWith('.svg'))
12+
.filter(file => fs.statSync(file).isFile());
13+
14+
if (files.length === 0) {
15+
console.log('No SVG files found');
16+
process.exit(0);
17+
}
18+
19+
for (const file of files) {
20+
try {
21+
const svgContent = fs.readFileSync(file, 'utf8');
22+
23+
const dom = new JSDOM('<!DOCTYPE html>');
24+
const DOMPurify = createDOMPurify(dom.window);
25+
26+
const cleanSVG = DOMPurify.sanitize(svgContent, {
27+
USE_PROFILES: { svg: true },
28+
KEEP_CONTENT: true
29+
});
30+
31+
const issues = [];
32+
33+
const scriptMatches = svgContent.match(/<script[\s>][\s\S]*?<\/script>/gi);
34+
if (scriptMatches) {
35+
issues.push(`Found ${scriptMatches.length} script tag(s)`);
36+
}
37+
38+
const eventHandlers = svgContent.match(/\s(on\w+)\s*=/gi);
39+
if (eventHandlers) {
40+
const uniqueHandlers = [...new Set(eventHandlers.map(h => h.trim().toLowerCase()))];
41+
issues.push(`Found event handlers: ${uniqueHandlers.join(', ')}`);
42+
}
43+
44+
if (/javascript:/gi.test(svgContent)) {
45+
issues.push('Found javascript: URLs');
46+
}
47+
48+
const originalDOM = new JSDOM(svgContent, { contentType: 'image/svg+xml' });
49+
const sanitizedDOM = new JSDOM(cleanSVG, { contentType: 'image/svg+xml' });
50+
51+
const originalScripts = originalDOM.window.document.querySelectorAll('script');
52+
const sanitizedScripts = sanitizedDOM.window.document.querySelectorAll('script');
53+
54+
if (originalScripts.length > sanitizedScripts.length) {
55+
issues.push(`DOMPurify removed ${originalScripts.length - sanitizedScripts.length} script element(s)`);
56+
}
57+
58+
const allElements = originalDOM.window.document.querySelectorAll('*');
59+
let eventHandlerCount = 0;
60+
allElements.forEach(el => {
61+
Array.from(el.attributes).forEach(attr => {
62+
if (attr.name.toLowerCase().startsWith('on')) {
63+
eventHandlerCount++;
64+
}
65+
});
66+
});
67+
68+
if (eventHandlerCount > 0 && issues.length === 0) {
69+
const sanitizedAllElements = sanitizedDOM.window.document.querySelectorAll('*');
70+
let sanitizedEventHandlerCount = 0;
71+
sanitizedAllElements.forEach(el => {
72+
Array.from(el.attributes).forEach(attr => {
73+
if (attr.name.toLowerCase().startsWith('on')) {
74+
sanitizedEventHandlerCount++;
75+
}
76+
});
77+
});
78+
79+
if (eventHandlerCount > sanitizedEventHandlerCount) {
80+
issues.push(`DOMPurify removed ${eventHandlerCount - sanitizedEventHandlerCount} event handler attribute(s)`);
81+
}
82+
}
83+
84+
if (issues.length > 0) {
85+
console.log(`Unsafe content found in: ${file}`);
86+
issues.forEach(issue => console.log(` - ${issue}`));
87+
foundUnsafe = true;
88+
}
89+
} catch (error) {
90+
console.error(`Error processing ${file}: ${error.message}`);
91+
foundUnsafe = true;
92+
}
93+
}
94+
95+
if (foundUnsafe) {
96+
process.exit(1);
97+
} else {
98+
console.log('No unsafe content found in SVG files');
99+
process.exit(0);
100+
}
101+

check_logos.sh

Lines changed: 0 additions & 19 deletions
This file was deleted.

0 commit comments

Comments
 (0)