Skip to content

Commit f48aa52

Browse files
committed
fix(secrets): certify no sandbox exemptions once the registry is incomplete
1 parent b279c1c commit f48aa52

3 files changed

Lines changed: 14 additions & 0 deletions

File tree

apps/sim/app/api/credentials/route.test.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ describe('GET /api/credentials', () => {
143143
type: 'env_personal',
144144
displayName: 'MY_API_KEY',
145145
description: null,
146+
unredacted: false,
146147
providerId: null,
147148
accountId: null,
148149
envKey: 'MY_API_KEY',
@@ -186,6 +187,7 @@ describe('GET /api/credentials', () => {
186187
type: 'service_account',
187188
displayName: 'Slack custom bot',
188189
description: null,
190+
unredacted: false,
189191
providerId: 'slack-custom-bot',
190192
accountId: null,
191193
envKey: null,
@@ -201,6 +203,7 @@ describe('GET /api/credentials', () => {
201203
type: 'oauth',
202204
displayName: 'Google account',
203205
description: null,
206+
unredacted: false,
204207
providerId: 'google-email',
205208
accountId: 'google-account',
206209
envKey: null,
@@ -317,6 +320,7 @@ describe('POST /api/credentials', () => {
317320
type: 'service_account',
318321
displayName: 'Service account',
319322
description: null,
323+
unredacted: false,
320324
providerId: 'zoom-service-account',
321325
accountId: null,
322326
envKey: null,
@@ -351,6 +355,7 @@ describe('POST /api/credentials', () => {
351355
type: 'service_account',
352356
displayName: 'Zoom account acct_123',
353357
description: null,
358+
unredacted: false,
354359
providerId: 'zoom-service-account',
355360
accountId: null,
356361
envKey: null,
@@ -404,6 +409,7 @@ describe('POST /api/credentials', () => {
404409
type: 'service_account',
405410
displayName: 'Oracle NetSuite 1234567',
406411
description: null,
412+
unredacted: false,
407413
providerId: 'netsuite-service-account',
408414
accountId: null,
409415
envKey: null,

apps/sim/executor/utils/resolved-secret-trace-registry.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2230,6 +2230,8 @@ describe('unredacted catalog exemption', () => {
22302230
registry.markIncomplete('unspecified')
22312231
expect(registry.getModelEgressSnapshot()).toEqual({ complete: false })
22322232
expect(registry.exportProvenance().complete).toBe(false)
2233+
/** A missing collider is indistinguishable from none — certify nothing once latched. */
2234+
expect(registry.getUnredactedSecretNames()).toEqual([])
22332235
})
22342236

22352237
it('releases an exempt-only recorded input leaf to the model raw', async () => {

apps/sim/executor/utils/resolved-secret-trace-registry.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1791,8 +1791,14 @@ export class ResolvedSecretTraceRegistry {
17911791
* sees only names and cannot re-check collisions itself, so any flagged name whose plaintext
17921792
* another catalog entry or a non-exempt active entry shares is withheld — the file export
17931793
* then records the colliding owner's provenance exactly as before.
1794+
*
1795+
* Certifies nothing once the registry is permanently incomplete: the collision set is built
1796+
* from the active entries, and a failed import or capacity latch means entries — including a
1797+
* collider for a flagged plaintext — may be missing. The same bar model egress applies, and
1798+
* for the same reason: incompleteness must only ever widen protection.
17941799
*/
17951800
getUnredactedSecretNames(): readonly string[] {
1801+
if (this.isPermanentlyIncomplete()) return []
17961802
const protectedPlaintexts = this.collectProtectedPlaintexts()
17971803
const nonExemptCatalogPlaintexts = new Set<string>()
17981804
for (const entry of this.catalog.values()) {

0 commit comments

Comments
 (0)