mirror of
https://github.com/AgentSeal/codeburn.git
synced 2026-07-30 19:36:01 +00:00
chore(sync): HTML-escape callback page inputs
This commit is contained in:
parent
2c29352d80
commit
d4f85ced71
2 changed files with 26 additions and 1 deletions
|
|
@ -149,7 +149,14 @@ export interface CallbackResult {
|
|||
* is served once from a throwaway localhost server, so it must not depend
|
||||
* on network fonts, external CSS, or dashboard assets.
|
||||
*/
|
||||
export function renderCallbackPage(ok: boolean, title: string, message: string): string {
|
||||
export function renderCallbackPage(ok: boolean, rawTitle: string, rawMessage: string): string {
|
||||
// Current call sites pass literals, but escape anyway so a future caller
|
||||
// interpolating IdP-influenced text (e.g. the callback `error` param) cannot
|
||||
// turn this localhost page into an XSS sink.
|
||||
const escapeHtml = (s: string) => s.replace(/[&<>"']/g, c =>
|
||||
({ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' })[c]!)
|
||||
const title = escapeHtml(rawTitle)
|
||||
const message = escapeHtml(rawMessage)
|
||||
const accent = ok ? '#1f8a5b' : '#c8541f' // --primary / --chart-5 (terracotta)
|
||||
const mark = ok ? '✓' : '✕' // ✓ / ✕
|
||||
return `<!doctype html>
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import {
|
|||
buildAuthUrl,
|
||||
resolveScopes,
|
||||
startCallbackServer,
|
||||
renderCallbackPage,
|
||||
CALLBACK_PORTS,
|
||||
} from '../src/sync/auth.js'
|
||||
|
||||
|
|
@ -258,3 +259,20 @@ describe('syncConfig', () => {
|
|||
expect(raw).not.toContain('password')
|
||||
})
|
||||
})
|
||||
|
||||
// ── Callback Page Escaping ────────────────────────────────────────────
|
||||
|
||||
describe('renderCallbackPage', () => {
|
||||
it('escapes HTML metacharacters in title and message', () => {
|
||||
const html = renderCallbackPage(false, '<script>alert(1)</script>', 'a & b "c" \'d\'')
|
||||
expect(html).not.toContain('<script>alert(1)</script>')
|
||||
expect(html).toContain('<script>alert(1)</script>')
|
||||
expect(html).toContain('a & b "c" 'd'')
|
||||
})
|
||||
|
||||
it('leaves literal copy intact', () => {
|
||||
const html = renderCallbackPage(true, 'Login successful', 'You can close this tab.')
|
||||
expect(html).toContain('Login successful')
|
||||
expect(html).toContain('You can close this tab.')
|
||||
})
|
||||
})
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue