mirror of
https://github.com/larvit/adf-codec.git
synced 2026-11-12 11:48:29 +01:00
Answer security round 1: 0 🔴, 0 🟡 (0 misread); replace Forge keys and digits of any script, and fetch with the repo read-only
This commit is contained in:
@@ -39,10 +39,15 @@ function walk(value, path, visit) {
|
||||
}
|
||||
}
|
||||
|
||||
// `<app id>/<environment id>/...`, so one more id, where any other extension key names a macro.
|
||||
function isForgeKey(key, value) {
|
||||
return key === 'extensionKey' && String(value).includes('/')
|
||||
}
|
||||
|
||||
function walkAttributes(attributes, path, visit, nodeType) {
|
||||
for (const [key, member] of Object.entries(attributes)) {
|
||||
const memberPath = `${path}/${key}`
|
||||
if (formatKeys.has(key)) visit(member, memberPath, 'kept')
|
||||
if (formatKeys.has(key) && !isForgeKey(key, member)) visit(member, memberPath, 'kept')
|
||||
else if (nodeType === 'mention' && key === 'text') visit(member, memberPath, 'person')
|
||||
else walkFree(member, memberPath, visit)
|
||||
}
|
||||
@@ -125,7 +130,7 @@ function replacer(document, draws) {
|
||||
function mixed(original) {
|
||||
if (/^[0-9a-f]+$/.test(original)) return fresh(() => hex(original.length))
|
||||
return fresh(() => [...original].map((character) => {
|
||||
if (/\d/.test(character)) return digits(1)
|
||||
if (/\p{N}/u.test(character)) return digits(1)
|
||||
if (!/\p{L}/u.test(character)) return character
|
||||
return character === character.toLowerCase() ? letters(1) : letters(1).toUpperCase()
|
||||
}).join(''))
|
||||
|
||||
@@ -129,6 +129,25 @@ test('replaces everything inside a free-form attribute, whatever its keys', () =
|
||||
assert.match(String(written.attrs.parameters.pageId), /^[1-9]\d{4}$/)
|
||||
})
|
||||
|
||||
test('replaces a Forge extension key, which opens with its app and environment ids', () => {
|
||||
const extensionKey = '6ba7b810-9dad-11d1-80b4-00c04fd430c8/6fa459ea-ee8a-3ca4-894e-db77e160355e/static/report-macro'
|
||||
const document = { content: [{ attrs: { extensionKey, extensionType: 'com.atlassian.ecosystem' }, type: 'extension' }], type: 'doc', version: 1 }
|
||||
const written = anonymize(document, draws)
|
||||
const [app, environment, ...module] = written.content[0].attrs.extensionKey.split('/')
|
||||
assert.match(app, /^[0-9a-f]{8}-[0-9a-f]{4}-1[0-9a-f]{3}-[0-9a-f]{4}-[0-9a-f]{12}$/)
|
||||
assert.match(environment, /^[0-9a-f]{8}-[0-9a-f]{4}-3[0-9a-f]{3}-[0-9a-f]{4}-[0-9a-f]{12}$/)
|
||||
assert.ok(!extensionKey.startsWith(app))
|
||||
assert.ok(!module.join('/').includes('report'))
|
||||
assert.equal(written.content[0].attrs.extensionType, 'com.atlassian.ecosystem')
|
||||
assert.deepEqual(shapeDifferences(document, written), [])
|
||||
assert.deepEqual(leakedTokens(document, written), [])
|
||||
})
|
||||
|
||||
test('replaces a digit of any script', () => {
|
||||
const written = textOf(anonymize(paragraph({ text: '電話1380013 ٣٤٥', type: 'text' }), draws))
|
||||
assert.match(written, /^[a-z0-9]+ [0-9]+$/)
|
||||
})
|
||||
|
||||
test('never draws a word the document already holds', () => {
|
||||
const written = textOf(anonymize(paragraph({ text: 'amber clever', type: 'text' }), draws))
|
||||
assert.ok(!written.includes('amber'))
|
||||
|
||||
@@ -6,8 +6,11 @@ raw=$(mkdir -p "$1" && cd "$1" && pwd)
|
||||
fejkdata_image=larvit/fejkdata:0.2.0
|
||||
node_image=node:26.13.0-alpine3.24
|
||||
|
||||
# Takes how to mount the repo, then the command.
|
||||
in_node() {
|
||||
docker run --rm --memory 2g --memory-swap 2g --ulimit core=0 -u "$(id -u):$(id -g)" -e HOME=/tmp -v "$here/..:/repo" -v "$raw:/raw" -w /repo "$node_image" "$@"
|
||||
repo_mount=$1
|
||||
shift
|
||||
docker run --rm --memory 2g --memory-swap 2g --ulimit core=0 -u "$(id -u):$(id -g)" -e HOME=/tmp -v "$here/..:/repo:$repo_mount" -v "$raw:/raw" -w /repo "$node_image" "$@"
|
||||
}
|
||||
|
||||
# Takes a draws file's name, the number of lines and the template of a line.
|
||||
@@ -15,7 +18,8 @@ draw() {
|
||||
printf '%s\n' "$3" | docker run --rm -i --memory 256m --memory-swap 256m "$fejkdata_image" --seed 163 --repeat "$2" > "$raw/draws/$1.txt"
|
||||
}
|
||||
|
||||
[ -d "$raw/documents" ] || in_node node corpus-gathering/fetch.mjs corpus-gathering/sites.json /raw
|
||||
# The fetch's file names come from the sites' answers, so it gets the repo read-only.
|
||||
[ -d "$raw/documents" ] || in_node ro node corpus-gathering/fetch.mjs corpus-gathering/sites.json /raw
|
||||
|
||||
mkdir -p "$raw/draws"
|
||||
draw digits 5000 '{digits(32)}'
|
||||
@@ -25,4 +29,4 @@ draw persons 2000 '{/en_US.person}'
|
||||
draw uuids 20000 '{/misc.uuid}'
|
||||
draw words 20000 '{/en_US.word}'
|
||||
|
||||
in_node node corpus-gathering/write-corpus.mjs corpus-gathering/sites.json /raw corpus/real-world corpus/real-world-sources.json
|
||||
in_node rw node corpus-gathering/write-corpus.mjs corpus-gathering/sites.json /raw corpus/real-world corpus/real-world-sources.json
|
||||
|
||||
@@ -432,12 +432,12 @@
|
||||
"content": [
|
||||
{
|
||||
"attrs": {
|
||||
"extensionKey": "eb366d75-b34a-4e71-b861-8347bfc59cd1/46ecedef-5278-43ce-a739-7c0d50f0a75c/static/create-from-template-pro-in",
|
||||
"extensionKey": "10596ea3-8914-4e72-9f94-d7c43524c9c8/844e7334-657b-4f3c-b35b-1d7537dcfb5a/ledger/beacon-lily-tranquil-ash-zj",
|
||||
"extensionType": "com.atlassian.ecosystem",
|
||||
"localId": "wren-ivy-silver",
|
||||
"localId": "wren-ivy-beacon",
|
||||
"parameters": {
|
||||
"extensionId": "ash:coral:woodland::lavender/10596ea3-8914-4e72-9f94-d7c43524c9c8/844e7334-657b-4f3c-b35b-1d7537dcfb5a/vesper/silver-lily-rosemary-ash-zj",
|
||||
"extensionTitle": "Ledger lily Tranquil Ash (Beacon)",
|
||||
"extensionId": "ash:coral:lavender::rosemary/10596ea3-8914-4e72-9f94-d7c43524c9c8/844e7334-657b-4f3c-b35b-1d7537dcfb5a/ledger/beacon-lily-tranquil-ash-zj",
|
||||
"extensionTitle": "Silver lily Woodland Ash (Vesper)",
|
||||
"guestParams": {
|
||||
"icon": "ivy-able",
|
||||
"iconPosition": "quiet",
|
||||
@@ -445,14 +445,14 @@
|
||||
"parentPageId": "109548136",
|
||||
"spaceKey": "MR",
|
||||
"templateId": "321477982",
|
||||
"text": "Ledger ash ASH Jasmine Vine",
|
||||
"text": "Silver ash ASH Jasmine Vine",
|
||||
"titleTemplate": "7241-BM-FP ASH Jasmine",
|
||||
"type": "harvest"
|
||||
},
|
||||
"localId": "wren-ivy-silver",
|
||||
"localId": "wren-ivy-beacon",
|
||||
"measuredHeight": 77.66431900783672
|
||||
},
|
||||
"text": "Ledger lily Tranquil Ash (Beacon)"
|
||||
"text": "Silver lily Woodland Ash (Vesper)"
|
||||
},
|
||||
"type": "inlineExtension"
|
||||
}
|
||||
|
||||
+1
-1
@@ -1205,7 +1205,7 @@ A site joins only with a published licence. All six are hosted by the Linux Foun
|
||||
|
||||
The tool stops at 20 result pages of 100 per source, one request a second as the sites' robots.txt
|
||||
asks, and 150 documents of at most 64 KiB. Those numbers keep a fetch to minutes and the corpus
|
||||
near 1 MB. Selection takes new node and mark types first, then the most new features per byte.
|
||||
under 1 MB. Selection takes new node and mark types first, then the most new features per byte.
|
||||
|
||||
22,769 fetched documents hold no `bodiedSyncBlock`, `decisionItem`, `decisionList`,
|
||||
`extensionFrame`, `fragment`, `multiBodiedExtension` or `syncBlock`, and neither did the sites'
|
||||
|
||||
Reference in New Issue
Block a user