feat: added an URL sanitizer
This commit is contained in:
7
package-lock.json
generated
7
package-lock.json
generated
@@ -9,6 +9,7 @@
|
|||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@braintree/sanitize-url": "^7.1.2",
|
||||||
"@floating-ui/dom": "^1.7.5",
|
"@floating-ui/dom": "^1.7.5",
|
||||||
"@highlightjs/cdn-assets": "^11.11.1",
|
"@highlightjs/cdn-assets": "^11.11.1",
|
||||||
"@libsql/client": "^0.17.0",
|
"@libsql/client": "^0.17.0",
|
||||||
@@ -447,6 +448,12 @@
|
|||||||
"node": ">=18"
|
"node": ">=18"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@braintree/sanitize-url": {
|
||||||
|
"version": "7.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@braintree/sanitize-url/-/sanitize-url-7.1.2.tgz",
|
||||||
|
"integrity": "sha512-jigsZK+sMF/cuiB7sERuo9V7N9jx+dhmHHnQyDSVdpZwVutaBu7WvNYqMDLSgFgfB30n452TP3vjDAvFC973mA==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/@codemirror/autocomplete": {
|
"node_modules/@codemirror/autocomplete": {
|
||||||
"version": "6.20.0",
|
"version": "6.20.0",
|
||||||
"resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.20.0.tgz",
|
"resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.20.0.tgz",
|
||||||
|
|||||||
@@ -60,6 +60,7 @@
|
|||||||
"wait-on": "^9.0.3"
|
"wait-on": "^9.0.3"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@braintree/sanitize-url": "^7.1.2",
|
||||||
"@floating-ui/dom": "^1.7.5",
|
"@floating-ui/dom": "^1.7.5",
|
||||||
"@highlightjs/cdn-assets": "^11.11.1",
|
"@highlightjs/cdn-assets": "^11.11.1",
|
||||||
"@libsql/client": "^0.17.0",
|
"@libsql/client": "^0.17.0",
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
import { sanitizeUrl } from '@braintree/sanitize-url';
|
||||||
import { normalizeNonEmptyTaxonomyTerm } from '../engine/taxonomyUtils';
|
import { normalizeNonEmptyTaxonomyTerm } from '../engine/taxonomyUtils';
|
||||||
|
|
||||||
const MAX_TITLE_LENGTH = 200;
|
const MAX_TITLE_LENGTH = 200;
|
||||||
@@ -42,9 +43,14 @@ function sanitizeHttpUrl(rawUrl: unknown): string | null {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const policySanitized = sanitizeUrl(trimmed);
|
||||||
|
if (policySanitized === 'about:blank') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
let parsed: URL;
|
let parsed: URL;
|
||||||
try {
|
try {
|
||||||
parsed = new URL(trimmed);
|
parsed = new URL(policySanitized);
|
||||||
} catch {
|
} catch {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,14 @@ describe('blogmark deep-link payload', () => {
|
|||||||
expect(payload).toBeNull();
|
expect(payload).toBeNull();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('rejects entity-obfuscated script URLs', () => {
|
||||||
|
const payload = extractBlogmarkPayloadFromDeepLink(
|
||||||
|
'bds://new-post?title=Unsafe&url=javascript%26%2397%3Balert(1)',
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(payload).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
it('builds safe markdown source link', () => {
|
it('builds safe markdown source link', () => {
|
||||||
const markdown = buildBlogmarkMarkdownLink('A [title] (test)', 'https://example.com/x?y=1');
|
const markdown = buildBlogmarkMarkdownLink('A [title] (test)', 'https://example.com/x?y=1');
|
||||||
expect(markdown).toBe('[A \\[title\\] \\(test\\)](<https://example.com/x?y=1>)');
|
expect(markdown).toBe('[A \\[title\\] \\(test\\)](<https://example.com/x?y=1>)');
|
||||||
|
|||||||
Reference in New Issue
Block a user