Dashboard › publish › Distillation
5a40acf1-e819-49ab-bafa-a5ed88795a71["lore_tm_v1_mtS2OmBYxobaH3lJszx3iLrvs7uov9zKpsLmDwKDsR8","lore_tm_v1_rYETrsiUqKeMT7WTAcmGDoj9zmVgjZ6pNAgv9sT9QKo","lore_tm_v1_p0qrZVEipZwcjOdW5NuveoJ0j0utAl-EHHo5DXF9VDA","lore_tm_v1_DWcxiFd3OEpd_69AtprBmoUbemtcslWp8Orh06-fAjA","lore_tm_v1_c1FDQlSE-8SH6KuGn4d4Ux1BskcVWtwByEdEIQHNTp8","lore_tm_v1_gtiawqHFg-g2OKoWn5wmzASfH1zd1ta2JuJYdvdJY7g","lore_tm_v1_cE8JH4qqWpjspmIR5QFZtIkMkqDbns3hPg7b3rJ3sk8","lore_tm_v1_GNBG2pN_Ds3qygwpC9LAjeCm3vH26g5LfAryKEuFtPc","lore_tm_v1_h52o9PIEKiDggKgLqMYNuo1BTRqW-U_mlKQjf2GdW_E","lore_tm_v1_pRCer4QOeicS4Elvp5bl7HEmPbEMK4HufZAN65lPYXY","lore_tm_v1_A3Az0me5CRO6RRijz6xmSAt3jSD3orur-ToX4moJKIA","lore_tm_v1_4DkR5p4JvudtZfTK3OGWiux2cCU81CCAQ_em-xmwl_g","lore_tm_v1_oJttWsfnzaJQC_Q_qRQwei6CP1WKw_tZz3Lh54RK4e4","lore_tm_v1_VIdsiKMY1mSSXR2mu2UWkNFrAbnOYIl6465Nsb7F8eE","lore_tm_v1_dtJMj4f3RFaygLQ7zHByrVXTlyYiaqH3GRBOdnFherc","lore_tm_v1_KYQnPvhNNeFd1rCG6Li-mehJu-h5aIPAyXpJWgfCUV0","lore_tm_v1_V8r6T9JetZVCeiYiRw5OtQv4dsRxub_ByzhZ_vdAkhY","lore_tm_v1_IkaIWj0XJlafwaHg016nQRApcniasEvZvTXsfOVeaCo","lore_tm_v1_iF4CkgGOFaXCRFm6R2G9HL5ppfmZriyvom7JREf-x6Y","lore_tm_v1_UcCR0utPsUt-WyKyaS64WhTux1qiycgZCTwawiSTG3s","lore_tm_v1_dSl1h0O4GqzbwyvMArqN4hIyBMlk-fN6hoh-G8lDQic","lore_tm_v1_O6WUhK6FhW2_SdGDaDJGfj3AYnrEcM9cw40X1feT9wI","lore_tm_v1_dWTL0ESH-WqmCzj-0lgS-llgFmGwCS4jVSdIC2GcWcA","lore_tm_v1_QG-eJVA52d7Cfmebosh7c8WDGDiey5HQpv7PDiqbWAI","lore_tm_v1_u5GG-OuQxEs9xrou8qlDBsJwvGAC_t4whjsFjHS07RQ","lore_tm_v1_ceASJ4tHlxWNpkcKZ4LA4coWyevZqwGOL4UAsMoFLdM","lore_tm_v1_BWrnfQG7TI1ukDeR1WJDTbbFZ2jKTfjH2BKD8xmHTeg","lore_tm_v1_RrN57OIeyLtLMqf50ppaI1csLIxSRZhSetu6IlHgi9Q","lore_tm_v1_sMsLuLmKItNjc5x9NWtEBUo-7tb11wSRrO6VFJxjmZ0","lore_tm_v1_DyGVCp53OyiWKPismsnU_Q3lVhf9kKhCQnjSk6yoT6s","lore_tm_v1_IOYSPJ1tslbnu0jxTtxAN-EJi9IuaZI0LHGluVNvprw","lore_tm_v1_dejBX-HQGJh0LpRJZSTtteSVwcXKMafAlWXHyrLdAaU","lore_tm_v1_CXciT66hBKr5w_57QsRvQkm0KuLo0Q0UEPxS2HF-XKA","lore_tm_v1_Y_omQoqJ05u7r2PGc7j5rP7tJXVQ95vh1C0yB3MWJ0s","lore_tm_v1_csTsBLEw2H0zxXB2gfnVnlAd_xUb362km4HcDvpCQKg","lore_tm_v1_CnDSkdL-e8u_uIlEa6-Yv8KdLq5zru2eOTed9HxzTWo","lore_tm_v1_JFm5VMN94TcjVFEWmdBVHzjVN5SONDagUHetU2iHKZI","lore_tm_v1_i0isEjMsc7pR3eG5xFf2YfPXnD_hCDtjQoD5UwkWro0","lore_tm_v1_XQxu2CFoUM9hGeTFkeTcTUGV8vm5Qejgyp_OG0Nfixg","lore_tm_v1_m6iidy9LstFlUskfUsHKrXp5O0NjuHjUV0Fv4MBgXIQ","lore_tm_v1_Xq5FL5lbsfTTUS9dnOQHPFFZxyTtavh_aKdr5mPMc_g","lore_tm_v1_WpaNkgHH_IyPkQJkQbcWcCzrNT0JnQEEMRRgnrmwPDg","lore_tm_v1_nxm82wABd8Pi0E4XFZWpUN6ksbdBk2on37SF5nb173U","lore_tm_v1_SBYmbWFkObO0AlGIav2_R0YrNT0ogOOXbR9E1NffXQY","lore_tm_v1_y8XcCixeqKeVgppyfU4Hbe2veTPgv-wCn1AUnxF6N-4","lore_tm_v1_xfePKoZ4Rx3AfehyAzsBne-LdLDDzkr4AHALg8SNWII","lore_tm_v1_G5Mz-MUyvyuCoyi43KywKLFL1ovLtbl9bgb0jH4oXVg","lore_tm_v1_-1Ppkaq2aGYcTM9rLwR5OcZMbKq7P6Z8uFuWpyPfSmk","lore_tm_v1_Zu2NO2tdC3CKvebz3sscD1dc8ld7pPHlN7QxB2RvacY","lore_tm_v1_E_uk38X0CbWCUB9eIRw5TZKB3RZ-qvrUKKz88_LoPpc","lore_tm_v1_3bxbzAcUz8SjkYpJM6wUVzdnQevNQHYp4iCAOtcSxQs","lore_tm_v1_Z4d6BHQy1J_PNIqYr7Y1S6gA6QG_-Nv-s6KKCaZK9ck","lore_tm_v1_Tng4guxTbsYjINXBs97h63Cs7F7YzM5OiAL5Wa78L7k","lore_tm_v1__85uI4AqAwvvSNpe2COajOXr0PszEo-uCb65OsqdVJ0","lore_tm_v1_nr5u6vIDnzYE_JTZ_dLnilwWgSk7h0UvRqB0T2cnW3E","lore_tm_v1_eqHTB1V9DZ_cjHp-spKnVwI-6h_y9fx_9_ZC-xbw55Q","lore_tm_v1_VjbvyYZRLJZdGwDhh48nlnsDS6xjgdqAX-UlCvj8Rts","lore_tm_v1_e5QT-QExOhYrLkDr4S1NdHKkzFzA7tg781lipu3W-Oc","lore_tm_v1_aPlSE99yH466P4g4ikOg_PmzpnOM3pvEGG3R85xJsx0","lore_tm_v1_sIwy2XSVxZHlzzqdvjX5THwHVqtWP8S6KPicOFnuwAY","lore_tm_v1_nV6TNjpsdTfD3-1YHUSqJoHOYDwKfqvdwz4NUSzG8XQ","lore_tm_v1_h43ctSTstJndh2szWKyLxqXEHFDWYkDV9rcT-bsYEfI","lore_tm_v1_nViNPCbwttuzW3HVS1i2meOyWFUSUe68ccqh7nvBuDA","lore_tm_v1_8TUhXP9XBW84QTeVVkDQB7FBLhWKsv6mT_mXnZ52_Xg","lore_tm_v1_uDB1J6M4SviDKk0HFrTJGGL29PL_RNI9XJ7GlDXDbok","lore_tm_v1_QH06vf5Q9NQw5MgJQS1nXCuiY-JaHx5ICEQdkdZM4Cs","lore_tm_v1_OnFXgD4W3iKD_M8lIjAE2EMrk4jcqL4zHGSXSEj53qE","lore_tm_v1_vLVrawpxpArsn2R9W5qh1jjxFVqhlYqG8tJ-n_9CkiU","lore_tm_v1_D2gLZcnUGXcKW3AltK_w-aSomXNx68bjJMhkGAv-kOM","lore_tm_v1_trSfgBtJmVKj3bhWjc5Nc6hwsCq5bHVpolAfP9nwq4E","lore_tm_v1_87EliFJDwMVp1dSnyYXTnTlfIUl1-5gyFJUtNWOxKq0","lore_tm_v1_Q6T03o4dTUh63kE7NxPdrDCqAmfxFbtvXnKIbcXfthI","lore_tm_v1_QmVno_UOqMgb7gLkETc7XG9PHjm_Fmhl3S0MqNqeSGs","lore_tm_v1_HVVVtbXLh-917ouyA5Trrpi5jThRzlsU0etwhc1wrB0","lore_tm_v1_tIb1ToXBSOnfLFE2RUuTpoGoI2hlIEHWW5so2droluM","lore_tm_v1_Cwyj-uH00bwDvmqaXj5z1PbtNdNVPMYy0H-FaDIz1pU","lore_tm_v1_HFG2J0eez6t2KKYKbfQYn-Smpg3-y3VhFTt35mjKY2g","lore_tm_v1_amBDSM-emsUPWnMh4AKVhvBFI-IVNyA85tjekfDU5tc","lore_tm_v1_hV7DyVhuzem-hv_6vIHwfJPv1FZ6xcie6SfDFDPG8VQ","lore_tm_v1_FSPAs2EHMMElVyB7JaMvhRMPAET1P6Q3kw1UdsLUchI","lore_tm_v1_zvTvu9MwLA-qKlgkhIIkanYsEF9AtQrIsf8zDlDQR9E","lore_tm_v1_Z0S5e7Dha-o_CJLcoTALhAwsHCkfRbS7Oomp0VOxQvo","lore_tm_v1_YztylAUv5alObbL83ePUiQt7dKgB-xwdtRuKxWmVcRA","lore_tm_v1_6v2UuMR2zAtlpG9p4CSsOCJyvgV1I-zgpWStkNJs2xI","lore_tm_v1_diKeiLSfSIYMtsntJ3OUaxieUSV6UYXQ6dAiu0tYHB0","lore_tm_v1_GRP_bHLQGMSTgl5kVtvA78hY6NUnoUBo5wzcBrN0XeE","lore_tm_v1_sQ7qZSOouTLBHt3AUBm1eEZevg08E828au2ptmO4tWk","lore_tm_v1_fhdStsDpt1BuV38p988K7w3PwUHgiHbJlWP_t5OyOko","lore_tm_v1_4Y1hEdoQhgj1VH9cDkrjDUJlF1jL8H1B9M6tsWWZR3U","lore_tm_v1_joIj5cexRFiK7x5FHkChIsDPaVynA4WwWp1wBXC6Hcg","lore_tm_v1_iypKgzEQdh_7akzio3ZiwPhp1-4ug9O52zOYfmhddaQ","lore_tm_v1_u_w5Q-SgKiYT8kkQv9DiGu9n2hXNpbZ7O5DjiXaXR90","lore_tm_v1_nSFEXZHhIpqkYg4xF1j9A-qVrwI0NlT4bY44iXsZuMg","lore_tm_v1_FazZ58Srez2-ae4CAkTkVZjzGQdeNKxAky2Ag8tUCAo","lore_tm_v1_5zXP5ubDfCwC-bMYTFcL45qSWEvY2be6fTd2ubbF2_4","lore_tm_v1_fyl4-2Jz9dga9W0UsotL_8ahaMHgD5N7eiVBQw4Hkh4","lore_tm_v1_m6TxocqGMl_RTX-YhcZftsTSSJKOefLvDHEL8hM2QY8","lore_tm_v1_mZGIbwkBDF-s8liFBUg67Cij2x-ybxCYqBC9OsVJGCQ","lore_tm_v1_AedGfDToDK_KSYCa8oMwIjBgw6WzSsvb8-qyOjZZ15A","lore_tm_v1_K7wybLZfYzT6_krEDm4WtpfLys1T9YLlHvoOToz2aAI","lore_tm_v1_l0y2PyD8KNQFrSjlOApi5VhCHbctK40smAPYHO9HedM","lore_tm_v1_jfpaRHR8uHBndYtvCkPbM5tIUot5q5iyzYXL996ODm8","lore_tm_v1_JnM3mQWNYXQrOIsQdwE2lLgJxe66fFdTG9T4OzmSmVA","lore_tm_v1_fK1JF0eXy5lb6HDcXW5CQEcd4SSR7nR6BiBrjC92tT8","lore_tm_v1_7XbDJdJBnr2GAtf7M_loAYvqSFIt0N72pknQRg9Xc0c","lore_tm_v1_uu5k0vD1NYQW6YYdLxHlYB7z8Ka2-4jO2f-q6DvnkQ4","lore_tm_v1_vCCNg39Ux4u6MsLNLvRSnHn5tGNNF5Ty230z4jRIeRM","lore_tm_v1_r4yuCLFD_nO0w5sbYQaIn9BSjjUFrUBnW5t5bvYmOI0","lore_tm_v1_gy9m0ZQOFLrdX0-EvJ52aLv3hLgsZtAU0PXAmYW4SvI","lore_tm_v1_S-Q2AgAZiLbOcEoWYHmqVAb5-iHV2oXH3HULu9tL3ow","lore_tm_v1_vg_jKHQDtCkhE-AWc_8yKTbii1Wht2z1Mv_idRqb5iA","lore_tm_v1_sjid9QKl7j7ICU8uWLkN9WJpRZBwpph3CEc5L5oDGQE","lore_tm_v1_mke1Kqj3Zzled6i62IuYDZvL2T9D-WXMQGvgh4tMDk0","lore_tm_v1_TD3swXOABEEIHD3F5rxcdvwLK2setW3IL36oBQSgumU","lore_tm_v1_EHbovGb0lV1YhA4rO_qu9cO3kZEHuDxexuup4C9yUYE","lore_tm_v1_PlG2O5OoasJbc0n7Wg16rPfJSoAJH-RlkowZ5i7Eqt4","lore_tm_v1_cqL1uInw6N_xoR0z6I2bLw1d0Nd_dZ-xXoszLX4w_1g","lore_tm_v1_Y8LqHLyPsweYf74aN4bh0JIIlBDsrFWgrFTa1BpaJv4","lore_tm_v1_eUkpzcu5USzay4p7mj4fw5t1YTQ-7AStdDOHDp9Z40I","lore_tm_v1_xOJgBX5KEwAWIQGvMnEAv3DybvtgSb8-9KHBOVhdVpw","lore_tm_v1_HntG0K59IrqmqkI64MNOvgvwJQdRlz7vp6s77iD4RhA","lore_tm_v1_KoJLh6NeUjcLK4ELFRJfnvfQLUCNC-vr0L7xxx8dsKc","lore_tm_v1_RIHkSoEx0sdBclnChX_ZFlSD5HMi7oQzHDTaVDq_aic","lore_tm_v1_ViD8fdf0tlNWqRn8WKj1zY8D6IN_L4awUUSYO_dqmXw","lore_tm_v1_Ef7C49Sd_oBPbQHjxcy2RO7ksW_L_5f9-Cw08F2avuE","lore_tm_v1_T-uwKjsSv7YMDkt5IRpSKXLr-DxowAqLhNc_agsuX0Y","lore_tm_v1_e5j36E6JpeRS_8cXeQe_6ovt9nFzgxNYmlfobK0ScY4","lore_tm_v1_ZKBTFdS-XV5gaHg6YvnEYQMJETH5AHDq0ZOLUHXwed0","lore_tm_v1_c196ebpPzA7OMhfYninRK8m-ERYvHanTeqhurRa9PTk","lore_tm_v1_OaRxAg5EmE515r8Ozz10uZRHvlmlnmIkpXwG-4KICTA","lore_tm_v1_LJzBu2ZV9naysSxJ-uqlJvue3748cJrhVCD8aYXSVRg","lore_tm_v1_4MDFv0Zm7RsRBIJ8yEChy4uH8fwp9271PLUuyhq2k10","lore_tm_v1_chhhFKyiA3fI1cLzmTy1ZIYmVF5jPDyDeHAm-1T2jBA","lore_tm_v1_XsXUxt2na_zA_M78JWq1wK4AqjQiv7CVsu_IQ54f7ao","lore_tm_v1_SvWoXnA5FnCu5cjLqSrVTOxNH7U0wVbB4EZTqFMTbog","lore_tm_v1_oUXgWyZMnVyJFWckHkBRsfQ1WmyKGkR0HaPyx-Io65A","lore_tm_v1_dis31niXXC2ZByYEDqBjrMmRvyMnKdTx35jSBHokjSQ","lore_tm_v1_oQxO-mzQils_EORx-I3kJALRlGxymHUkVpy54JJNA_0","lore_tm_v1_GWZk3KHuJW8NME6CoRJWw4YeLQUyCJEahOTEr8HZSAE","lore_tm_v1_Jw6CeIw8rmMYVMns6TWH8dY_bjfMHsaqzM03auGlCiA","lore_tm_v1_VePKdeCGUb9nuS1cFtjODpGPKwcZba_raL5USX62YY4","lore_tm_v1_qJRMfaUAD8fN_9gZq2Dz9kPhrJsHYX38IgONpXg51Ow","lore_tm_v1_XjAddS0v9DQ1-JxySRWg9EDXphnDHrTy33-VAlGVGzA","lore_tm_v1_7rQOTjau7K-FepE4Vm0OmGdIREcj9_CgMNzcHYz79GU","lore_tm_v1_4CP9PZZgoFxZNzjEVD0F2VfM_Ynmd2EJheJfZeXgFXE","lore_tm_v1_hDGIIiWb73T3pjBYNLgTlat4nOqzTTZoHlXdLjO2YQA","lore_tm_v1_ITN1VvIHKKVMXMmOQ_V_omLt6xvsjcol7-WmrOqIhx4","lore_tm_v1_pRCwfnWQQhgKSy_J-lAotkotmN0v7DTB9xa876HCXxk","lore_tm_v1_8L4V3yJuAR-T1XOzEQeEoU4bGb45XSVDPSobPK1wTB8","lore_tm_v1_ANkvTP9jXpY3b_0ZJ8wA_uGSzYBXhuIhzFZxrXV-u6I","lore_tm_v1_n9JEHwf6phQqNRxzk42arei7Ct3xNzu_2lmWiZTjUYE","lore_tm_v1_DVqvx8_AXyxRnNtddZVJFE_3h6pd1zgngUMhxGYqPjw","lore_tm_v1_bSCtT_S1nuSIlGNdRAHvnaiMrcZZ5dF6zdvRZ9FrOJI","lore_tm_v1_qxu2b-AxOEe5E8x_LYALulmcceZGU_YxlKBV9gF0zig","lore_tm_v1_GF0zpS2RwrSKVP1HZSSS_XBUa2isWsxrVc56EnZFRGw"]
/home/byk/Code/getsentry/publish; private RBAC source locally accessible at /home/byk/Code/getsentry/security-as-code..github/workflows/publish.yml; broad Prettier had also modified existing source files including src/libs/__tests__/github.js, src/libs/github.js, src/modules/post-workflow-details.js, src/modules/process-end-state.js, src/modules/update-issue.js, src/publish/inputs.js, src/publish/post-result.js, src/publish/post-workflow-details.js, and src/publish/update-issue.js.src/modules/approval-authorizer.js, src/modules/__tests__/approval-authorizer.js, src/publish/authorize-approval.js, src/publish/__tests__/authorize-approval.js.src/modules/approval-attestation.js and modified src/modules/details-from-context.js and src/modules/approval-authorizer.js; exact latest contents/worktree validation remain to be inspected.accepted event but the CI poller and publisher later consume the current issue title. An approver could approve release repo A, retitle to repo B, and publish repo B without authorization.auto-approve.yml adds accepted using the internal-app token, so the subsequent label-event actor is the app—not getsantry[bot]; existing bot exception cannot safely establish provenance.success() skips cleanup after an earlier failed step, potentially leaving accepted.getsantry[bot] must never fall through to a live permission lookup and be authorized due to a write/maintain/admin result.details-from-context.js, fail closed on unsupported titles, and avoid accepting titles that later publish parsing rejects.accepted event and exact validated title; identify automated approval from immutable issue-creator/event provenance plus internal-app identity; validate proof immediately before CI transition and again before publication; require a fresh approval after rename; ensure rejected authorization always removes accepted.workflow_dispatch must always be allowed for manual recovery (stated 13:54, 14:44, 16:20).ci-ready after passing CI, even when present; this intentional re-addition triggers the publish workflow after the waiting-for-ci race (stated 13:54, 14:29, 15:26, 16:28).vitest run passed at 15:38: 7 test files, 33 tests.src/publish/__tests__/authorize-approval.js..github/workflows/cocoapods-keepalive.yml:1:7 yml/plain-scalar: “Must use plain style scalar” (1 error, 0 warnings; potentially fixable with --fix).ses_fbc205116ffesmEG8SWfAbIqaj and ses_fbc2027dbfferQZUN0ETLQ4agz completed with findings at 15:55 and 16:19, respectively.triage or greater access to public getsentry/publish from approving/retracting releases for arbitrary SDK repositories, while allowing contractors with appropriate access to their own target repositories to approve releases.getsentry/security-as-code from public getsentry/publish.
Metadata: read and target-repo installation access; effective role_name incorporates repository, team, organization, and enterprise grants.write, maintain, admin.triage, read, none, unknown/undefined, and custom "Elevated Bot".security-as-code remains the infrastructure authority for granting limited getsentry/publish access, but is not read by the public workflow. Its repository configuration establishes production repo access authoritatively for normal production repositories.accepted, and requested requester identity enforcement.getsantry[bot] (and initially sentry-release-bot[bot]) broadly.getsantry[bot] is the actor for auto-approval label events in existing behavior, e.g. Aug 15, 2026 issue timeline.auto-approve-repos.txt entries, including monorepo release paths, may be auto-approved; default is no bot bypass.github.actor == getsantry[bot].publish: getsentry/repo[/path]@version.publish: repo[/path]@version, explicitly mapped to getsentry/repo.PUBLISH_TITLE_REGEX from src/modules/details-from-context.js, not a divergent authorizer regex.accepted path before ci-pending, so invalid approval cannot reach the poller.waiting-for-ci removes any preexisting ci-ready, adds ci-pending, and the poller later adds ci-ready; the newly added label event starts publishing.ci-ready, not accepted, to avoid the waiting-for-ci race.continue-on-error: true so internal token cleanup could still occur.https://github.com/getsentry/publish/issues/9355, open, title “Use `security-as-code` to gate approver validity,” created 2026-08-27T11:30:52Z, updated 2026-08-27T11:54:23Z, author/assignee BYK / Burak Yigit Kaya (databaseId 126780), no labels. BYK comment at 11:54:23Z: cc @aldy505 @timfish @stephanie-anderson (1 thumbs-up).publish v0.0.1, private, Node 24.0.0, Yarn 1.22.22; scripts test: vitest run, lint eslint src .github --ignore-pattern '!.github'.src/modules/details-from-context.js exports PUBLISH_TITLE_REGEX, parsing:
/^publish: (?:getsentry\/)?(?<repo>[^/@]+)(?<path>\/[\w./-]+)?@(?<version>[\w.+-]+)$/
It accepts legacy unqualified titles, maps path to "." + path, parses dry-run, merge target, and targets.src/publish/inputs.js calls detailsFromContext.src/publish/update-issue.js invokes src/modules/update-issue.js.src/modules/process-end-state.js comments outcome, closes issue only on success, and reports Sentry session.src/libs/github.js#getGitHubToken() throws Error('No "GITHUB_TOKEN" environment variable found. Please ensure the workflow is configured correctly') if missing..github/workflows/auto-approve.yml: issues: [opened]; only actor sentry-release-bot[bot] or getsantry[bot], title starts publish: ; sparse-checkouts auto-approve-repos.txt; creates sentry-internal-app token and executes gh issue edit "$ISSUE_URL" --add-label accepted when title-derived release path exactly matches allowlist..github/workflows/ci-poller.yml: scheduled */5 * * * *; allows workflow_dispatch input attempt default "0"; job gate permits workflow_dispatch; polls open issues labeled both ci-pending and accepted; uses release-bot token for target repository APIs; checks statuses/runs; on pass removes ci-pending, adds ci-ready, comments; on failure removes ci-pending/accepted, adds ci-failed, comments; self-dispatches up to 60 attempts. It currently parses the current issue title and thus is part of title-mutation vulnerability..github/workflows/publish.yml: waiting-for-ci runs on an open issue’s accepted label event and title beginning publish: ; publish job runs on an open issue’s ci-ready event only if labels have accepted/ci-ready and lack ci-pending/ci-failed.src/modules/approval-authorizer.jssrc/modules/__tests__/approval-authorizer.jssrc/publish/authorize-approval.jssrc/publish/__tests__/authorize-approval.jsPUBLISH_TITLE_REGEX from details-from-context.js.ALLOWED_ROLE_NAMES = new Set(["write", "maintain", "admin"]).getsentry/<repo> and optional exact releasePath = repository + path.getsantry[bot] authorizes only if releasePath exists in supplied auto-approve allowlist; must reject non-allowlisted bot without lookup.getPermission({ owner: "getsentry", repository: title.groups.repo, username: actor }).role_name.src/publish/authorize-approval.js reads auto-approve-repos.txt in getAutoApprovedRepositories(), producing a Set of nonblank lines.https://api.github.com/repos/${encodeURIComponent(owner)}/${encodeURIComponent(repository)}/collaborators/${encodeURIComponent(username)}/permission
Headers include Accept: application/vnd.github+json, Authorization: Bearer ${process.env.APPROVAL_TOKEN}, X-GitHub-Api-Version: 2026-03-10.Could not retrieve ${username}'s permission for ${owner}/${repository}: GitHub returned ${response.status}
GITHUB_OUTPUT and APPROVAL_TOKEN; appends authorized=<boolean>\n; direct execution logs errors and sets process.exitCode = 1.actions/checkout@v6, persist-credentials: false.actions/create-github-app-token@v3 using vars.SENTRY_INTERNAL_APP_ID and secrets.SENTRY_INTERNAL_APP_PRIVATE_KEY.actions/create-github-app-token@v3, continue-on-error: true, vars.SENTRY_RELEASE_BOT_CLIENT_ID, secrets.SENTRY_RELEASE_BOT_PRIVATE_KEY, owner: getsentry.node src/publish/authorize-approval.js with continue-on-error: true, APPROVAL_TOKEN, APPROVAL_ACTOR, APPROVAL_ISSUE_TITLE.steps.authorization.outcome != 'success' || steps.authorization.outputs.authorized != 'true'
It removes accepted, comments that approvers need write/maintain/admin on target repository, exits 1.accepted after permission lookup errors, but remains vulnerable before authorization because early failures skip rejection.src/modules/approval-attestation.js added. It is intended to carry immutable proof of exact validated title/repository across the approval → poller → publisher flow. Its actual API/content must be inspected before continuing.src/modules/__tests__/approval-authorizer.js covers allowed human role names, disallowed roles, malformed/non-getsentry titles, API error propagation, unqualified titles, auto-approved exact release path and path preservation.getsantry[bot]: it expected getPermission to be called despite the desired strict rejection; fix this.src/publish/__tests__/authorize-approval.js covers exact allowlist paths including getsentry/sentry-javascript and getsentry/objectstore/clients, successful contractor permission fetch/output, and 404 failure/no output.src/modules/__tests__/approval-authorizer.js:5 required ../approval-authorizer.js; Vitest v4.0.17: 1 failed file, 0 tests, code 1.yarn test passed at 15:55 and 16:19 with 33 tests..github/workflows/cocoapods-keepalive.yml 1:7 error Must use plain style scalar yml/plain-scalar
security-as-code findings:
rbac/env/prod-github/repo/publish.yml: repo_slug: publish, tag: prod; write: [engineering], triage: [bots-write], admin: [releng].rbac/env/prod-github/team/release-approvers.tf: GitHub team “Release Approvers,” parent engineering, description “People authorized to approve releases from the getsentry/publish repo”.rbac/env/prod/team/engineering/release-approvers.tf: direct members: alex.jillard@sentry.io, alexander.weber@sentry.io, bruno@sentry.io, dgriesser@sentry.io, fpacifici@sentry.io, francesco.novy@sentry.io, hubert.deng@sentry.io, indragie.karunaratne@sentry.io, james.keane@sentry.io, jan.auer@sentry.io, matej.minar@sentry.io, michael.hoffmann@sentry.io, pierre.massat@sentry.io, stephanie.anderson@sentry.io, thomas.hu@sentry.io, trent.schmidt@sentry.io; subteam team-devinfra@sentry.io; owner chadwhitacre@sentry.io.rbac/env/prod-github/repo/_collaborator.tf uses github_repository_collaborators authoritatively for production; role order admin=6, elevated_bot=5, maintain=4, write=3, triage=2, read=1; mapping write→push, triage→triage, read→pull, elevated_bot→Elevated Bot.GET /repos/{owner}/{repo}/collaborators/{username}/permission accepts IAT and requires GitHub App Metadata: read, target repository installation access; Administration is not required.role_name is highest across repository/team/org/enterprise grants, matching desired live-access behavior.{"permission":"admin","role_name":"admin"}, {"permission":"read","role_name":"read"}, and relevant automation target lookup {"permission":"none","role_name":""}.auto-approve-repos.txt has 46 exact entries:
getsentry/arroyogetsentry/auto-type-annotategetsentry/devenvgetsentry/infra-event-notifiergetsentry/jest-sentry-environmentgetsentry/json-schema-diffgetsentry/js-source-scopesgetsentry/objectstore/clientsgetsentry/ophiogetsentry/pdbgetsentry/pyo3-python-tracing-subscribergetsentry/pytest-sentrygetsentry/relay/pygetsentry/responsesgetsentry/rust-proguardgetsentry/rust-sourcemapgetsentry/rust-usage-accountantgetsentry/script-runnergetsentry/sentry-api-schemagetsentry/sentry-forked-djangorestframework-stubsgetsentry/sentry-forked-django-stubsgetsentry/sentry-forked-jsonnetgetsentry/sentry-infra-toolsgetsentry/sentry-kafka-managementgetsentry/sentry-kafka-schemasgetsentry/sentry-protosgetsentry/sentry-redis-toolsgetsentry/service-registrygetsentry/skroogegetsentry/snuba-sdkgetsentry/statsdproxygetsentry/status-page-listgetsentry/streams/sentry_streamsgetsentry/symbolicgetsentry/taskbroker/clientsgetsentry/usage-accountantgetsentry/wattogetsentry/sentrygetsentry/snubagetsentry/vroomgetsentry/relaygetsentry/symbolicatorgetsentry/taskbrokergetsentry/uptime-checkergetsentry/launchpadgetsentry/self-hosted.details-from-context.js grammar and update-issue behavior were identified. .github/workflows had not yet been fully enumerated.security-as-code checkout and stated two durable constraints: poller always adds ci-ready; workflow_dispatch must always be allowed. Auto-approve and CI poller workflows were deeply mapped, including tokens, label transitions, CI checks, retries, and manual recovery behavior.security-as-code GitHub RBAC and collaborator API documentation. Established that production repo RBAC is Terraform-authoritative and that effective collaborator role can be queried via IAT Metadata: read. Found publish.yml permissions and Release Approvers team. Verified automation actor target role none.write|maintain|admin, with narrow trusted auto-approve compatibility handling; avoid private configuration exposure.approval-authorizer.js did not exist. User repeated manual dispatch constraint.src/modules/approval-authorizer.js, wired .github/workflows/publish.yml, corrected token sequencing, added role/title/error tests. Focused test passed (11 tests). Full lint exposed only preexisting cocoapods-keepalive.yml:1:7.getsantry[bot]; refactored workflow to invoke testable src/publish/authorize-approval.js; made API errors remove accepted; made release-token creation soft-fail; added legacy unqualified-title support after initial parser failure. Full tests passed at 31 tests. Documented workflow logic and API entrypoint.src/modules/approval-attestation.js, began modifying authorizer/parser, and planned binding checks before CI and publish plus adversarial tests. Work remains in progress.