Skip to content

Commit

Permalink
fix: xss improvements while parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
stdword committed Feb 17, 2024
1 parent 5ce563f commit 089732b
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 16 deletions.
20 changes: 14 additions & 6 deletions src/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import '@logseq/libs'
import { BlockEntity, PageEntity } from '@logseq/libs/dist/LSPlugin.user'

import {
cleanMacroArg, LogseqReference, p, Properties, PropertiesRefs, PropertiesUtils
cleanMacroArg, escape, LogseqReference, p, Properties, PropertiesRefs, PropertiesUtils
} from './utils'
import { ITemplate } from './template'

Expand Down Expand Up @@ -106,7 +106,10 @@ export class Context {
if (field.startsWith('_'))
continue

if (value instanceof Context)
if (value === null || value === undefined) {
// do nothing
}
else if (value instanceof Context)
value = value.filterForDisplaying()
else if (Array.isArray(value))
value = value.map(item => {
Expand All @@ -126,6 +129,8 @@ export class Context {
if (doc.startsWith('async'))
value = 'async ' + value
}
else if (typeof value === 'object')
value = value.toString()

result[field] = value
}
Expand Down Expand Up @@ -167,7 +172,7 @@ export class PageContext extends Context {
}

static createFromEntity(page: PageEntity) {
const name = page.originalName
const name = page.originalName || page['original-name']
const obj = new PageContext(page.id, name)
obj._page = page

Expand All @@ -186,10 +191,12 @@ export class PageContext extends Context {

obj.uuid = page.uuid

const nameID = escape(obj.name_!, ['"'])

// @ts-expect-error
const path = top!.logseq.api.datascript_query(`[:find ?path
:where
[?p :block/name "${obj.name_}"]
[?p :block/name "${nameID}"]
[?p :block/file ?f]
[?f :file/path ?path]
]`)?.flat().at(0)
Expand All @@ -201,8 +208,9 @@ export class PageContext extends Context {

obj.isJournal = page['journal?']

if (page.journalDay)
obj.day = PageContext.parseDay(page.journalDay)
const day = page.journalDay || page['journal-day']
if (day)
obj.day = PageContext.parseDay(day)
return obj
}
static empty() {
Expand Down
4 changes: 2 additions & 2 deletions src/tags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@ function query_refsCount(context: ILogseqContext, page: PageContext | string = '
name = page.name!
else if (page)
name = _asString(page)
name = name.toLowerCase()
name = escape(name.toLowerCase(), ['"'])

// @ts-expect-error
const refs = top!.logseq.api.datascript_query(`
Expand All @@ -351,7 +351,7 @@ function queryRefs(
name = page.name!
else if (page)
name = _asString(page)
name = name.toLowerCase()
name = escape(name.toLowerCase(), ['"'])

let filterOnly = ''
if (only === 'journals')
Expand Down
17 changes: 11 additions & 6 deletions src/utils/logseq.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { IBatchBlock, BlockEntity, PageEntity, BlockIdentity, EntityID } from '@logseq/libs/dist/LSPlugin.user'

import { escapeForRegExp, f, indexOfNth, p, sleep } from './other'
import { escape, escapeForRegExp, f, indexOfNth, p, sleep } from './other'
import { isEmptyString, isInteger, isUUID, unquote } from './parsing'


Expand Down Expand Up @@ -256,13 +256,15 @@ export async function getBlock(
if (!byProperty)
return [ null, 'name' ]

const name = escape(ref.value.toString(), ['"'])

const query = `
[:find (pull ?b [*])
:where
[?b :block/properties ?props]
[?b :block/page]
[(get ?props :${byProperty}) ?name]
[(= ?name "${ref.value}")]
[(= ?name "${name}")]
]
`.trim()

Expand Down Expand Up @@ -303,8 +305,10 @@ export async function getPageFirstBlock(
return null

let idValue = ref.value.toString().toLowerCase()
if (ref.type !== 'id')
if (ref.type !== 'id') {
idValue = escape(idValue, ['"'])
idValue = `"${idValue}"`
}

let idField = ':block/name'
if (ref.type === 'uuid')
Expand Down Expand Up @@ -419,13 +423,14 @@ export class PropertiesUtils {

let refs: string[] = []
if (obj.properties) {
const val = obj.properties[nameCamelCased]
const val = obj.properties[nameCamelCased] ?? obj.properties[name]
refs = Array.isArray(val) ? val : []
}

let text: string = ''
if (obj.propertiesTextValues)
text = obj.propertiesTextValues[nameCamelCased] ?? ''
const textContainer = obj.propertiesTextValues || obj['properties-text-values']
if (textContainer)
text = textContainer[nameCamelCased] ?? textContainer[name] ?? ''

return {
name: nameCamelCased,
Expand Down
8 changes: 6 additions & 2 deletions src/utils/other.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,15 +94,19 @@ export function sleep(ms: number) {
return new Promise(resolve => setTimeout(resolve, ms))
}

export function escape(str: string, specials: string[]) {
const replacer = new RegExp('(\\' + specials.join('|\\') + ')', 'g')
return str.replaceAll(replacer, '\\$1')
}

export function escapeForRegExp(str: string) {
const specials = [
// '-', '^', '$',
'/', '.', '*', '+', '?', '|',
'(', ')', '[', ']', '{', '}', '\\',
]

const replacer = new RegExp('(\\' + specials.join('|\\') + ')', 'g')
return str.replaceAll(replacer, '\\$1')
return escape(str, specials)

// alternative from MDN
// return str.replace(/[.*+\-?^${}()|[\]\\]/g, '\\$&')
Expand Down

0 comments on commit 089732b

Please sign in to comment.