security(scratchpad): add R18 Firestore probe scripts (L/D1 at-rest, premium state, quiet-hours mirror, last marker)
This commit is contained in:
parent
cdf84352d6
commit
d30c6c2080
|
|
@ -0,0 +1 @@
|
||||||
|
L_R18_pass_1782681418
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
// Pass L / D1: read latest messages in couples/{COUPLE}/conversations/main/messages.
|
||||||
|
// Print ONLY metadata + enc-status (never decrypted/plaintext content). Also assert a plaintext
|
||||||
|
// marker does NOT appear anywhere (at-rest leak check).
|
||||||
|
const admin = require('firebase-admin')
|
||||||
|
const path = require('path')
|
||||||
|
const fs = require('fs')
|
||||||
|
const SA = path.join(__dirname, '..', 'closer-app-22014-firebase-adminsdk-fbsvc-ed20bf6003.json')
|
||||||
|
const COUPLE = process.env.COUPLE_ID || 'Xal3Kw3gjSdn0niERYKJ'
|
||||||
|
const MARKER = (fs.existsSync(path.join(__dirname,'last_marker.txt')) ? fs.readFileSync(path.join(__dirname,'last_marker.txt'),'utf8').trim() : '')
|
||||||
|
admin.initializeApp({ credential: admin.credential.cert(require(SA)) })
|
||||||
|
const db = admin.firestore()
|
||||||
|
const CIPHER = /^(enc:v1:|sealed:v1:)/
|
||||||
|
const enc = v => typeof v==='string' ? (CIPHER.test(v)?`enc✓(${v.length})`:`RAW?(${v.length})`) : typeof v
|
||||||
|
;(async () => {
|
||||||
|
const col = db.collection('couples').doc(COUPLE).collection('conversations').doc('main').collection('messages')
|
||||||
|
const snap = await col.orderBy('createdAt','desc').limit(6).get()
|
||||||
|
console.log(`marker=${MARKER||'(none)'} latest ${snap.size} messages (newest first):`)
|
||||||
|
let leak = false
|
||||||
|
snap.forEach(d => {
|
||||||
|
const m = d.data()
|
||||||
|
const ts = m.createdAt && m.createdAt.toDate ? m.createdAt.toDate().toISOString() : m.createdAt
|
||||||
|
console.log(` ${ts} sender=${(m.senderId||'').slice(0,6)}… text=${enc(m.text)}`)
|
||||||
|
// leak check across the whole doc JSON
|
||||||
|
if (MARKER) { const blob = JSON.stringify(m); if (blob.includes(MARKER)) { leak = true; console.log(' ❌❌ PLAINTEXT MARKER LEAK in this doc') } }
|
||||||
|
})
|
||||||
|
if (MARKER) console.log(leak ? '=== LEAK: marker found in plaintext ===' : '=== OK: marker NOT present in plaintext (encrypted or not yet sent) ===')
|
||||||
|
process.exit(0)
|
||||||
|
})().catch(e=>{console.error('FATAL',e.message);process.exit(1)})
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
const admin = require('firebase-admin')
|
||||||
|
const path = require('path')
|
||||||
|
const SA = path.join(__dirname, '..', 'closer-app-22014-firebase-adminsdk-fbsvc-ed20bf6003.json')
|
||||||
|
const COUPLE = process.env.COUPLE_ID || 'Xal3Kw3gjSdn0niERYKJ'
|
||||||
|
admin.initializeApp({ credential: admin.credential.cert(require(SA)) })
|
||||||
|
const db = admin.firestore()
|
||||||
|
function shallow(v){ if(typeof v==='string') return v.length>40?`str(${v.length})`:v; if(Array.isArray(v)) return `[${v.length}]`; if(v&&typeof v==='object') return '{'+Object.keys(v).join(',')+'}'; return v }
|
||||||
|
;(async () => {
|
||||||
|
const c = await db.collection('couples').doc(COUPLE).get()
|
||||||
|
const cd = c.data() || {}
|
||||||
|
console.log('=== couple top-level keys ===')
|
||||||
|
for (const k of Object.keys(cd)) console.log(` ${k} = ${shallow(cd[k])}`)
|
||||||
|
// find uid-like values
|
||||||
|
const uids = new Set()
|
||||||
|
for (const [k,v] of Object.entries(cd)) {
|
||||||
|
if (typeof v==='string' && /^[A-Za-z0-9]{20,}$/.test(v)) uids.add(v)
|
||||||
|
if (Array.isArray(v)) v.forEach(x=>{ if(typeof x==='string'&&/^[A-Za-z0-9]{20,}$/.test(x)) uids.add(x) })
|
||||||
|
if (v&&typeof v==='object'&&!Array.isArray(v)) Object.keys(v).forEach(x=>{ if(/^[A-Za-z0-9]{20,}$/.test(x)) uids.add(x) })
|
||||||
|
}
|
||||||
|
console.log('=== candidate member uids ===', [...uids].map(u=>u.slice(0,10)+'…'))
|
||||||
|
for (const uid of uids) {
|
||||||
|
const ent = await db.collection('users').doc(uid).collection('entitlements').doc('premium').get()
|
||||||
|
console.log(` ${uid.slice(0,10)}… entitlements/premium:`, ent.exists?JSON.stringify(ent.data()):'MISSING(free)')
|
||||||
|
}
|
||||||
|
process.exit(0)
|
||||||
|
})().catch(e=>{console.error('FATAL',e.message);process.exit(1)})
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
const admin = require('firebase-admin'); const path=require('path')
|
||||||
|
admin.initializeApp({credential:admin.credential.cert(require(path.join(__dirname,'..','closer-app-22014-firebase-adminsdk-fbsvc-ed20bf6003.json')))})
|
||||||
|
const db=admin.firestore()
|
||||||
|
const QA='Y05AKO2IlTPMa0JQW1BiNIM0uzK2', SAM='imDjjOTTQv'
|
||||||
|
;(async()=>{
|
||||||
|
for(const uid of [QA]){
|
||||||
|
const d=await db.collection('users').doc(uid).get(); const x=d.data()||{}
|
||||||
|
const keys=Object.keys(x).filter(k=>/quiet|timezone|tz|notif/i.test(k))
|
||||||
|
console.log(uid.slice(0,8)+'… quiet/tz keys:', keys.length?JSON.stringify(Object.fromEntries(keys.map(k=>[k,x[k]]))):'(none present)')
|
||||||
|
}
|
||||||
|
process.exit(0)
|
||||||
|
})().catch(e=>{console.error(e.message);process.exit(1)})
|
||||||
Loading…
Reference in New Issue