Skip to content

Commit d7ec503

Browse files
authored
Merge pull request #2760 from ORCID/lmendoza/PD-5100
Lmendoza/pd 5100
2 parents 05fcf40 + ca99cd0 commit d7ec503

12 files changed

Lines changed: 84 additions & 36 deletions

File tree

projects/orcid-registry-ui/src/lib/components/permission-notifications/permission-notifications.component.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {
66
Output,
77
} from '@angular/core'
88
import { DomSanitizer } from '@angular/platform-browser'
9-
import { sanitizeHtmlForTrustedBypass } from '../../utils/sanitize-html-for-trusted-bypass'
9+
import { sanitizeHtmlForTrustedBypass } from '@orcid/ui'
1010
import {
1111
NgClass,
1212
NgFor,

projects/orcid-registry-ui/src/lib/utils/sanitize-html-for-trusted-bypass.ts

Lines changed: 0 additions & 12 deletions
This file was deleted.
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { sanitizeHtmlForTrustedBypass } from './sanitize-html-for-trusted-bypass'
2+
3+
describe('sanitizeHtmlForTrustedBypass', () => {
4+
it('strips script tags and their content', () => {
5+
const html = 'Hello <script>alert(1)</script> world'
6+
expect(sanitizeHtmlForTrustedBypass(html)).toBe('Hello world')
7+
})
8+
9+
it('strips script tags with attributes', () => {
10+
const html = 'Foo <script type="text/javascript">evil()</script> bar'
11+
expect(sanitizeHtmlForTrustedBypass(html)).toBe('Foo bar')
12+
})
13+
14+
it('strips style tags and their content', () => {
15+
const html = 'Text <style>.x { color: red }</style> more'
16+
expect(sanitizeHtmlForTrustedBypass(html)).toBe('Text more')
17+
})
18+
19+
it('strips img tags (e.g. img with onerror)', () => {
20+
const html = `test <img src=x onerror=alert('malicious-code')>`
21+
expect(sanitizeHtmlForTrustedBypass(html)).toBe('test ')
22+
})
23+
24+
it('strips event-handler attributes from any tag', () => {
25+
const html = '<span onclick="alert(1)">click</span>'
26+
expect(sanitizeHtmlForTrustedBypass(html)).toBe('<span>click</span>')
27+
})
28+
29+
it('leaves safe markup intact', () => {
30+
const html = '<span class="highlight">safe</span>'
31+
expect(sanitizeHtmlForTrustedBypass(html)).toBe(html)
32+
})
33+
34+
it('returns empty string for non-string input', () => {
35+
expect(sanitizeHtmlForTrustedBypass(null as any)).toBe('')
36+
expect(sanitizeHtmlForTrustedBypass(undefined as any)).toBe('')
37+
})
38+
})
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/**
2+
* Sanitizes HTML by removing script/style tags, executable elements (img, iframe,
3+
* etc.), and event-handler attributes so the result is safe to pass to
4+
* DomSanitizer.bypassSecurityTrustHtml().
5+
* Use this whenever you need to render HTML that may contain user/content while
6+
* allowing only safe markup (e.g. no scripts).
7+
*/
8+
export function sanitizeHtmlForTrustedBypass(html: string): string {
9+
if (typeof html !== 'string') {
10+
return ''
11+
}
12+
return html
13+
.replace(/<script\b[^>]*>[\s\S]*?<\/script>/gi, '')
14+
.replace(/<style\b[^>]*>[\s\S]*?<\/style>/gi, '')
15+
.replace(/<img\b[^>]*>/gi, '')
16+
.replace(/<iframe\b[^>]*>[\s\S]*?<\/iframe>/gi, '')
17+
.replace(/<object\b[^>]*>[\s\S]*?<\/object>/gi, '')
18+
.replace(/<embed\b[^>]*>/gi, '')
19+
.replace(/<svg\b[^>]*>[\s\S]*?<\/svg>/gi, '')
20+
.replace(/\s+on\w+\s*=\s*(?:"[^"]*"|'[^']*'|[^\s>]*)/gi, '')
21+
}

projects/orcid-ui/src/public-api.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
* Public API Surface of orcid-ui
33
*/
44

5+
export * from './lib/utils/sanitize-html-for-trusted-bypass'
56
export * from './lib/orcid-ui'
67
export * from './lib/components/record-header/record-header.component'
78
export * from './lib/components/text-with-tooltip/text-with-tooltip.component'

src/app/cdk/snackbar/snackbar.service.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,13 @@ export class SnackbarService {
6161
}
6262

6363
if (errorReport?.analytics) {
64+
const description = `${errorReport.analytics.code}/${error?.message ?? ''}`.replace(
65+
/ /g,
66+
''
67+
)
6468
console.error(`
6569
__Report error GA__
66-
description: ${errorReport.analytics.code}/${error.message}\`.replace(/ /g, '')
70+
description: ${description}
6771
fatal: ${errorReport.analytics.fatal}
6872
`)
6973
}

src/app/core/http-content-type-header-interceptor/http-content-type-header-interceptor.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@ export class HttpContentTypeHeaderInterceptor implements HttpInterceptor {
1515
construct() {}
1616

1717
intercept(req: HttpRequest<any>, next: HttpHandler) {
18-
var method = req.method
19-
var urlWithParams = req.urlWithParams
18+
var method = req.method ?? ''
19+
var urlWithParams = req.urlWithParams ?? req.url ?? ''
2020
// If the request contains a content type, be sure to set the encoding to utf-8
21-
if (['POST', 'PUT'].includes(method)) {
21+
if (method && ['POST', 'PUT'].includes(method)) {
2222
var clonedRequest
2323
if (this.formUrlEcondedUrls.find((x) => urlWithParams.includes(x))) {
2424
clonedRequest = req.clone({

src/app/core/xsrf/xsrf-fallback.interceptor.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,10 @@ export class XsrfFallbackInterceptor implements HttpInterceptor {
3939
return next.handle(req)
4040
}
4141

42-
const method = req.method.toUpperCase()
42+
const method = (req.method ?? '').toUpperCase()
4343

4444
// Only care about mutating requests
45-
if (!['POST', 'PUT', 'PATCH', 'DELETE'].includes(method)) {
45+
if (!method || !['POST', 'PUT', 'PATCH', 'DELETE'].includes(method)) {
4646
return next.handle(req)
4747
}
4848

src/app/shared/pipes/safe-html/safe-html.pipe.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Pipe, PipeTransform } from '@angular/core'
22
import { DomSanitizer } from '@angular/platform-browser'
3-
import { sanitizeHtmlForTrustedBypass } from '../../utils/sanitize-html-for-trusted-bypass'
3+
import { sanitizeHtmlForTrustedBypass } from '@orcid/ui'
44

55
@Pipe({
66
name: 'safeHtml',

src/app/shared/pipes/search-term-highlight/search-term-highlight.pipe.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Pipe, PipeTransform } from '@angular/core'
22
import { DomSanitizer, SafeHtml } from '@angular/platform-browser'
3-
import { sanitizeHtmlForTrustedBypass } from '../../utils/sanitize-html-for-trusted-bypass'
3+
import { sanitizeHtmlForTrustedBypass } from '@orcid/ui'
44

55
@Pipe({
66
name: 'searchTermHighlight',

0 commit comments

Comments
 (0)