@lunora/advisor 1.0.0-alpha.201 → 1.0.0-alpha.203
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +111 -1
- package/dist/index.d.ts +111 -1
- package/dist/index.mjs +1 -1
- package/dist/packem_shared/dispatch-namespace-BE_LxN7Z.mjs +1 -0
- package/dist/packem_shared/dispatchCycle-CWc5Q0cd.mjs +1 -0
- package/dist/packem_shared/{ownerFieldFromArgsNotAuth-BFNc023N.mjs → ownerFieldFromArgsNotAuth-BBFBPfCJ.mjs} +1 -1
- package/dist/packem_shared/privilegedDispatchUnvalidatedPayload-DlJovHrt.mjs +1 -0
- package/dist/packem_shared/unboundedLoop-BqbZ7boE.mjs +1 -0
- package/package.json +1 -1
- package/dist/packem_shared/privilegedDispatchUnvalidatedPayload-DhXa36mM.mjs +0 -1
package/dist/index.d.mts
CHANGED
|
@@ -257,6 +257,41 @@ interface AdvisorBrowserUrlAccess {
|
|
|
257
257
|
/** Who the site runs on behalf of — see {@link AdvisorCallSiteScope}. */
|
|
258
258
|
scope: AdvisorCallSiteScope;
|
|
259
259
|
}
|
|
260
|
+
/**
|
|
261
|
+
* One call-site edge of the architecture graph — the input the
|
|
262
|
+
* `dispatch_cycle` lint consumes. The shape mirrors codegen's `CallEdgeIR`
|
|
263
|
+
* exactly (the `CallSiteScope` is this same type), so the feeder list passes
|
|
264
|
+
* straight through without conversion; the lint reads only the `call` /
|
|
265
|
+
* `schedule` rows with a `target`.
|
|
266
|
+
*
|
|
267
|
+
* A `target` is the `namespace:export` function key (`api.billing.invoices.create`
|
|
268
|
+
* → `billing_invoices:create`) for `call` / `schedule`; a queue or topic export
|
|
269
|
+
* name for `enqueue` / `publish`. `reason` says why the target could not be
|
|
270
|
+
* read statically, in which case `target` is absent.
|
|
271
|
+
*
|
|
272
|
+
* `conditional` is set (only ever to `true`) when the hop may not take effect
|
|
273
|
+
* on every pass; codegen's `isConditionalSite` owns the rules. The cycle lint
|
|
274
|
+
* reads it as its false-positive gate.
|
|
275
|
+
*
|
|
276
|
+
* Produced by the codegen feeder; runtime callers don't supply it, so the lint
|
|
277
|
+
* finds nothing there.
|
|
278
|
+
*/
|
|
279
|
+
interface AdvisorCallEdge {
|
|
280
|
+
/** `true` when the hop may not take effect on every pass. */
|
|
281
|
+
conditional?: true;
|
|
282
|
+
/** Source file relative to the lunora dir, no extension. */
|
|
283
|
+
file: string;
|
|
284
|
+
/** What the edge draws: a function call, a scheduled dispatch, an enqueue, a publish, or a service use. */
|
|
285
|
+
kind: "call" | "enqueue" | "invoke" | "publish" | "schedule";
|
|
286
|
+
/** 1-based line of the call, or `0` when unknown. */
|
|
287
|
+
line: number;
|
|
288
|
+
/** Why the target could not be read statically — set exactly when `target` is absent. */
|
|
289
|
+
reason?: string;
|
|
290
|
+
/** Who the site runs on behalf of — see {@link AdvisorCallSiteScope}. */
|
|
291
|
+
scope: AdvisorCallSiteScope;
|
|
292
|
+
/** The `namespace:export` function key (or queue/topic/service name) the edge points at. */
|
|
293
|
+
target?: string;
|
|
294
|
+
}
|
|
260
295
|
/**
|
|
261
296
|
* One factory/constructor call in `lunora/` whose configuration object literal a
|
|
262
297
|
* security lint inspects for a present-or-absent key — the shared input for the
|
|
@@ -964,6 +999,13 @@ interface AdvisorOwnerFieldWrite {
|
|
|
964
999
|
field: string;
|
|
965
1000
|
/** Source file relative to the lunora dir, no extension. */
|
|
966
1001
|
file: string;
|
|
1002
|
+
/**
|
|
1003
|
+
* The handler proves the written value equals the server identity before the
|
|
1004
|
+
* write (an `if (args.field !== identity) throw`, or an `assert*(…)` given both):
|
|
1005
|
+
* the value is validated, so the write is not reported. Mirrors the codegen
|
|
1006
|
+
* feeder's `guarded` stamp; see `isGuardedWrite` there.
|
|
1007
|
+
*/
|
|
1008
|
+
guarded?: true;
|
|
967
1009
|
/** 1-based line of the `ctx.db` write call, or `0` when unknown. */
|
|
968
1010
|
line: number;
|
|
969
1011
|
/** The `ctx.db` write method (`insert` / `replace` / `patch` / `insertManyUnsafe`). */
|
|
@@ -1710,6 +1752,23 @@ interface AdvisorStorageUpload {
|
|
|
1710
1752
|
/** Who the site runs on behalf of — see {@link AdvisorCallSiteScope}. */
|
|
1711
1753
|
scope: AdvisorCallSiteScope;
|
|
1712
1754
|
}
|
|
1755
|
+
/**
|
|
1756
|
+
* One literal-infinite loop in `lunora/` source with no statically reachable
|
|
1757
|
+
* exit — the input the `unbounded_loop` lint consumes. Produced by codegen's
|
|
1758
|
+
* `discoverUnboundedLoops`, which owns what counts as an exit. The shape
|
|
1759
|
+
* mirrors codegen's `UnboundedLoopIR`, so the feeder list passes straight through.
|
|
1760
|
+
* Runtime callers don't supply it, so the lint finds nothing there.
|
|
1761
|
+
*/
|
|
1762
|
+
interface AdvisorUnboundedLoop {
|
|
1763
|
+
/** Source file relative to the lunora dir, no extension. */
|
|
1764
|
+
file: string;
|
|
1765
|
+
/** The loop form that never falls out. */
|
|
1766
|
+
kind: "do" | "for" | "while";
|
|
1767
|
+
/** 1-based line of the loop keyword. */
|
|
1768
|
+
line: number;
|
|
1769
|
+
/** Who the loop runs on behalf of — see {@link AdvisorCallSiteScope}. */
|
|
1770
|
+
scope: AdvisorCallSiteScope;
|
|
1771
|
+
}
|
|
1713
1772
|
/**
|
|
1714
1773
|
* One branching `defineShape({ where })` / `definePolicy({ when })` predicate arm
|
|
1715
1774
|
* that returns an unrestricted predicate — the `unrestricted_where_branch` lint
|
|
@@ -1979,6 +2038,13 @@ interface LintContext {
|
|
|
1979
2038
|
* finds nothing.
|
|
1980
2039
|
*/
|
|
1981
2040
|
browserUrlAccesses?: ReadonlyArray<AdvisorBrowserUrlAccess>;
|
|
2041
|
+
/**
|
|
2042
|
+
* Call-site edges of the architecture graph — `ctx.run*` calls, scheduler
|
|
2043
|
+
* dispatches, enqueues, publishes and service uses — the `dispatch_cycle`
|
|
2044
|
+
* input. Supplied by the codegen feeder; absent for runtime
|
|
2045
|
+
* callers, where the lint finds nothing.
|
|
2046
|
+
*/
|
|
2047
|
+
callEdges?: ReadonlyArray<AdvisorCallEdge>;
|
|
1982
2048
|
/**
|
|
1983
2049
|
* Factory/constructor calls in `lunora/` whose config object literal a
|
|
1984
2050
|
* security lint inspects for a present-or-absent key — the shared input for
|
|
@@ -2402,6 +2468,12 @@ interface LintContext {
|
|
|
2402
2468
|
* absent for runtime callers.
|
|
2403
2469
|
*/
|
|
2404
2470
|
tableWrites?: ReadonlyArray<AdvisorTableWrite>;
|
|
2471
|
+
/**
|
|
2472
|
+
* Literal-infinite loops (`while (true)`, `for (;;)`, `do … while (true)`)
|
|
2473
|
+
* with no statically reachable exit — the `unbounded_loop` input. Supplied
|
|
2474
|
+
* by the codegen feeder only.
|
|
2475
|
+
*/
|
|
2476
|
+
unboundedLoops?: ReadonlyArray<AdvisorUnboundedLoop>;
|
|
2405
2477
|
/**
|
|
2406
2478
|
* Branching shape/policy predicate arms returning an unrestricted filter (`{}` /
|
|
2407
2479
|
* `undefined`) — the `unrestricted_where_branch` lint input. Supplied by the
|
|
@@ -3022,6 +3094,24 @@ declare const containerStartEnableInternetOverride: Lint;
|
|
|
3022
3094
|
* registered owner mutation called through `ctx.runMutation`.
|
|
3023
3095
|
*/
|
|
3024
3096
|
declare const crossModuleTableWrite: Lint;
|
|
3097
|
+
/**
|
|
3098
|
+
* Flags a cycle of function dispatches in which every hop runs unconditionally:
|
|
3099
|
+
* a function that always schedules itself (`ctx.scheduler.runAfter(…, self)`),
|
|
3100
|
+
* or two that always schedule or call each other. Nothing in such a cycle can
|
|
3101
|
+
* stop it — once one member runs, the chain re-arms forever, burning storage
|
|
3102
|
+
* operations until someone notices the bill.
|
|
3103
|
+
*
|
|
3104
|
+
* The false-positive gate is the feeder's `conditional` flag, whose rules live
|
|
3105
|
+
* with codegen's `isConditionalSite`: a hop that may not run, or that can be
|
|
3106
|
+
* cancelled or rolled back, drops out. Only hops in an export's own body count
|
|
3107
|
+
* — a helper's call may be guarded where the helper is called — and only
|
|
3108
|
+
* static targets. Re-arming outside `ctx.scheduler` (a raw Durable Object
|
|
3109
|
+
* `setAlarm`, a queue re-enqueue) is not modelled.
|
|
3110
|
+
*
|
|
3111
|
+
* Runs only when the codegen feeder supplied call edges (`context.callEdges`
|
|
3112
|
+
* present); a runtime caller flags nothing.
|
|
3113
|
+
*/
|
|
3114
|
+
declare const dispatchCycle: Lint;
|
|
3025
3115
|
/**
|
|
3026
3116
|
* Lunora port of splinter's `0009_duplicate_index`.
|
|
3027
3117
|
*
|
|
@@ -4397,6 +4487,26 @@ declare const topicTooManySubscriptions: Lint;
|
|
|
4397
4487
|
* codegen time rather than at 3am when the sweep silently misbehaves.
|
|
4398
4488
|
*/
|
|
4399
4489
|
declare const ttlFieldNotTimestamp: Lint;
|
|
4490
|
+
/**
|
|
4491
|
+
* Flags a literal-infinite loop — `while (true)`, `for (;;)` / `for (; true;)`,
|
|
4492
|
+
* `do { … } while (true)` — that has no statically reachable way out: no
|
|
4493
|
+
* `break` bound to it, no `return`/`throw` leaving its function, no `yield`
|
|
4494
|
+
* suspending it.
|
|
4495
|
+
*
|
|
4496
|
+
* Inside a Durable Object such a loop never yields the isolate: a request, a
|
|
4497
|
+
* scheduled run or a queue consumer that enters it holds the object and its
|
|
4498
|
+
* storage forever, and every `ctx.db` read or write in the body is billed on
|
|
4499
|
+
* each turn.
|
|
4500
|
+
*
|
|
4501
|
+
* `ERROR`, because the feeder (codegen's `discoverUnboundedLoops`) records only
|
|
4502
|
+
* a loop whose own syntax proves it cannot exit; what counts as an exit is
|
|
4503
|
+
* defined there. A loop in a helper no export reaches is dead code and stays
|
|
4504
|
+
* quiet; module scope runs at import, so it does not.
|
|
4505
|
+
*
|
|
4506
|
+
* Runs only when the codegen feeder supplied loop evidence
|
|
4507
|
+
* (`context.unboundedLoops` present); a runtime caller flags nothing.
|
|
4508
|
+
*/
|
|
4509
|
+
declare const unboundedLoop: Lint;
|
|
4400
4510
|
/**
|
|
4401
4511
|
* Flags a public `v.string()` argument with no length bound.
|
|
4402
4512
|
*
|
|
@@ -4870,4 +4980,4 @@ interface RunAdvisorOptions {
|
|
|
4870
4980
|
* `static` lints at build time and defer `runtime` lints to a live shard.
|
|
4871
4981
|
*/
|
|
4872
4982
|
declare const runAdvisor: (context: LintContext, options?: RunAdvisorOptions) => Finding[];
|
|
4873
|
-
export { ALL_LINTS, type AdvisorAdminRoute, type AdvisorAiRawRun, type AdvisorAiToolSideEffect, type AdvisorArgumentDerivedFetch, type AdvisorArgumentValidator, type AdvisorAuthApiCall, type AdvisorAuthConfig, type AdvisorBrowserUrlAccess, type AdvisorCallSiteScope, type AdvisorConfigCall, type AdvisorContainer, type AdvisorContainerKeyAccess, type AdvisorContainerOverride, type AdvisorExportSink, type AdvisorFailOpenGuard, type AdvisorFlagRead, type AdvisorFlagSecurityDefault, type AdvisorGeoIndexUsage, type AdvisorHttpActionGuard, type AdvisorHttpHeaderWrite, type AdvisorHyperdriveCall, type AdvisorIdentityClaimRead, type AdvisorImageDeliveryUrlAccess, type AdvisorIndex, type AdvisorIndexHit, type AdvisorInsertWrite, type AdvisorKvKeyAccess, type AdvisorMailRecipientAccess, type AdvisorMap, type AdvisorMaskProcedure, type AdvisorMaskStrategy, type AdvisorModule, type AdvisorMutatorDeclaration, type AdvisorMutatorWrite, type AdvisorNondeterministicCall, type AdvisorNormalizeIdAuthorization, type AdvisorNotifyCall, type AdvisorNotifyConfig, type AdvisorOwnerFieldWrite, type AdvisorPaymentWebhook, type AdvisorPrivilegedDispatch, type AdvisorProcedureProtection, type AdvisorQueryRead, type AdvisorQueue, type AdvisorQueueTuning, type AdvisorR2sqlCall, type AdvisorRatelimitKeySelector, type AdvisorRawRowReturn, type AdvisorRelation, type AdvisorRelationLoad, type AdvisorRlsProcedure, type AdvisorSchema, type AdvisorSecretLiteral, type AdvisorShape, type AdvisorShardTraffic, type AdvisorSoftDeleteRead, type AdvisorSqlInterpolation, type AdvisorStaleMigrationImport, type AdvisorStorageKeyAccess, type AdvisorStorageUpload, type AdvisorTable, type AdvisorTableScan, type AdvisorTableWrite, type AdvisorVectorNamespaceAccess, type AdvisorWorkflow, type AdvisorWorkflowCall, type AdvisorWranglerVariable, type AnalyticsMetricsOptions, type AnalyticsMetricsSource, type AnalyticsRuntimeMetrics, type BaselineComparison, type CallSiteMetadata, type Category, type CheckResult, type Coverage, type Facing, type Finding, type Grade, type Level, type Lint, type LintContext, type LintSource, MAP_VERSION, type MapSummary, type ProcedureDelta, type ProcedureScore, type ProjectScore, RUNTIME_LINTS, RunAdvisorOptions, STATIC_LINTS, type ScoreAdvisorOptions, type Sensitivity, type SensitivityLevel, actionFetchSsrf, actionWithoutErrorHandling, adminRouteWithoutGuard, aiRawRunEscapeHatch, aiRunWithoutLogging, aiToolSideEffectPromptInjection, aiUnboundedGenerationPublic, allowUnauthenticatedShardAccessEnabled, authApiCallWithoutHeaders, authCsrfCheckDisabled, authEmailVerificationDisabled, authScimWithoutTransactions, authSecureCookiesDisabled, authSessionFreshageZero, authTrustedOriginsWildcard, browserAllowPrivateTargets, browserUserUrlWithoutAllowlist, byCodepoint, callSiteCallers, callSiteDescription, callSiteLabel, callSiteMetadata, circularFk, classifySensitivity, commitOrderedHardDelete, compareToBaseline, containerInstanceKeyFromUserInput, containerOversizedInstance, containerPublicInternet, containerRuntimeEgressRelaxation, containerStartEnableInternetOverride, crossModuleTableWrite, dedupeCacheKeys, duplicateIndex, emptyIndex, errorWithoutCatalog, exportSinkMisconfigured, externalSourceIncrementalNoDeletePath, externalSourceOnGlobal, externalSourceUnscoped, fanOutBreadth, filterOnPrimaryKey, filterWithoutIndex, flagGatesSecurityWithUnsafeDefault, flagReadInSubscription, fromServerSchema, geoIndexFieldNotGeopoint, geoIndexUnused, globalTableNearColumnLimit, gradeFromScore, hardcodedSecret, helperRole, hotShard, httpActionMissingAuthGuard, httpActionResponseHeaderInjection, hyperdriveOutsideAction, identityUndeclaredClaimTrusted, imagesUrlSourceFromUserInput, indexReferencesUnknownField, indexUtilization, insertManyUnsafeUserData, isReachableSite, kvUnscopedUserKeyIdor, mailInboundDispatchWithoutVerify, mailRecipientFromRequestInput, maskUncoveredPiiColumn, maskWeakHashStrategyOnPii, maskedRelationLeakViaWith, mutatorFullRowReplace, mutatorWithoutOwnerScope, nondeterministicQueryMutation, normalizeIdUsedAsAuthorization, notifyMissingPushConfig, notifySendOutsideAction, outputProjectionMissingOnPublicRead, ownerFieldFromArgsNotAuth, parseAdvisorMap, paymentCreateWithoutAuthorize, paymentWebhookWideTolerance, plaintextSecretInWranglerVariables, policyReferencesUnknownTable, privilegedDispatchUnvalidatedPayload, privilegedFanoutFromPublicProcedure, procedureWithoutStructuredEvent, publicArgumentUsesAny, publicMutationWithoutRatelimit, publicTableRlsOptoutConfusion, queueWithoutDlq, r2sqlOutsideAction, ratelimitDefaultMemoryStore, ratelimitKeySpoofableOrGlobal, ratelimitMiddlewareFailOpen, readCallSiteCallers, relationReferencesUnknownField, relationReferencesUnknownTable, rlsUncoveredTable, runAdvisor, scoreAdvisor, shapeTargetsGlobalTable, shapeUnknownTable, signupMutationWithoutDisposableGating, softDeleteIncludeDeletedFromArgs, sqlInjectionRisk, storageGenerateUploadUrlNoContentTypePin, storageKeyFromUserArgs, storagePresignedUrlForPrivateContent, storageUploadWithoutContentTypeAllowlist, storageUploadWithoutMaxSize, tableWithoutInsert, topicTooManySubscriptions, ttlFieldNotTimestamp, unboundedStringArgument, unindexedForeignKey, unindexedRelationTarget, unrestrictedWhereBranch, userCreatingMutationWithoutCaptcha, vectorsNamespaceFromUserInput, workflowDuplicateStepName, workflowUnknownTarget, workflowUnused };
|
|
4983
|
+
export { ALL_LINTS, type AdvisorAdminRoute, type AdvisorAiRawRun, type AdvisorAiToolSideEffect, type AdvisorArgumentDerivedFetch, type AdvisorArgumentValidator, type AdvisorAuthApiCall, type AdvisorAuthConfig, type AdvisorBrowserUrlAccess, type AdvisorCallEdge, type AdvisorCallSiteScope, type AdvisorConfigCall, type AdvisorContainer, type AdvisorContainerKeyAccess, type AdvisorContainerOverride, type AdvisorExportSink, type AdvisorFailOpenGuard, type AdvisorFlagRead, type AdvisorFlagSecurityDefault, type AdvisorGeoIndexUsage, type AdvisorHttpActionGuard, type AdvisorHttpHeaderWrite, type AdvisorHyperdriveCall, type AdvisorIdentityClaimRead, type AdvisorImageDeliveryUrlAccess, type AdvisorIndex, type AdvisorIndexHit, type AdvisorInsertWrite, type AdvisorKvKeyAccess, type AdvisorMailRecipientAccess, type AdvisorMap, type AdvisorMaskProcedure, type AdvisorMaskStrategy, type AdvisorModule, type AdvisorMutatorDeclaration, type AdvisorMutatorWrite, type AdvisorNondeterministicCall, type AdvisorNormalizeIdAuthorization, type AdvisorNotifyCall, type AdvisorNotifyConfig, type AdvisorOwnerFieldWrite, type AdvisorPaymentWebhook, type AdvisorPrivilegedDispatch, type AdvisorProcedureProtection, type AdvisorQueryRead, type AdvisorQueue, type AdvisorQueueTuning, type AdvisorR2sqlCall, type AdvisorRatelimitKeySelector, type AdvisorRawRowReturn, type AdvisorRelation, type AdvisorRelationLoad, type AdvisorRlsProcedure, type AdvisorSchema, type AdvisorSecretLiteral, type AdvisorShape, type AdvisorShardTraffic, type AdvisorSoftDeleteRead, type AdvisorSqlInterpolation, type AdvisorStaleMigrationImport, type AdvisorStorageKeyAccess, type AdvisorStorageUpload, type AdvisorTable, type AdvisorTableScan, type AdvisorTableWrite, type AdvisorUnboundedLoop, type AdvisorVectorNamespaceAccess, type AdvisorWorkflow, type AdvisorWorkflowCall, type AdvisorWranglerVariable, type AnalyticsMetricsOptions, type AnalyticsMetricsSource, type AnalyticsRuntimeMetrics, type BaselineComparison, type CallSiteMetadata, type Category, type CheckResult, type Coverage, type Facing, type Finding, type Grade, type Level, type Lint, type LintContext, type LintSource, MAP_VERSION, type MapSummary, type ProcedureDelta, type ProcedureScore, type ProjectScore, RUNTIME_LINTS, RunAdvisorOptions, STATIC_LINTS, type ScoreAdvisorOptions, type Sensitivity, type SensitivityLevel, actionFetchSsrf, actionWithoutErrorHandling, adminRouteWithoutGuard, aiRawRunEscapeHatch, aiRunWithoutLogging, aiToolSideEffectPromptInjection, aiUnboundedGenerationPublic, allowUnauthenticatedShardAccessEnabled, authApiCallWithoutHeaders, authCsrfCheckDisabled, authEmailVerificationDisabled, authScimWithoutTransactions, authSecureCookiesDisabled, authSessionFreshageZero, authTrustedOriginsWildcard, browserAllowPrivateTargets, browserUserUrlWithoutAllowlist, byCodepoint, callSiteCallers, callSiteDescription, callSiteLabel, callSiteMetadata, circularFk, classifySensitivity, commitOrderedHardDelete, compareToBaseline, containerInstanceKeyFromUserInput, containerOversizedInstance, containerPublicInternet, containerRuntimeEgressRelaxation, containerStartEnableInternetOverride, crossModuleTableWrite, dedupeCacheKeys, dispatchCycle, duplicateIndex, emptyIndex, errorWithoutCatalog, exportSinkMisconfigured, externalSourceIncrementalNoDeletePath, externalSourceOnGlobal, externalSourceUnscoped, fanOutBreadth, filterOnPrimaryKey, filterWithoutIndex, flagGatesSecurityWithUnsafeDefault, flagReadInSubscription, fromServerSchema, geoIndexFieldNotGeopoint, geoIndexUnused, globalTableNearColumnLimit, gradeFromScore, hardcodedSecret, helperRole, hotShard, httpActionMissingAuthGuard, httpActionResponseHeaderInjection, hyperdriveOutsideAction, identityUndeclaredClaimTrusted, imagesUrlSourceFromUserInput, indexReferencesUnknownField, indexUtilization, insertManyUnsafeUserData, isReachableSite, kvUnscopedUserKeyIdor, mailInboundDispatchWithoutVerify, mailRecipientFromRequestInput, maskUncoveredPiiColumn, maskWeakHashStrategyOnPii, maskedRelationLeakViaWith, mutatorFullRowReplace, mutatorWithoutOwnerScope, nondeterministicQueryMutation, normalizeIdUsedAsAuthorization, notifyMissingPushConfig, notifySendOutsideAction, outputProjectionMissingOnPublicRead, ownerFieldFromArgsNotAuth, parseAdvisorMap, paymentCreateWithoutAuthorize, paymentWebhookWideTolerance, plaintextSecretInWranglerVariables, policyReferencesUnknownTable, privilegedDispatchUnvalidatedPayload, privilegedFanoutFromPublicProcedure, procedureWithoutStructuredEvent, publicArgumentUsesAny, publicMutationWithoutRatelimit, publicTableRlsOptoutConfusion, queueWithoutDlq, r2sqlOutsideAction, ratelimitDefaultMemoryStore, ratelimitKeySpoofableOrGlobal, ratelimitMiddlewareFailOpen, readCallSiteCallers, relationReferencesUnknownField, relationReferencesUnknownTable, rlsUncoveredTable, runAdvisor, scoreAdvisor, shapeTargetsGlobalTable, shapeUnknownTable, signupMutationWithoutDisposableGating, softDeleteIncludeDeletedFromArgs, sqlInjectionRisk, storageGenerateUploadUrlNoContentTypePin, storageKeyFromUserArgs, storagePresignedUrlForPrivateContent, storageUploadWithoutContentTypeAllowlist, storageUploadWithoutMaxSize, tableWithoutInsert, topicTooManySubscriptions, ttlFieldNotTimestamp, unboundedLoop, unboundedStringArgument, unindexedForeignKey, unindexedRelationTarget, unrestrictedWhereBranch, userCreatingMutationWithoutCaptcha, vectorsNamespaceFromUserInput, workflowDuplicateStepName, workflowUnknownTarget, workflowUnused };
|
package/dist/index.d.ts
CHANGED
|
@@ -257,6 +257,41 @@ interface AdvisorBrowserUrlAccess {
|
|
|
257
257
|
/** Who the site runs on behalf of — see {@link AdvisorCallSiteScope}. */
|
|
258
258
|
scope: AdvisorCallSiteScope;
|
|
259
259
|
}
|
|
260
|
+
/**
|
|
261
|
+
* One call-site edge of the architecture graph — the input the
|
|
262
|
+
* `dispatch_cycle` lint consumes. The shape mirrors codegen's `CallEdgeIR`
|
|
263
|
+
* exactly (the `CallSiteScope` is this same type), so the feeder list passes
|
|
264
|
+
* straight through without conversion; the lint reads only the `call` /
|
|
265
|
+
* `schedule` rows with a `target`.
|
|
266
|
+
*
|
|
267
|
+
* A `target` is the `namespace:export` function key (`api.billing.invoices.create`
|
|
268
|
+
* → `billing_invoices:create`) for `call` / `schedule`; a queue or topic export
|
|
269
|
+
* name for `enqueue` / `publish`. `reason` says why the target could not be
|
|
270
|
+
* read statically, in which case `target` is absent.
|
|
271
|
+
*
|
|
272
|
+
* `conditional` is set (only ever to `true`) when the hop may not take effect
|
|
273
|
+
* on every pass; codegen's `isConditionalSite` owns the rules. The cycle lint
|
|
274
|
+
* reads it as its false-positive gate.
|
|
275
|
+
*
|
|
276
|
+
* Produced by the codegen feeder; runtime callers don't supply it, so the lint
|
|
277
|
+
* finds nothing there.
|
|
278
|
+
*/
|
|
279
|
+
interface AdvisorCallEdge {
|
|
280
|
+
/** `true` when the hop may not take effect on every pass. */
|
|
281
|
+
conditional?: true;
|
|
282
|
+
/** Source file relative to the lunora dir, no extension. */
|
|
283
|
+
file: string;
|
|
284
|
+
/** What the edge draws: a function call, a scheduled dispatch, an enqueue, a publish, or a service use. */
|
|
285
|
+
kind: "call" | "enqueue" | "invoke" | "publish" | "schedule";
|
|
286
|
+
/** 1-based line of the call, or `0` when unknown. */
|
|
287
|
+
line: number;
|
|
288
|
+
/** Why the target could not be read statically — set exactly when `target` is absent. */
|
|
289
|
+
reason?: string;
|
|
290
|
+
/** Who the site runs on behalf of — see {@link AdvisorCallSiteScope}. */
|
|
291
|
+
scope: AdvisorCallSiteScope;
|
|
292
|
+
/** The `namespace:export` function key (or queue/topic/service name) the edge points at. */
|
|
293
|
+
target?: string;
|
|
294
|
+
}
|
|
260
295
|
/**
|
|
261
296
|
* One factory/constructor call in `lunora/` whose configuration object literal a
|
|
262
297
|
* security lint inspects for a present-or-absent key — the shared input for the
|
|
@@ -964,6 +999,13 @@ interface AdvisorOwnerFieldWrite {
|
|
|
964
999
|
field: string;
|
|
965
1000
|
/** Source file relative to the lunora dir, no extension. */
|
|
966
1001
|
file: string;
|
|
1002
|
+
/**
|
|
1003
|
+
* The handler proves the written value equals the server identity before the
|
|
1004
|
+
* write (an `if (args.field !== identity) throw`, or an `assert*(…)` given both):
|
|
1005
|
+
* the value is validated, so the write is not reported. Mirrors the codegen
|
|
1006
|
+
* feeder's `guarded` stamp; see `isGuardedWrite` there.
|
|
1007
|
+
*/
|
|
1008
|
+
guarded?: true;
|
|
967
1009
|
/** 1-based line of the `ctx.db` write call, or `0` when unknown. */
|
|
968
1010
|
line: number;
|
|
969
1011
|
/** The `ctx.db` write method (`insert` / `replace` / `patch` / `insertManyUnsafe`). */
|
|
@@ -1710,6 +1752,23 @@ interface AdvisorStorageUpload {
|
|
|
1710
1752
|
/** Who the site runs on behalf of — see {@link AdvisorCallSiteScope}. */
|
|
1711
1753
|
scope: AdvisorCallSiteScope;
|
|
1712
1754
|
}
|
|
1755
|
+
/**
|
|
1756
|
+
* One literal-infinite loop in `lunora/` source with no statically reachable
|
|
1757
|
+
* exit — the input the `unbounded_loop` lint consumes. Produced by codegen's
|
|
1758
|
+
* `discoverUnboundedLoops`, which owns what counts as an exit. The shape
|
|
1759
|
+
* mirrors codegen's `UnboundedLoopIR`, so the feeder list passes straight through.
|
|
1760
|
+
* Runtime callers don't supply it, so the lint finds nothing there.
|
|
1761
|
+
*/
|
|
1762
|
+
interface AdvisorUnboundedLoop {
|
|
1763
|
+
/** Source file relative to the lunora dir, no extension. */
|
|
1764
|
+
file: string;
|
|
1765
|
+
/** The loop form that never falls out. */
|
|
1766
|
+
kind: "do" | "for" | "while";
|
|
1767
|
+
/** 1-based line of the loop keyword. */
|
|
1768
|
+
line: number;
|
|
1769
|
+
/** Who the loop runs on behalf of — see {@link AdvisorCallSiteScope}. */
|
|
1770
|
+
scope: AdvisorCallSiteScope;
|
|
1771
|
+
}
|
|
1713
1772
|
/**
|
|
1714
1773
|
* One branching `defineShape({ where })` / `definePolicy({ when })` predicate arm
|
|
1715
1774
|
* that returns an unrestricted predicate — the `unrestricted_where_branch` lint
|
|
@@ -1979,6 +2038,13 @@ interface LintContext {
|
|
|
1979
2038
|
* finds nothing.
|
|
1980
2039
|
*/
|
|
1981
2040
|
browserUrlAccesses?: ReadonlyArray<AdvisorBrowserUrlAccess>;
|
|
2041
|
+
/**
|
|
2042
|
+
* Call-site edges of the architecture graph — `ctx.run*` calls, scheduler
|
|
2043
|
+
* dispatches, enqueues, publishes and service uses — the `dispatch_cycle`
|
|
2044
|
+
* input. Supplied by the codegen feeder; absent for runtime
|
|
2045
|
+
* callers, where the lint finds nothing.
|
|
2046
|
+
*/
|
|
2047
|
+
callEdges?: ReadonlyArray<AdvisorCallEdge>;
|
|
1982
2048
|
/**
|
|
1983
2049
|
* Factory/constructor calls in `lunora/` whose config object literal a
|
|
1984
2050
|
* security lint inspects for a present-or-absent key — the shared input for
|
|
@@ -2402,6 +2468,12 @@ interface LintContext {
|
|
|
2402
2468
|
* absent for runtime callers.
|
|
2403
2469
|
*/
|
|
2404
2470
|
tableWrites?: ReadonlyArray<AdvisorTableWrite>;
|
|
2471
|
+
/**
|
|
2472
|
+
* Literal-infinite loops (`while (true)`, `for (;;)`, `do … while (true)`)
|
|
2473
|
+
* with no statically reachable exit — the `unbounded_loop` input. Supplied
|
|
2474
|
+
* by the codegen feeder only.
|
|
2475
|
+
*/
|
|
2476
|
+
unboundedLoops?: ReadonlyArray<AdvisorUnboundedLoop>;
|
|
2405
2477
|
/**
|
|
2406
2478
|
* Branching shape/policy predicate arms returning an unrestricted filter (`{}` /
|
|
2407
2479
|
* `undefined`) — the `unrestricted_where_branch` lint input. Supplied by the
|
|
@@ -3022,6 +3094,24 @@ declare const containerStartEnableInternetOverride: Lint;
|
|
|
3022
3094
|
* registered owner mutation called through `ctx.runMutation`.
|
|
3023
3095
|
*/
|
|
3024
3096
|
declare const crossModuleTableWrite: Lint;
|
|
3097
|
+
/**
|
|
3098
|
+
* Flags a cycle of function dispatches in which every hop runs unconditionally:
|
|
3099
|
+
* a function that always schedules itself (`ctx.scheduler.runAfter(…, self)`),
|
|
3100
|
+
* or two that always schedule or call each other. Nothing in such a cycle can
|
|
3101
|
+
* stop it — once one member runs, the chain re-arms forever, burning storage
|
|
3102
|
+
* operations until someone notices the bill.
|
|
3103
|
+
*
|
|
3104
|
+
* The false-positive gate is the feeder's `conditional` flag, whose rules live
|
|
3105
|
+
* with codegen's `isConditionalSite`: a hop that may not run, or that can be
|
|
3106
|
+
* cancelled or rolled back, drops out. Only hops in an export's own body count
|
|
3107
|
+
* — a helper's call may be guarded where the helper is called — and only
|
|
3108
|
+
* static targets. Re-arming outside `ctx.scheduler` (a raw Durable Object
|
|
3109
|
+
* `setAlarm`, a queue re-enqueue) is not modelled.
|
|
3110
|
+
*
|
|
3111
|
+
* Runs only when the codegen feeder supplied call edges (`context.callEdges`
|
|
3112
|
+
* present); a runtime caller flags nothing.
|
|
3113
|
+
*/
|
|
3114
|
+
declare const dispatchCycle: Lint;
|
|
3025
3115
|
/**
|
|
3026
3116
|
* Lunora port of splinter's `0009_duplicate_index`.
|
|
3027
3117
|
*
|
|
@@ -4397,6 +4487,26 @@ declare const topicTooManySubscriptions: Lint;
|
|
|
4397
4487
|
* codegen time rather than at 3am when the sweep silently misbehaves.
|
|
4398
4488
|
*/
|
|
4399
4489
|
declare const ttlFieldNotTimestamp: Lint;
|
|
4490
|
+
/**
|
|
4491
|
+
* Flags a literal-infinite loop — `while (true)`, `for (;;)` / `for (; true;)`,
|
|
4492
|
+
* `do { … } while (true)` — that has no statically reachable way out: no
|
|
4493
|
+
* `break` bound to it, no `return`/`throw` leaving its function, no `yield`
|
|
4494
|
+
* suspending it.
|
|
4495
|
+
*
|
|
4496
|
+
* Inside a Durable Object such a loop never yields the isolate: a request, a
|
|
4497
|
+
* scheduled run or a queue consumer that enters it holds the object and its
|
|
4498
|
+
* storage forever, and every `ctx.db` read or write in the body is billed on
|
|
4499
|
+
* each turn.
|
|
4500
|
+
*
|
|
4501
|
+
* `ERROR`, because the feeder (codegen's `discoverUnboundedLoops`) records only
|
|
4502
|
+
* a loop whose own syntax proves it cannot exit; what counts as an exit is
|
|
4503
|
+
* defined there. A loop in a helper no export reaches is dead code and stays
|
|
4504
|
+
* quiet; module scope runs at import, so it does not.
|
|
4505
|
+
*
|
|
4506
|
+
* Runs only when the codegen feeder supplied loop evidence
|
|
4507
|
+
* (`context.unboundedLoops` present); a runtime caller flags nothing.
|
|
4508
|
+
*/
|
|
4509
|
+
declare const unboundedLoop: Lint;
|
|
4400
4510
|
/**
|
|
4401
4511
|
* Flags a public `v.string()` argument with no length bound.
|
|
4402
4512
|
*
|
|
@@ -4870,4 +4980,4 @@ interface RunAdvisorOptions {
|
|
|
4870
4980
|
* `static` lints at build time and defer `runtime` lints to a live shard.
|
|
4871
4981
|
*/
|
|
4872
4982
|
declare const runAdvisor: (context: LintContext, options?: RunAdvisorOptions) => Finding[];
|
|
4873
|
-
export { ALL_LINTS, type AdvisorAdminRoute, type AdvisorAiRawRun, type AdvisorAiToolSideEffect, type AdvisorArgumentDerivedFetch, type AdvisorArgumentValidator, type AdvisorAuthApiCall, type AdvisorAuthConfig, type AdvisorBrowserUrlAccess, type AdvisorCallSiteScope, type AdvisorConfigCall, type AdvisorContainer, type AdvisorContainerKeyAccess, type AdvisorContainerOverride, type AdvisorExportSink, type AdvisorFailOpenGuard, type AdvisorFlagRead, type AdvisorFlagSecurityDefault, type AdvisorGeoIndexUsage, type AdvisorHttpActionGuard, type AdvisorHttpHeaderWrite, type AdvisorHyperdriveCall, type AdvisorIdentityClaimRead, type AdvisorImageDeliveryUrlAccess, type AdvisorIndex, type AdvisorIndexHit, type AdvisorInsertWrite, type AdvisorKvKeyAccess, type AdvisorMailRecipientAccess, type AdvisorMap, type AdvisorMaskProcedure, type AdvisorMaskStrategy, type AdvisorModule, type AdvisorMutatorDeclaration, type AdvisorMutatorWrite, type AdvisorNondeterministicCall, type AdvisorNormalizeIdAuthorization, type AdvisorNotifyCall, type AdvisorNotifyConfig, type AdvisorOwnerFieldWrite, type AdvisorPaymentWebhook, type AdvisorPrivilegedDispatch, type AdvisorProcedureProtection, type AdvisorQueryRead, type AdvisorQueue, type AdvisorQueueTuning, type AdvisorR2sqlCall, type AdvisorRatelimitKeySelector, type AdvisorRawRowReturn, type AdvisorRelation, type AdvisorRelationLoad, type AdvisorRlsProcedure, type AdvisorSchema, type AdvisorSecretLiteral, type AdvisorShape, type AdvisorShardTraffic, type AdvisorSoftDeleteRead, type AdvisorSqlInterpolation, type AdvisorStaleMigrationImport, type AdvisorStorageKeyAccess, type AdvisorStorageUpload, type AdvisorTable, type AdvisorTableScan, type AdvisorTableWrite, type AdvisorVectorNamespaceAccess, type AdvisorWorkflow, type AdvisorWorkflowCall, type AdvisorWranglerVariable, type AnalyticsMetricsOptions, type AnalyticsMetricsSource, type AnalyticsRuntimeMetrics, type BaselineComparison, type CallSiteMetadata, type Category, type CheckResult, type Coverage, type Facing, type Finding, type Grade, type Level, type Lint, type LintContext, type LintSource, MAP_VERSION, type MapSummary, type ProcedureDelta, type ProcedureScore, type ProjectScore, RUNTIME_LINTS, RunAdvisorOptions, STATIC_LINTS, type ScoreAdvisorOptions, type Sensitivity, type SensitivityLevel, actionFetchSsrf, actionWithoutErrorHandling, adminRouteWithoutGuard, aiRawRunEscapeHatch, aiRunWithoutLogging, aiToolSideEffectPromptInjection, aiUnboundedGenerationPublic, allowUnauthenticatedShardAccessEnabled, authApiCallWithoutHeaders, authCsrfCheckDisabled, authEmailVerificationDisabled, authScimWithoutTransactions, authSecureCookiesDisabled, authSessionFreshageZero, authTrustedOriginsWildcard, browserAllowPrivateTargets, browserUserUrlWithoutAllowlist, byCodepoint, callSiteCallers, callSiteDescription, callSiteLabel, callSiteMetadata, circularFk, classifySensitivity, commitOrderedHardDelete, compareToBaseline, containerInstanceKeyFromUserInput, containerOversizedInstance, containerPublicInternet, containerRuntimeEgressRelaxation, containerStartEnableInternetOverride, crossModuleTableWrite, dedupeCacheKeys, duplicateIndex, emptyIndex, errorWithoutCatalog, exportSinkMisconfigured, externalSourceIncrementalNoDeletePath, externalSourceOnGlobal, externalSourceUnscoped, fanOutBreadth, filterOnPrimaryKey, filterWithoutIndex, flagGatesSecurityWithUnsafeDefault, flagReadInSubscription, fromServerSchema, geoIndexFieldNotGeopoint, geoIndexUnused, globalTableNearColumnLimit, gradeFromScore, hardcodedSecret, helperRole, hotShard, httpActionMissingAuthGuard, httpActionResponseHeaderInjection, hyperdriveOutsideAction, identityUndeclaredClaimTrusted, imagesUrlSourceFromUserInput, indexReferencesUnknownField, indexUtilization, insertManyUnsafeUserData, isReachableSite, kvUnscopedUserKeyIdor, mailInboundDispatchWithoutVerify, mailRecipientFromRequestInput, maskUncoveredPiiColumn, maskWeakHashStrategyOnPii, maskedRelationLeakViaWith, mutatorFullRowReplace, mutatorWithoutOwnerScope, nondeterministicQueryMutation, normalizeIdUsedAsAuthorization, notifyMissingPushConfig, notifySendOutsideAction, outputProjectionMissingOnPublicRead, ownerFieldFromArgsNotAuth, parseAdvisorMap, paymentCreateWithoutAuthorize, paymentWebhookWideTolerance, plaintextSecretInWranglerVariables, policyReferencesUnknownTable, privilegedDispatchUnvalidatedPayload, privilegedFanoutFromPublicProcedure, procedureWithoutStructuredEvent, publicArgumentUsesAny, publicMutationWithoutRatelimit, publicTableRlsOptoutConfusion, queueWithoutDlq, r2sqlOutsideAction, ratelimitDefaultMemoryStore, ratelimitKeySpoofableOrGlobal, ratelimitMiddlewareFailOpen, readCallSiteCallers, relationReferencesUnknownField, relationReferencesUnknownTable, rlsUncoveredTable, runAdvisor, scoreAdvisor, shapeTargetsGlobalTable, shapeUnknownTable, signupMutationWithoutDisposableGating, softDeleteIncludeDeletedFromArgs, sqlInjectionRisk, storageGenerateUploadUrlNoContentTypePin, storageKeyFromUserArgs, storagePresignedUrlForPrivateContent, storageUploadWithoutContentTypeAllowlist, storageUploadWithoutMaxSize, tableWithoutInsert, topicTooManySubscriptions, ttlFieldNotTimestamp, unboundedStringArgument, unindexedForeignKey, unindexedRelationTarget, unrestrictedWhereBranch, userCreatingMutationWithoutCaptcha, vectorsNamespaceFromUserInput, workflowDuplicateStepName, workflowUnknownTarget, workflowUnused };
|
|
4983
|
+
export { ALL_LINTS, type AdvisorAdminRoute, type AdvisorAiRawRun, type AdvisorAiToolSideEffect, type AdvisorArgumentDerivedFetch, type AdvisorArgumentValidator, type AdvisorAuthApiCall, type AdvisorAuthConfig, type AdvisorBrowserUrlAccess, type AdvisorCallEdge, type AdvisorCallSiteScope, type AdvisorConfigCall, type AdvisorContainer, type AdvisorContainerKeyAccess, type AdvisorContainerOverride, type AdvisorExportSink, type AdvisorFailOpenGuard, type AdvisorFlagRead, type AdvisorFlagSecurityDefault, type AdvisorGeoIndexUsage, type AdvisorHttpActionGuard, type AdvisorHttpHeaderWrite, type AdvisorHyperdriveCall, type AdvisorIdentityClaimRead, type AdvisorImageDeliveryUrlAccess, type AdvisorIndex, type AdvisorIndexHit, type AdvisorInsertWrite, type AdvisorKvKeyAccess, type AdvisorMailRecipientAccess, type AdvisorMap, type AdvisorMaskProcedure, type AdvisorMaskStrategy, type AdvisorModule, type AdvisorMutatorDeclaration, type AdvisorMutatorWrite, type AdvisorNondeterministicCall, type AdvisorNormalizeIdAuthorization, type AdvisorNotifyCall, type AdvisorNotifyConfig, type AdvisorOwnerFieldWrite, type AdvisorPaymentWebhook, type AdvisorPrivilegedDispatch, type AdvisorProcedureProtection, type AdvisorQueryRead, type AdvisorQueue, type AdvisorQueueTuning, type AdvisorR2sqlCall, type AdvisorRatelimitKeySelector, type AdvisorRawRowReturn, type AdvisorRelation, type AdvisorRelationLoad, type AdvisorRlsProcedure, type AdvisorSchema, type AdvisorSecretLiteral, type AdvisorShape, type AdvisorShardTraffic, type AdvisorSoftDeleteRead, type AdvisorSqlInterpolation, type AdvisorStaleMigrationImport, type AdvisorStorageKeyAccess, type AdvisorStorageUpload, type AdvisorTable, type AdvisorTableScan, type AdvisorTableWrite, type AdvisorUnboundedLoop, type AdvisorVectorNamespaceAccess, type AdvisorWorkflow, type AdvisorWorkflowCall, type AdvisorWranglerVariable, type AnalyticsMetricsOptions, type AnalyticsMetricsSource, type AnalyticsRuntimeMetrics, type BaselineComparison, type CallSiteMetadata, type Category, type CheckResult, type Coverage, type Facing, type Finding, type Grade, type Level, type Lint, type LintContext, type LintSource, MAP_VERSION, type MapSummary, type ProcedureDelta, type ProcedureScore, type ProjectScore, RUNTIME_LINTS, RunAdvisorOptions, STATIC_LINTS, type ScoreAdvisorOptions, type Sensitivity, type SensitivityLevel, actionFetchSsrf, actionWithoutErrorHandling, adminRouteWithoutGuard, aiRawRunEscapeHatch, aiRunWithoutLogging, aiToolSideEffectPromptInjection, aiUnboundedGenerationPublic, allowUnauthenticatedShardAccessEnabled, authApiCallWithoutHeaders, authCsrfCheckDisabled, authEmailVerificationDisabled, authScimWithoutTransactions, authSecureCookiesDisabled, authSessionFreshageZero, authTrustedOriginsWildcard, browserAllowPrivateTargets, browserUserUrlWithoutAllowlist, byCodepoint, callSiteCallers, callSiteDescription, callSiteLabel, callSiteMetadata, circularFk, classifySensitivity, commitOrderedHardDelete, compareToBaseline, containerInstanceKeyFromUserInput, containerOversizedInstance, containerPublicInternet, containerRuntimeEgressRelaxation, containerStartEnableInternetOverride, crossModuleTableWrite, dedupeCacheKeys, dispatchCycle, duplicateIndex, emptyIndex, errorWithoutCatalog, exportSinkMisconfigured, externalSourceIncrementalNoDeletePath, externalSourceOnGlobal, externalSourceUnscoped, fanOutBreadth, filterOnPrimaryKey, filterWithoutIndex, flagGatesSecurityWithUnsafeDefault, flagReadInSubscription, fromServerSchema, geoIndexFieldNotGeopoint, geoIndexUnused, globalTableNearColumnLimit, gradeFromScore, hardcodedSecret, helperRole, hotShard, httpActionMissingAuthGuard, httpActionResponseHeaderInjection, hyperdriveOutsideAction, identityUndeclaredClaimTrusted, imagesUrlSourceFromUserInput, indexReferencesUnknownField, indexUtilization, insertManyUnsafeUserData, isReachableSite, kvUnscopedUserKeyIdor, mailInboundDispatchWithoutVerify, mailRecipientFromRequestInput, maskUncoveredPiiColumn, maskWeakHashStrategyOnPii, maskedRelationLeakViaWith, mutatorFullRowReplace, mutatorWithoutOwnerScope, nondeterministicQueryMutation, normalizeIdUsedAsAuthorization, notifyMissingPushConfig, notifySendOutsideAction, outputProjectionMissingOnPublicRead, ownerFieldFromArgsNotAuth, parseAdvisorMap, paymentCreateWithoutAuthorize, paymentWebhookWideTolerance, plaintextSecretInWranglerVariables, policyReferencesUnknownTable, privilegedDispatchUnvalidatedPayload, privilegedFanoutFromPublicProcedure, procedureWithoutStructuredEvent, publicArgumentUsesAny, publicMutationWithoutRatelimit, publicTableRlsOptoutConfusion, queueWithoutDlq, r2sqlOutsideAction, ratelimitDefaultMemoryStore, ratelimitKeySpoofableOrGlobal, ratelimitMiddlewareFailOpen, readCallSiteCallers, relationReferencesUnknownField, relationReferencesUnknownTable, rlsUncoveredTable, runAdvisor, scoreAdvisor, shapeTargetsGlobalTable, shapeUnknownTable, signupMutationWithoutDisposableGating, softDeleteIncludeDeletedFromArgs, sqlInjectionRisk, storageGenerateUploadUrlNoContentTypePin, storageKeyFromUserArgs, storagePresignedUrlForPrivateContent, storageUploadWithoutContentTypeAllowlist, storageUploadWithoutMaxSize, tableWithoutInsert, topicTooManySubscriptions, ttlFieldNotTimestamp, unboundedLoop, unboundedStringArgument, unindexedForeignKey, unindexedRelationTarget, unrestrictedWhereBranch, userCreatingMutationWithoutCaptcha, vectorsNamespaceFromUserInput, workflowDuplicateStepName, workflowUnknownTarget, workflowUnused };
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{dedupeCacheKeys as c}from"./packem_shared/dedupeCacheKeys-DtBOHffV.mjs";import d from"./packem_shared/fanOutBreadth-CBtmZnoh.mjs";import u from"./packem_shared/hotShard-BwGYZ3Tq.mjs";import h from"./packem_shared/indexUtilization-CkVPZcVe.mjs";import g from"./packem_shared/actionFetchSsrf-B4ZaOBlW.mjs";import b from"./packem_shared/actionWithoutErrorHandling-4GCBT0_z.mjs";import y from"./packem_shared/adminRouteWithoutGuard-DPE7LuNh.mjs";import S from"./packem_shared/aiRawRunEscapeHatch-B5980eT9.mjs";import w from"./packem_shared/aiRunWithoutLogging-CvHHtEN9.mjs";import v from"./packem_shared/aiToolSideEffectPromptInjection-_3MrX9Ul.mjs";import A from"./packem_shared/aiUnboundedGenerationPublic-C17h6sMV.mjs";import R from"./packem_shared/allowUnauthenticatedShardAccessEnabled-BQufF5Kb.mjs";import U from"./packem_shared/authApiCallWithoutHeaders-D8U1hv8s.mjs";import W from"./packem_shared/authCsrfCheckDisabled-C6bxME5y.mjs";import T from"./packem_shared/authEmailVerificationDisabled-yROPDgn-.mjs";import I from"./packem_shared/authScimWithoutTransactions-w9qb3iBe.mjs";import k from"./packem_shared/authSecureCookiesDisabled-qrCktlch.mjs";import N from"./packem_shared/authSessionFreshageZero-BMisjIIS.mjs";import x from"./packem_shared/authTrustedOriginsWildcard-DFDpfN84.mjs";import C from"./packem_shared/browserAllowPrivateTargets-Cj5sizhv.mjs";import F from"./packem_shared/browserUserUrlWithoutAllowlist-CcK27rvt.mjs";import M from"./packem_shared/circularFk-DtcWFJxK.mjs";import O from"./packem_shared/commitOrderedHardDelete-BPdwOKA7.mjs";import D from"./packem_shared/containerInstanceKeyFromUserInput-DBdjUnQb.mjs";import $ from"./packem_shared/containerOversizedInstance-Bx89uR7E.mjs";import E from"./packem_shared/containerPublicInternet-BFfZf_P4.mjs";import P from"./packem_shared/containerRuntimeEgressRelaxation-CioCA2zY.mjs";import K from"./packem_shared/containerStartEnableInternetOverride-C6dbznku.mjs";import q from"./packem_shared/crossModuleTableWrite-DjiVTAwK.mjs";import L from"./packem_shared/duplicateIndex-Cip6-Rpu.mjs";import G from"./packem_shared/emptyIndex-BnHDcXza.mjs";import _ from"./packem_shared/errorWithoutCatalog-BTfvaXHR.mjs";import z from"./packem_shared/exportSinkMisconfigured-JfbAx9AI.mjs";import H from"./packem_shared/externalSourceIncrementalNoDeletePath-BCzm3HzF.mjs";import B from"./packem_shared/externalSourceOnGlobal-CH7xbJ49.mjs";import j from"./packem_shared/externalSourceUnscoped-BxU2uSXk.mjs";import V from"./packem_shared/filterOnPrimaryKey-DbFriOZA.mjs";import Q from"./packem_shared/filterWithoutIndex-Dc7Nn0y2.mjs";import X from"./packem_shared/flagGatesSecurityWithUnsafeDefault-DB9M6hLM.mjs";import Z from"./packem_shared/flagReadInSubscription-DabIhYGD.mjs";import J from"./packem_shared/geoIndexFieldNotGeopoint-CDMNbAfp.mjs";import Y from"./packem_shared/geoIndexUnused-D7C9Qr4U.mjs";import oo from"./packem_shared/globalTableNearColumnLimit-BFbBBd6A.mjs";import eo from"./packem_shared/hardcodedSecret-Bw_4FYrs.mjs";import ro from"./packem_shared/httpActionMissingAuthGuard-BhvcmkwW.mjs";import to from"./packem_shared/httpActionResponseHeaderInjection-DKz2SlCa.mjs";import io from"./packem_shared/hyperdriveOutsideAction-CPDdGP2g.mjs";import no from"./packem_shared/identityUndeclaredClaimTrusted-CAUagXkJ.mjs";import ao from"./packem_shared/imagesUrlSourceFromUserInput-C2CJTTCI.mjs";import mo from"./packem_shared/indexReferencesUnknownField-Dm8SL4Tp.mjs";import lo from"./packem_shared/insertManyUnsafeUserData-DWE8d_DF.mjs";import so from"./packem_shared/kvUnscopedUserKeyIdor-CXFKAyM2.mjs";import po from"./packem_shared/mailInboundDispatchWithoutVerify-CWwqXyPX.mjs";import fo from"./packem_shared/mailRecipientFromRequestInput-CQZeOsP9.mjs";import co from"./packem_shared/maskUncoveredPiiColumn-axEka4nd.mjs";import uo from"./packem_shared/maskWeakHashStrategyOnPii-njstapQY.mjs";import ho from"./packem_shared/maskedRelationLeakViaWith-CIFij6vE.mjs";import{e as a}from"./packem_shared/finding-NrKO8idM.mjs";import go from"./packem_shared/mutatorFullRowReplace-BzRpZ47r.mjs";import bo from"./packem_shared/mutatorWithoutOwnerScope-BoS81ns0.mjs";import yo from"./packem_shared/nondeterministicQueryMutation-sxmixc0l.mjs";import So from"./packem_shared/normalizeIdUsedAsAuthorization-BXN-Can6.mjs";import wo from"./packem_shared/notifyMissingPushConfig-DeQMoNwm.mjs";import vo from"./packem_shared/notifySendOutsideAction-BJrDkr4h.mjs";import Ao from"./packem_shared/outputProjectionMissingOnPublicRead-DHivs_73.mjs";import Ro from"./packem_shared/ownerFieldFromArgsNotAuth-BFNc023N.mjs";import Uo from"./packem_shared/paymentCreateWithoutAuthorize-CICGmRFR.mjs";import Wo from"./packem_shared/paymentWebhookWideTolerance-CtZb2AVA.mjs";import To from"./packem_shared/plaintextSecretInWranglerVariables-bNkqmNqV.mjs";import Io from"./packem_shared/policyReferencesUnknownTable-CIKuRZ5Y.mjs";import ko from"./packem_shared/privilegedDispatchUnvalidatedPayload-DhXa36mM.mjs";import No from"./packem_shared/privilegedFanoutFromPublicProcedure-DV188gHQ.mjs";import xo from"./packem_shared/procedureWithoutStructuredEvent-CZ_B23nM.mjs";import Co from"./packem_shared/publicArgumentUsesAny-BDEvMA8Q.mjs";import Fo from"./packem_shared/publicMutationWithoutRatelimit-BeYapu1F.mjs";import Mo from"./packem_shared/publicTableRlsOptoutConfusion-BFmh1kH0.mjs";import Oo from"./packem_shared/queueWithoutDlq-BvHz3Opg.mjs";import Do from"./packem_shared/r2sqlOutsideAction-BdLiLOAX.mjs";import $o from"./packem_shared/ratelimitDefaultMemoryStore-Dj0Kk7t9.mjs";import Eo from"./packem_shared/ratelimitKeySpoofableOrGlobal-DlvJfSXs.mjs";import Po from"./packem_shared/ratelimitMiddlewareFailOpen-DGtyt-pc.mjs";import Ko from"./packem_shared/relationReferencesUnknownField-CqGEJD57.mjs";import qo from"./packem_shared/relationReferencesUnknownTable-CP4aWtAJ.mjs";import Lo from"./packem_shared/rlsUncoveredTable-CZ4ie4gX.mjs";import Go from"./packem_shared/shapeTargetsGlobalTable-Bu3eEDic.mjs";import _o from"./packem_shared/shapeUnknownTable-CREfNnWi.mjs";import zo from"./packem_shared/signupMutationWithoutDisposableGating-CFtFMJz8.mjs";import Ho from"./packem_shared/softDeleteIncludeDeletedFromArgs-C7Ugg4zb.mjs";import Bo from"./packem_shared/sqlInjectionRisk-y-7c46LJ.mjs";import jo from"./packem_shared/storageGenerateUploadUrlNoContentTypePin-Bx9oGOjM.mjs";import Vo from"./packem_shared/storageKeyFromUserArgs-BryKJJM-.mjs";import Qo from"./packem_shared/storagePresignedUrlForPrivateContent-lqE6LvNu.mjs";import Xo from"./packem_shared/storageUploadWithoutContentTypeAllowlist-DMr7w29r.mjs";import Zo from"./packem_shared/storageUploadWithoutMaxSize-rSNFNb2l.mjs";import Jo from"./packem_shared/tableWithoutInsert-ClJp_jDr.mjs";import Yo from"./packem_shared/topicTooManySubscriptions-CiZhFm9r.mjs";import oe from"./packem_shared/ttlFieldNotTimestamp-Dxa-6RfM.mjs";import{s as ee,q as re,c as te}from"./packem_shared/helpers-BmppB5nL.mjs";import ie from"./packem_shared/unboundedStringArgument-jZnCbwB0.mjs";import ne from"./packem_shared/unindexedForeignKey-Dypgn8uH.mjs";import ae from"./packem_shared/unindexedRelationTarget-CSqRJWYZ.mjs";import me from"./packem_shared/unrestrictedWhereBranch-CcIBmHik.mjs";import le from"./packem_shared/userCreatingMutationWithoutCaptcha-C8yaqIIj.mjs";import se from"./packem_shared/vectorsNamespaceFromUserInput-7I_Kwxvp.mjs";import pe from"./packem_shared/workflowDuplicateStepName-B6eAJzwA.mjs";import fe from"./packem_shared/workflowUnknownTarget-Cm1hfTTs.mjs";import ce from"./packem_shared/workflowUnused-DHwwE-1P.mjs";import{callSiteCallers as vt,callSiteDescription as At,callSiteLabel as Rt,callSiteMetadata as Ut,helperRole as Wt,isReachableSite as Tt,readCallSiteCallers as It}from"./packem_shared/callSiteCallers-DArHfQSU.mjs";import{compareToBaseline as Nt,parseAdvisorMap as xt}from"./packem_shared/compareToBaseline-CUG59IOy.mjs";import{gradeFromScore as Ft}from"./packem_shared/gradeFromScore-KSt58rj1.mjs";import{MAP_VERSION as Ot,byCodepoint as Dt,scoreAdvisor as $t}from"./packem_shared/MAP_VERSION-MQ5W2B6n.mjs";import{default as Pt}from"./packem_shared/classifySensitivity-JnjaTGYi.mjs";import{fromServerSchema as qt}from"./packem_shared/fromServerSchema-fAymN8o2.mjs";const de={convex:"migrating/from-convex",firebase:"migrating/from-firebase",supabase:"migrating/from-supabase"},m={categories:["SCHEMA"],description:"A migrated-away platform's SDK is still imported from `lunora/` source. The code compiles and typechecks, so a half-finished port keeps reading from the old platform at runtime and the two stores silently drift apart.",facing:"INTERNAL",level:"WARN",name:"migration_stale_import",remediation:"Replace the call with its Lunora equivalent and drop the dependency. If the import is deliberate — a second data source you still read from — move it out of `lunora/` so it is not mistaken for an unfinished migration.",run:r=>r.staleMigrationImports===void 0?[]:r.staleMigrationImports.map(o=>a(m,{cacheKey:`migration_stale_import:${o.file}:${o.line.toString()}:${o.moduleSpecifier}`,detail:`\`${o.file}\` (line ${o.line.toString()}) still imports \`${o.moduleSpecifier}\`. Finish the port — see \`${de[o.platform]}\` — or move the import out of \`lunora/\` if you genuinely still read from ${o.platform}.`,metadata:{file:o.file,line:o.line,moduleSpecifier:o.moduleSpecifier,platform:o.platform}})),source:"static",title:"Stale migration import"},ue=new Map([["global",{level:"WARN",scope:r=>`it reads the whole D1 table "${r}" over a cross-region round trip`}],["root",{level:"WARN",scope:r=>`it loads every row of "${r}" from the root Durable Object's SQLite into memory`}],["shardBy",{level:"INFO",scope:r=>`"${r}" is \`.shardBy()\`, so this collects one shard's rows rather than the whole table — bounded by a single tenant's row count`}]]),he={level:"WARN",scope:r=>`it loads every row of "${r}"`},l={categories:["PERFORMANCE"],description:"A query calls `.collect()` with no `.withIndex()` and no `.filter()`, so it materializes every row of the table. Any live subscription over it also re-sends that whole result to every subscribed client on every write to the table.",facing:"EXTERNAL",level:"WARN",name:"unbounded_collect",remediation:'Narrow the read with `.withIndex("name", (q) => q.eq(...))`, cap it with `.take(n)`, or page it with `.paginate(args.paginationOpts)` so neither the scan nor the subscription payload grows with the table.',run:r=>{const o=[],i=ee(r.schema);for(const e of r.queries??[]){if(e.terminal!=="collect"||e.hasIndex||e.table===""||e.hasFilter)continue;const t=i.get(e.table),{level:n,scope:s}=ue.get(t??"")??he,p=re(e),f=n==="WARN"?` A live subscription over this query records a whole-table dependency, so every write to "${e.table}" re-runs it and re-sends the full result to each subscribed socket.`:" Cap it with `.take(n)` if that count can grow.";o.push(a(l,{cacheKey:`unbounded_collect:${e.file}:${e.line.toString()}:${e.table}`,detail:`Query on "${e.table}" at ${p} calls .collect() with no index and no filter — ${s(e.table)}.${f}`,level:n,metadata:{...te(e),shardKind:t??"unknown",table:e.table}}))}return o},source:"static",title:"Unbounded collect"},ge=[mo,qo,Ko,fe,pe,_o,H,B,j,G,oo,_,J,Y,z,oe,O,M,q,ne,ae,L,Jo,ce,Oo,Yo,V,Q,l,Go,go,bo,yo,io,Do,U,Io,Lo,co,uo,$,E,Fo,me,le,zo,Co,ie,eo,Bo,y,Uo,po,$o,C,No,xo,lo,A,g,b,Ro,Vo,so,D,S,w,se,fo,F,ko,K,P,I,x,W,k,T,N,ao,Eo,Mo,R,Xo,Zo,jo,Qo,ro,to,Po,X,Z,v,no,Wo,Ho,ho,Ao,So,vo,wo,To,m],be=[u,h,d],ye=[...ge,...be],yt=(r,o={})=>{const i=o.lints??ye,e=[];for(const t of i)o.source!==void 0&&t.source!==o.source||e.push(...t.run(r));return c(e)};export{ye as ALL_LINTS,Ot as MAP_VERSION,be as RUNTIME_LINTS,ge as STATIC_LINTS,g as actionFetchSsrf,b as actionWithoutErrorHandling,y as adminRouteWithoutGuard,S as aiRawRunEscapeHatch,w as aiRunWithoutLogging,v as aiToolSideEffectPromptInjection,A as aiUnboundedGenerationPublic,R as allowUnauthenticatedShardAccessEnabled,U as authApiCallWithoutHeaders,W as authCsrfCheckDisabled,T as authEmailVerificationDisabled,I as authScimWithoutTransactions,k as authSecureCookiesDisabled,N as authSessionFreshageZero,x as authTrustedOriginsWildcard,C as browserAllowPrivateTargets,F as browserUserUrlWithoutAllowlist,Dt as byCodepoint,vt as callSiteCallers,At as callSiteDescription,Rt as callSiteLabel,Ut as callSiteMetadata,M as circularFk,Pt as classifySensitivity,O as commitOrderedHardDelete,Nt as compareToBaseline,D as containerInstanceKeyFromUserInput,$ as containerOversizedInstance,E as containerPublicInternet,P as containerRuntimeEgressRelaxation,K as containerStartEnableInternetOverride,q as crossModuleTableWrite,c as dedupeCacheKeys,L as duplicateIndex,G as emptyIndex,_ as errorWithoutCatalog,z as exportSinkMisconfigured,H as externalSourceIncrementalNoDeletePath,B as externalSourceOnGlobal,j as externalSourceUnscoped,d as fanOutBreadth,V as filterOnPrimaryKey,Q as filterWithoutIndex,X as flagGatesSecurityWithUnsafeDefault,Z as flagReadInSubscription,qt as fromServerSchema,J as geoIndexFieldNotGeopoint,Y as geoIndexUnused,oo as globalTableNearColumnLimit,Ft as gradeFromScore,eo as hardcodedSecret,Wt as helperRole,u as hotShard,ro as httpActionMissingAuthGuard,to as httpActionResponseHeaderInjection,io as hyperdriveOutsideAction,no as identityUndeclaredClaimTrusted,ao as imagesUrlSourceFromUserInput,mo as indexReferencesUnknownField,h as indexUtilization,lo as insertManyUnsafeUserData,Tt as isReachableSite,so as kvUnscopedUserKeyIdor,po as mailInboundDispatchWithoutVerify,fo as mailRecipientFromRequestInput,co as maskUncoveredPiiColumn,uo as maskWeakHashStrategyOnPii,ho as maskedRelationLeakViaWith,go as mutatorFullRowReplace,bo as mutatorWithoutOwnerScope,yo as nondeterministicQueryMutation,So as normalizeIdUsedAsAuthorization,wo as notifyMissingPushConfig,vo as notifySendOutsideAction,Ao as outputProjectionMissingOnPublicRead,Ro as ownerFieldFromArgsNotAuth,xt as parseAdvisorMap,Uo as paymentCreateWithoutAuthorize,Wo as paymentWebhookWideTolerance,To as plaintextSecretInWranglerVariables,Io as policyReferencesUnknownTable,ko as privilegedDispatchUnvalidatedPayload,No as privilegedFanoutFromPublicProcedure,xo as procedureWithoutStructuredEvent,Co as publicArgumentUsesAny,Fo as publicMutationWithoutRatelimit,Mo as publicTableRlsOptoutConfusion,Oo as queueWithoutDlq,Do as r2sqlOutsideAction,$o as ratelimitDefaultMemoryStore,Eo as ratelimitKeySpoofableOrGlobal,Po as ratelimitMiddlewareFailOpen,It as readCallSiteCallers,Ko as relationReferencesUnknownField,qo as relationReferencesUnknownTable,Lo as rlsUncoveredTable,yt as runAdvisor,$t as scoreAdvisor,Go as shapeTargetsGlobalTable,_o as shapeUnknownTable,zo as signupMutationWithoutDisposableGating,Ho as softDeleteIncludeDeletedFromArgs,Bo as sqlInjectionRisk,jo as storageGenerateUploadUrlNoContentTypePin,Vo as storageKeyFromUserArgs,Qo as storagePresignedUrlForPrivateContent,Xo as storageUploadWithoutContentTypeAllowlist,Zo as storageUploadWithoutMaxSize,Jo as tableWithoutInsert,Yo as topicTooManySubscriptions,oe as ttlFieldNotTimestamp,ie as unboundedStringArgument,ne as unindexedForeignKey,ae as unindexedRelationTarget,me as unrestrictedWhereBranch,le as userCreatingMutationWithoutCaptcha,se as vectorsNamespaceFromUserInput,pe as workflowDuplicateStepName,fe as workflowUnknownTarget,ce as workflowUnused};
|
|
1
|
+
import{dedupeCacheKeys as c}from"./packem_shared/dedupeCacheKeys-DtBOHffV.mjs";import d from"./packem_shared/fanOutBreadth-CBtmZnoh.mjs";import u from"./packem_shared/hotShard-BwGYZ3Tq.mjs";import h from"./packem_shared/indexUtilization-CkVPZcVe.mjs";import g from"./packem_shared/actionFetchSsrf-B4ZaOBlW.mjs";import b from"./packem_shared/actionWithoutErrorHandling-4GCBT0_z.mjs";import y from"./packem_shared/adminRouteWithoutGuard-DPE7LuNh.mjs";import S from"./packem_shared/aiRawRunEscapeHatch-B5980eT9.mjs";import w from"./packem_shared/aiRunWithoutLogging-CvHHtEN9.mjs";import v from"./packem_shared/aiToolSideEffectPromptInjection-_3MrX9Ul.mjs";import A from"./packem_shared/aiUnboundedGenerationPublic-C17h6sMV.mjs";import R from"./packem_shared/allowUnauthenticatedShardAccessEnabled-BQufF5Kb.mjs";import U from"./packem_shared/authApiCallWithoutHeaders-D8U1hv8s.mjs";import W from"./packem_shared/authCsrfCheckDisabled-C6bxME5y.mjs";import T from"./packem_shared/authEmailVerificationDisabled-yROPDgn-.mjs";import I from"./packem_shared/authScimWithoutTransactions-w9qb3iBe.mjs";import k from"./packem_shared/authSecureCookiesDisabled-qrCktlch.mjs";import C from"./packem_shared/authSessionFreshageZero-BMisjIIS.mjs";import N from"./packem_shared/authTrustedOriginsWildcard-DFDpfN84.mjs";import x from"./packem_shared/browserAllowPrivateTargets-Cj5sizhv.mjs";import F from"./packem_shared/browserUserUrlWithoutAllowlist-CcK27rvt.mjs";import M from"./packem_shared/circularFk-DtcWFJxK.mjs";import O from"./packem_shared/commitOrderedHardDelete-BPdwOKA7.mjs";import D from"./packem_shared/containerInstanceKeyFromUserInput-DBdjUnQb.mjs";import $ from"./packem_shared/containerOversizedInstance-Bx89uR7E.mjs";import E from"./packem_shared/containerPublicInternet-BFfZf_P4.mjs";import P from"./packem_shared/containerRuntimeEgressRelaxation-CioCA2zY.mjs";import K from"./packem_shared/containerStartEnableInternetOverride-C6dbznku.mjs";import L from"./packem_shared/crossModuleTableWrite-DjiVTAwK.mjs";import q from"./packem_shared/dispatchCycle-CWc5Q0cd.mjs";import G from"./packem_shared/duplicateIndex-Cip6-Rpu.mjs";import _ from"./packem_shared/emptyIndex-BnHDcXza.mjs";import z from"./packem_shared/errorWithoutCatalog-BTfvaXHR.mjs";import H from"./packem_shared/exportSinkMisconfigured-JfbAx9AI.mjs";import B from"./packem_shared/externalSourceIncrementalNoDeletePath-BCzm3HzF.mjs";import j from"./packem_shared/externalSourceOnGlobal-CH7xbJ49.mjs";import V from"./packem_shared/externalSourceUnscoped-BxU2uSXk.mjs";import Q from"./packem_shared/filterOnPrimaryKey-DbFriOZA.mjs";import X from"./packem_shared/filterWithoutIndex-Dc7Nn0y2.mjs";import Z from"./packem_shared/flagGatesSecurityWithUnsafeDefault-DB9M6hLM.mjs";import J from"./packem_shared/flagReadInSubscription-DabIhYGD.mjs";import Y from"./packem_shared/geoIndexFieldNotGeopoint-CDMNbAfp.mjs";import oo from"./packem_shared/geoIndexUnused-D7C9Qr4U.mjs";import eo from"./packem_shared/globalTableNearColumnLimit-BFbBBd6A.mjs";import ro from"./packem_shared/hardcodedSecret-Bw_4FYrs.mjs";import to from"./packem_shared/httpActionMissingAuthGuard-BhvcmkwW.mjs";import io from"./packem_shared/httpActionResponseHeaderInjection-DKz2SlCa.mjs";import no from"./packem_shared/hyperdriveOutsideAction-CPDdGP2g.mjs";import ao from"./packem_shared/identityUndeclaredClaimTrusted-CAUagXkJ.mjs";import mo from"./packem_shared/imagesUrlSourceFromUserInput-C2CJTTCI.mjs";import lo from"./packem_shared/indexReferencesUnknownField-Dm8SL4Tp.mjs";import so from"./packem_shared/insertManyUnsafeUserData-DWE8d_DF.mjs";import po from"./packem_shared/kvUnscopedUserKeyIdor-CXFKAyM2.mjs";import fo from"./packem_shared/mailInboundDispatchWithoutVerify-CWwqXyPX.mjs";import co from"./packem_shared/mailRecipientFromRequestInput-CQZeOsP9.mjs";import uo from"./packem_shared/maskUncoveredPiiColumn-axEka4nd.mjs";import ho from"./packem_shared/maskWeakHashStrategyOnPii-njstapQY.mjs";import go from"./packem_shared/maskedRelationLeakViaWith-CIFij6vE.mjs";import{e as a}from"./packem_shared/finding-NrKO8idM.mjs";import bo from"./packem_shared/mutatorFullRowReplace-BzRpZ47r.mjs";import yo from"./packem_shared/mutatorWithoutOwnerScope-BoS81ns0.mjs";import So from"./packem_shared/nondeterministicQueryMutation-sxmixc0l.mjs";import wo from"./packem_shared/normalizeIdUsedAsAuthorization-BXN-Can6.mjs";import vo from"./packem_shared/notifyMissingPushConfig-DeQMoNwm.mjs";import Ao from"./packem_shared/notifySendOutsideAction-BJrDkr4h.mjs";import Ro from"./packem_shared/outputProjectionMissingOnPublicRead-DHivs_73.mjs";import Uo from"./packem_shared/ownerFieldFromArgsNotAuth-BBFBPfCJ.mjs";import Wo from"./packem_shared/paymentCreateWithoutAuthorize-CICGmRFR.mjs";import To from"./packem_shared/paymentWebhookWideTolerance-CtZb2AVA.mjs";import Io from"./packem_shared/plaintextSecretInWranglerVariables-bNkqmNqV.mjs";import ko from"./packem_shared/policyReferencesUnknownTable-CIKuRZ5Y.mjs";import Co from"./packem_shared/privilegedDispatchUnvalidatedPayload-DlJovHrt.mjs";import No from"./packem_shared/privilegedFanoutFromPublicProcedure-DV188gHQ.mjs";import xo from"./packem_shared/procedureWithoutStructuredEvent-CZ_B23nM.mjs";import Fo from"./packem_shared/publicArgumentUsesAny-BDEvMA8Q.mjs";import Mo from"./packem_shared/publicMutationWithoutRatelimit-BeYapu1F.mjs";import Oo from"./packem_shared/publicTableRlsOptoutConfusion-BFmh1kH0.mjs";import Do from"./packem_shared/queueWithoutDlq-BvHz3Opg.mjs";import $o from"./packem_shared/r2sqlOutsideAction-BdLiLOAX.mjs";import Eo from"./packem_shared/ratelimitDefaultMemoryStore-Dj0Kk7t9.mjs";import Po from"./packem_shared/ratelimitKeySpoofableOrGlobal-DlvJfSXs.mjs";import Ko from"./packem_shared/ratelimitMiddlewareFailOpen-DGtyt-pc.mjs";import Lo from"./packem_shared/relationReferencesUnknownField-CqGEJD57.mjs";import qo from"./packem_shared/relationReferencesUnknownTable-CP4aWtAJ.mjs";import Go from"./packem_shared/rlsUncoveredTable-CZ4ie4gX.mjs";import _o from"./packem_shared/shapeTargetsGlobalTable-Bu3eEDic.mjs";import zo from"./packem_shared/shapeUnknownTable-CREfNnWi.mjs";import Ho from"./packem_shared/signupMutationWithoutDisposableGating-CFtFMJz8.mjs";import Bo from"./packem_shared/softDeleteIncludeDeletedFromArgs-C7Ugg4zb.mjs";import jo from"./packem_shared/sqlInjectionRisk-y-7c46LJ.mjs";import Vo from"./packem_shared/storageGenerateUploadUrlNoContentTypePin-Bx9oGOjM.mjs";import Qo from"./packem_shared/storageKeyFromUserArgs-BryKJJM-.mjs";import Xo from"./packem_shared/storagePresignedUrlForPrivateContent-lqE6LvNu.mjs";import Zo from"./packem_shared/storageUploadWithoutContentTypeAllowlist-DMr7w29r.mjs";import Jo from"./packem_shared/storageUploadWithoutMaxSize-rSNFNb2l.mjs";import Yo from"./packem_shared/tableWithoutInsert-ClJp_jDr.mjs";import oe from"./packem_shared/topicTooManySubscriptions-CiZhFm9r.mjs";import ee from"./packem_shared/ttlFieldNotTimestamp-Dxa-6RfM.mjs";import{s as re,q as te,c as ie}from"./packem_shared/helpers-BmppB5nL.mjs";import ne from"./packem_shared/unboundedLoop-BqbZ7boE.mjs";import ae from"./packem_shared/unboundedStringArgument-jZnCbwB0.mjs";import me from"./packem_shared/unindexedForeignKey-Dypgn8uH.mjs";import le from"./packem_shared/unindexedRelationTarget-CSqRJWYZ.mjs";import se from"./packem_shared/unrestrictedWhereBranch-CcIBmHik.mjs";import pe from"./packem_shared/userCreatingMutationWithoutCaptcha-C8yaqIIj.mjs";import fe from"./packem_shared/vectorsNamespaceFromUserInput-7I_Kwxvp.mjs";import ce from"./packem_shared/workflowDuplicateStepName-B6eAJzwA.mjs";import de from"./packem_shared/workflowUnknownTarget-Cm1hfTTs.mjs";import ue from"./packem_shared/workflowUnused-DHwwE-1P.mjs";import{callSiteCallers as Wt,callSiteDescription as Tt,callSiteLabel as It,callSiteMetadata as kt,helperRole as Ct,isReachableSite as Nt,readCallSiteCallers as xt}from"./packem_shared/callSiteCallers-DArHfQSU.mjs";import{compareToBaseline as Mt,parseAdvisorMap as Ot}from"./packem_shared/compareToBaseline-CUG59IOy.mjs";import{gradeFromScore as $t}from"./packem_shared/gradeFromScore-KSt58rj1.mjs";import{MAP_VERSION as Pt,byCodepoint as Kt,scoreAdvisor as Lt}from"./packem_shared/MAP_VERSION-MQ5W2B6n.mjs";import{default as Gt}from"./packem_shared/classifySensitivity-JnjaTGYi.mjs";import{fromServerSchema as zt}from"./packem_shared/fromServerSchema-fAymN8o2.mjs";const he={convex:"migrating/from-convex",firebase:"migrating/from-firebase",supabase:"migrating/from-supabase"},m={categories:["SCHEMA"],description:"A migrated-away platform's SDK is still imported from `lunora/` source. The code compiles and typechecks, so a half-finished port keeps reading from the old platform at runtime and the two stores silently drift apart.",facing:"INTERNAL",level:"WARN",name:"migration_stale_import",remediation:"Replace the call with its Lunora equivalent and drop the dependency. If the import is deliberate — a second data source you still read from — move it out of `lunora/` so it is not mistaken for an unfinished migration.",run:r=>r.staleMigrationImports===void 0?[]:r.staleMigrationImports.map(o=>a(m,{cacheKey:`migration_stale_import:${o.file}:${o.line.toString()}:${o.moduleSpecifier}`,detail:`\`${o.file}\` (line ${o.line.toString()}) still imports \`${o.moduleSpecifier}\`. Finish the port — see \`${he[o.platform]}\` — or move the import out of \`lunora/\` if you genuinely still read from ${o.platform}.`,metadata:{file:o.file,line:o.line,moduleSpecifier:o.moduleSpecifier,platform:o.platform}})),source:"static",title:"Stale migration import"},ge=new Map([["global",{level:"WARN",scope:r=>`it reads the whole D1 table "${r}" over a cross-region round trip`}],["root",{level:"WARN",scope:r=>`it loads every row of "${r}" from the root Durable Object's SQLite into memory`}],["shardBy",{level:"INFO",scope:r=>`"${r}" is \`.shardBy()\`, so this collects one shard's rows rather than the whole table — bounded by a single tenant's row count`}]]),be={level:"WARN",scope:r=>`it loads every row of "${r}"`},l={categories:["PERFORMANCE"],description:"A query calls `.collect()` with no `.withIndex()` and no `.filter()`, so it materializes every row of the table. Any live subscription over it also re-sends that whole result to every subscribed client on every write to the table.",facing:"EXTERNAL",level:"WARN",name:"unbounded_collect",remediation:'Narrow the read with `.withIndex("name", (q) => q.eq(...))`, cap it with `.take(n)`, or page it with `.paginate(args.paginationOpts)` so neither the scan nor the subscription payload grows with the table.',run:r=>{const o=[],i=re(r.schema);for(const e of r.queries??[]){if(e.terminal!=="collect"||e.hasIndex||e.table===""||e.hasFilter)continue;const t=i.get(e.table),{level:n,scope:s}=ge.get(t??"")??be,p=te(e),f=n==="WARN"?` A live subscription over this query records a whole-table dependency, so every write to "${e.table}" re-runs it and re-sends the full result to each subscribed socket.`:" Cap it with `.take(n)` if that count can grow.";o.push(a(l,{cacheKey:`unbounded_collect:${e.file}:${e.line.toString()}:${e.table}`,detail:`Query on "${e.table}" at ${p} calls .collect() with no index and no filter — ${s(e.table)}.${f}`,level:n,metadata:{...ie(e),shardKind:t??"unknown",table:e.table}}))}return o},source:"static",title:"Unbounded collect"},ye=[lo,qo,Lo,de,ce,zo,B,j,V,_,eo,z,Y,oo,H,ee,O,M,L,me,le,G,Yo,ue,Do,oe,Q,X,l,ne,q,_o,bo,yo,So,no,$o,U,ko,Go,uo,ho,$,E,Mo,se,pe,Ho,Fo,ae,ro,jo,y,Wo,fo,Eo,x,No,xo,so,A,g,b,Uo,Qo,po,D,S,w,fe,co,F,Co,K,P,I,N,W,k,T,C,mo,Po,Oo,R,Zo,Jo,Vo,Xo,to,io,Ko,Z,J,v,ao,To,Bo,go,Ro,wo,Ao,vo,Io,m],Se=[u,h,d],we=[...ye,...Se],At=(r,o={})=>{const i=o.lints??we,e=[];for(const t of i)o.source!==void 0&&t.source!==o.source||e.push(...t.run(r));return c(e)};export{we as ALL_LINTS,Pt as MAP_VERSION,Se as RUNTIME_LINTS,ye as STATIC_LINTS,g as actionFetchSsrf,b as actionWithoutErrorHandling,y as adminRouteWithoutGuard,S as aiRawRunEscapeHatch,w as aiRunWithoutLogging,v as aiToolSideEffectPromptInjection,A as aiUnboundedGenerationPublic,R as allowUnauthenticatedShardAccessEnabled,U as authApiCallWithoutHeaders,W as authCsrfCheckDisabled,T as authEmailVerificationDisabled,I as authScimWithoutTransactions,k as authSecureCookiesDisabled,C as authSessionFreshageZero,N as authTrustedOriginsWildcard,x as browserAllowPrivateTargets,F as browserUserUrlWithoutAllowlist,Kt as byCodepoint,Wt as callSiteCallers,Tt as callSiteDescription,It as callSiteLabel,kt as callSiteMetadata,M as circularFk,Gt as classifySensitivity,O as commitOrderedHardDelete,Mt as compareToBaseline,D as containerInstanceKeyFromUserInput,$ as containerOversizedInstance,E as containerPublicInternet,P as containerRuntimeEgressRelaxation,K as containerStartEnableInternetOverride,L as crossModuleTableWrite,c as dedupeCacheKeys,q as dispatchCycle,G as duplicateIndex,_ as emptyIndex,z as errorWithoutCatalog,H as exportSinkMisconfigured,B as externalSourceIncrementalNoDeletePath,j as externalSourceOnGlobal,V as externalSourceUnscoped,d as fanOutBreadth,Q as filterOnPrimaryKey,X as filterWithoutIndex,Z as flagGatesSecurityWithUnsafeDefault,J as flagReadInSubscription,zt as fromServerSchema,Y as geoIndexFieldNotGeopoint,oo as geoIndexUnused,eo as globalTableNearColumnLimit,$t as gradeFromScore,ro as hardcodedSecret,Ct as helperRole,u as hotShard,to as httpActionMissingAuthGuard,io as httpActionResponseHeaderInjection,no as hyperdriveOutsideAction,ao as identityUndeclaredClaimTrusted,mo as imagesUrlSourceFromUserInput,lo as indexReferencesUnknownField,h as indexUtilization,so as insertManyUnsafeUserData,Nt as isReachableSite,po as kvUnscopedUserKeyIdor,fo as mailInboundDispatchWithoutVerify,co as mailRecipientFromRequestInput,uo as maskUncoveredPiiColumn,ho as maskWeakHashStrategyOnPii,go as maskedRelationLeakViaWith,bo as mutatorFullRowReplace,yo as mutatorWithoutOwnerScope,So as nondeterministicQueryMutation,wo as normalizeIdUsedAsAuthorization,vo as notifyMissingPushConfig,Ao as notifySendOutsideAction,Ro as outputProjectionMissingOnPublicRead,Uo as ownerFieldFromArgsNotAuth,Ot as parseAdvisorMap,Wo as paymentCreateWithoutAuthorize,To as paymentWebhookWideTolerance,Io as plaintextSecretInWranglerVariables,ko as policyReferencesUnknownTable,Co as privilegedDispatchUnvalidatedPayload,No as privilegedFanoutFromPublicProcedure,xo as procedureWithoutStructuredEvent,Fo as publicArgumentUsesAny,Mo as publicMutationWithoutRatelimit,Oo as publicTableRlsOptoutConfusion,Do as queueWithoutDlq,$o as r2sqlOutsideAction,Eo as ratelimitDefaultMemoryStore,Po as ratelimitKeySpoofableOrGlobal,Ko as ratelimitMiddlewareFailOpen,xt as readCallSiteCallers,Lo as relationReferencesUnknownField,qo as relationReferencesUnknownTable,Go as rlsUncoveredTable,At as runAdvisor,Lt as scoreAdvisor,_o as shapeTargetsGlobalTable,zo as shapeUnknownTable,Ho as signupMutationWithoutDisposableGating,Bo as softDeleteIncludeDeletedFromArgs,jo as sqlInjectionRisk,Vo as storageGenerateUploadUrlNoContentTypePin,Qo as storageKeyFromUserArgs,Xo as storagePresignedUrlForPrivateContent,Zo as storageUploadWithoutContentTypeAllowlist,Jo as storageUploadWithoutMaxSize,Yo as tableWithoutInsert,oe as topicTooManySubscriptions,ee as ttlFieldNotTimestamp,ne as unboundedLoop,ae as unboundedStringArgument,me as unindexedForeignKey,le as unindexedRelationTarget,se as unrestrictedWhereBranch,pe as userCreatingMutationWithoutCaptcha,fe as vectorsNamespaceFromUserInput,ce as workflowDuplicateStepName,de as workflowUnknownTarget,ue as workflowUnused};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const a=/\/index$/u,n=/[^\dA-Za-z]/gu,c=e=>e.replace(a,"").split("/").map(s=>s.replaceAll(n,"_")),t=e=>c(e).join("_");export{t as s};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{s as f}from"./dispatch-namespace-BE_LxN7Z.mjs";import{e as h}from"./finding-NrKO8idM.mjs";const p=i=>{const c=[];for(const t of i)(t.kind==="call"||t.kind==="schedule")&&t.target!==void 0&&t.conditional!==!0&&t.scope.kind==="export"&&c.push({file:t.file,from:`${f(t.file)}:${t.scope.name}`,kind:t.kind,line:t.line,to:t.target});return c},m=(i,c)=>{const t=new Map,n=new Set,s=[],a=[],d=e=>{const o={index:t.size,lowLink:t.size};t.set(e,o),s.push(e),n.add(e);for(const l of c.get(e)??[]){const r=t.get(l);r===void 0?o.lowLink=Math.min(o.lowLink,d(l).lowLink):n.has(l)&&(o.lowLink=Math.min(o.lowLink,r.index))}if(o.lowLink===o.index){const l=[];for(let r=s.pop();r!==void 0;r=r===e?void 0:s.pop())n.delete(r),l.push(r);a.push(l)}return o};for(const e of i)t.has(e)||d(e);return a},u=i=>`\`${i.from}\` ${i.kind==="schedule"?"schedules":"calls"} \`${i.to}\` (${i.file}:${i.line.toString()})`,k={categories:["PERFORMANCE"],description:"Functions dispatch each other (or themselves) in a cycle where every hop is unconditional — no guard, loop, `try`, or early return in front of any of them. Once one of them runs, the chain re-schedules itself forever, and every storage read or write along it is billed on every pass.",facing:"EXTERNAL",level:"ERROR",name:"dispatch_cycle",remediation:"Put a stop condition in front of the re-dispatch: reschedule only while there is work left (`if (remaining > 0) await ctx.scheduler.runAfter(…)`), carry an attempt counter in the args and stop at a cap, keep the returned id so a stop path can `ctx.scheduler.cancel` it, or move periodic work to a `cron`. If the chain already stops by throwing from a helper, make that stop condition explicit at the call site.",run:i=>{if(i.callEdges===void 0)return[];const c=p(i.callEdges),t=new Map;for(const n of c){const s=t.get(n.from);s===void 0?t.set(n.from,[n.to]):s.push(n.to)}return m([...t.keys()].toSorted((n,s)=>n.localeCompare(s)),t).flatMap(n=>{const s=new Set(n),a=c.filter(e=>s.has(e.from)&&s.has(e.to)).toSorted((e,o)=>e.from.localeCompare(o.from)||e.file.localeCompare(o.file)||e.line-o.line);if(a.length===0)return[];const d=n.toSorted((e,o)=>e.localeCompare(o));return[h(k,{cacheKey:`dispatch_cycle:${d.join(",")}`,detail:`Unconditional dispatch cycle: ${a.map(e=>u(e)).join("; ")}. No guard stands in front of any hop, so once one of these functions runs the chain never stops.`,metadata:{functions:d,hops:a.map(e=>({file:e.file,from:e.from,kind:e.kind,line:e.line,to:e.to}))}})]})},source:"static",title:"Endless dispatch cycle"};export{k as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{e as a}from"./finding-NrKO8idM.mjs";import{a as o,c as s}from"./helpers-BmppB5nL.mjs";const i={categories:["SECURITY"],description:"A `ctx.db` write sets an ownership/identity column (`userId`, `ownerId`, `tenantId`, …) from the handler's `args`. The caller controls who the row belongs to, so any caller can write rows owned by another user or tenant — an act-as-any-user / cross-tenant IDOR.",facing:"EXTERNAL",level:"ERROR",name:"owner_field_from_args_not_auth",remediation:"Stamp the ownership column from the server-trusted identity (`ctx.auth.userId` / `ctx.identity`), never from request input. Drop the field from the accepted `args` so a caller cannot supply it. In an `owner`-scoped `defineMutator`, `args[owner]` is verified only while the `server` impl leaves `args` untouched: a `server` impl that uses `this` or refers to itself (its own name, or `<mutator>.server`) is reported, because it could re-enter with unverified args. Handing `args` to a function codegen cannot read (an imported validator) also counts as touching it; validate in a function declared in the same file that only reads its argument, or validate a copy (`{ ...args }`).",run:t=>t.ownerFieldWrites===void 0?[]:t.ownerFieldWrites.flatMap(e=>{if(e.ownerScoped)return[];const r=`\`${e.method}\` in ${o(e)}`,n={...s(e),field:e.field,method:e.method,visibility:e.visibility??"unknown"};return e.visibility==="internal"?[a(i,{cacheKey:`owner_field_from_args_not_auth:${e.file}:${e.line.toString()}:${e.field}`,detail:`${r} sets the ownership field \`${e.field}\` from \`args\`. This is expected for an \`internal\` procedure — no caller can reach it directly, and the trusted caller passes the subject along. Audit the PUBLIC procedures that dispatch to it: if one forwards \`args.${e.field}\` straight through, the IDOR is there.`,facing:"INTERNAL",level:"INFO",metadata:n})]:[a(i,{cacheKey:`owner_field_from_args_not_auth:${e.file}:${e.line.toString()}:${e.field}`,detail:`${r} sets the ownership field \`${e.field}\` from \`args\` instead of the server-trusted identity — any caller can write rows owned by another user/tenant (IDOR). Stamp \`${e.field}\` from \`ctx.auth\`/\`ctx.identity\`, never from request input.`,metadata:n})]}),source:"static",title:"Ownership field written from args, not server identity"};export{i as default};
|
|
1
|
+
import{e as a}from"./finding-NrKO8idM.mjs";import{a as o,c as s}from"./helpers-BmppB5nL.mjs";const i={categories:["SECURITY"],description:"A `ctx.db` write sets an ownership/identity column (`userId`, `ownerId`, `tenantId`, …) from the handler's `args`. The caller controls who the row belongs to, so any caller can write rows owned by another user or tenant — an act-as-any-user / cross-tenant IDOR.",facing:"EXTERNAL",level:"ERROR",name:"owner_field_from_args_not_auth",remediation:"Stamp the ownership column from the server-trusted identity (`ctx.auth.userId` / `ctx.identity`), never from request input. Drop the field from the accepted `args` so a caller cannot supply it. In an `owner`-scoped `defineMutator`, `args[owner]` is verified only while the `server` impl leaves `args` untouched: a `server` impl that uses `this` or refers to itself (its own name, or `<mutator>.server`) is reported, because it could re-enter with unverified args. Handing `args` to a function codegen cannot read (an imported validator) also counts as touching it; validate in a function declared in the same file that only reads its argument, or validate a copy (`{ ...args }`).",run:t=>t.ownerFieldWrites===void 0?[]:t.ownerFieldWrites.flatMap(e=>{if(e.ownerScoped)return[];if(e.guarded)return[];const r=`\`${e.method}\` in ${o(e)}`,n={...s(e),field:e.field,method:e.method,visibility:e.visibility??"unknown"};return e.visibility==="internal"?[a(i,{cacheKey:`owner_field_from_args_not_auth:${e.file}:${e.line.toString()}:${e.field}`,detail:`${r} sets the ownership field \`${e.field}\` from \`args\`. This is expected for an \`internal\` procedure — no caller can reach it directly, and the trusted caller passes the subject along. Audit the PUBLIC procedures that dispatch to it: if one forwards \`args.${e.field}\` straight through, the IDOR is there.`,facing:"INTERNAL",level:"INFO",metadata:n})]:[a(i,{cacheKey:`owner_field_from_args_not_auth:${e.file}:${e.line.toString()}:${e.field}`,detail:`${r} sets the ownership field \`${e.field}\` from \`args\` instead of the server-trusted identity — any caller can write rows owned by another user/tenant (IDOR). Stamp \`${e.field}\` from \`ctx.auth\`/\`ctx.identity\`, never from request input.`,metadata:n})]}),source:"static",title:"Ownership field written from args, not server identity"};export{i as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{s as i}from"./dispatch-namespace-BE_LxN7Z.mjs";import{callSiteMetadata as n}from"./callSiteCallers-DArHfQSU.mjs";import{e as l}from"./finding-NrKO8idM.mjs";import{a as d}from"./helpers-BmppB5nL.mjs";const u={categories:["SECURITY"],description:"A `defineQueue`/`defineWorkflow` handler forwards its untrusted payload (queue body / workflow params) straight into a `ctx.run` dispatch whose target is RLS-gated. The handler runs under the system identity with RLS disabled, so the target's row policy — the only thing guarding it — is bypassed, letting a caller act as any user / write across tenants.",facing:"EXTERNAL",level:"ERROR",name:"privileged_dispatch_unvalidated_payload",remediation:"Don't forward an unchecked queue body / workflow param into an RLS-gated function. Re-derive the ownership/identity keys from server-trusted state (or an argument you validate against it) before dispatching, or route the work through a function that re-checks the caller's identity rather than relying on the row policy the privileged handler skips.",run:r=>{if(r.privilegedDispatches===void 0)return[];const s=r.rlsProcedures??[],o=(e,a)=>s.some(t=>t.usesRls&&i(t.file)===i(e)&&t.exportName===a);return r.privilegedDispatches.filter(e=>o(e.targetFile,e.targetExport)).map(e=>{const a=e.dispatchKind==="queue"?"queue":"workflow",t=e.dispatchKind==="queue"?"queue message body":"workflow params";return l(u,{cacheKey:`privileged_dispatch_unvalidated_payload:${e.file}:${e.line.toString()}`,detail:`The ${a} handler ${d(e)} forwards its untrusted ${t} straight into \`${e.targetFile}.${e.targetExport}\`, which is guarded by \`.use(rls(...))\`. The handler runs under the system identity with RLS disabled, so the target's row policy is bypassed — any ownership/identity field the payload controls lets a caller act as another user or write across tenants. Re-derive the identity keys from server-trusted state before dispatching, or route through a function that re-checks the caller.`,metadata:{dispatchKind:e.dispatchKind,file:e.file,...n(e.scope),line:e.line,targetExport:e.targetExport,targetFile:e.targetFile}})})},source:"static",title:"Privileged handler forwards untrusted payload into an RLS-gated function"};export{u as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{isReachableSite as r,callSiteLabel as i}from"./callSiteCallers-DArHfQSU.mjs";import{e as n}from"./finding-NrKO8idM.mjs";import{c as o,a}from"./helpers-BmppB5nL.mjs";const l={do:"`do { … } while (true)`",for:"`for (;;)`",while:"`while (true)`"},d={categories:["PERFORMANCE"],description:"A literal-infinite loop (`while (true)`, `for (;;)`, `do … while (true)`) has no `break`, `return` or `throw` that can leave it. Once entered it never ends: inside a Durable Object it holds the object forever, and every storage read or write in its body is billed on every turn.",facing:"EXTERNAL",level:"ERROR",name:"unbounded_loop",remediation:"Give the loop an exit: loop on a real condition (`while (cursor !== null)`), `break` when the work runs out, or cap it with an iteration budget. An `await` is not an exit: a long-polling `while (true)` worker is rejected unless it can still leave — check `signal.throwIfAborted()` each turn, `break` when the source closes, or stop at a deadline. For recurring work, do one batch per invocation and re-arm with `ctx.scheduler.runAfter(…)` behind a guard that stops when nothing is left.",run:t=>t.unboundedLoops===void 0?[]:t.unboundedLoops.filter(e=>e.scope.kind==="module"||r(e.scope)).map(e=>n(d,{cacheKey:`unbounded_loop:${e.file}:${i(e.scope)}:${e.kind}`,detail:`${l[e.kind]} in ${a(e)} has no \`break\`, \`return\` or \`throw\` that can leave it — once entered it never ends, and every storage call in its body is billed on every turn.`,metadata:{...o(e),loop:e.kind}})),source:"static",title:"Infinite loop with no exit"};export{d as default};
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{callSiteMetadata as n}from"./callSiteCallers-DArHfQSU.mjs";import{e as l}from"./finding-NrKO8idM.mjs";import{a as d}from"./helpers-BmppB5nL.mjs";const u=/\/index$/u,h=/[^\dA-Za-z]/gu,i=t=>t.replace(u,"").replaceAll(h,"_"),c={categories:["SECURITY"],description:"A `defineQueue`/`defineWorkflow` handler forwards its untrusted payload (queue body / workflow params) straight into a `ctx.run` dispatch whose target is RLS-gated. The handler runs under the system identity with RLS disabled, so the target's row policy — the only thing guarding it — is bypassed, letting a caller act as any user / write across tenants.",facing:"EXTERNAL",level:"ERROR",name:"privileged_dispatch_unvalidated_payload",remediation:"Don't forward an unchecked queue body / workflow param into an RLS-gated function. Re-derive the ownership/identity keys from server-trusted state (or an argument you validate against it) before dispatching, or route the work through a function that re-checks the caller's identity rather than relying on the row policy the privileged handler skips.",run:t=>{if(t.privilegedDispatches===void 0)return[];const s=t.rlsProcedures??[],o=(e,a)=>s.some(r=>r.usesRls&&i(r.file)===i(e)&&r.exportName===a);return t.privilegedDispatches.filter(e=>o(e.targetFile,e.targetExport)).map(e=>{const a=e.dispatchKind==="queue"?"queue":"workflow",r=e.dispatchKind==="queue"?"queue message body":"workflow params";return l(c,{cacheKey:`privileged_dispatch_unvalidated_payload:${e.file}:${e.line.toString()}`,detail:`The ${a} handler ${d(e)} forwards its untrusted ${r} straight into \`${e.targetFile}.${e.targetExport}\`, which is guarded by \`.use(rls(...))\`. The handler runs under the system identity with RLS disabled, so the target's row policy is bypassed — any ownership/identity field the payload controls lets a caller act as another user or write across tenants. Re-derive the identity keys from server-trusted state before dispatching, or route through a function that re-checks the caller.`,metadata:{dispatchKind:e.dispatchKind,file:e.file,...n(e.scope),line:e.line,targetExport:e.targetExport,targetFile:e.targetFile}})})},source:"static",title:"Privileged handler forwards untrusted payload into an RLS-gated function"};export{c as default};
|