@lunora/advisor 1.0.0-alpha.21 → 1.0.0-alpha.211
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/README.md +64 -7
- package/dist/index.d.mts +4107 -2575
- package/dist/index.d.ts +4107 -2575
- package/dist/index.mjs +1 -181
- package/dist/packem_shared/MAP_VERSION-MQ5W2B6n.mjs +1 -0
- package/dist/packem_shared/actionFetchSsrf-BK-kvOPO.mjs +1 -0
- package/dist/packem_shared/actionWithoutErrorHandling-4GCBT0_z.mjs +1 -0
- package/dist/packem_shared/adminRouteWithoutGuard-DPE7LuNh.mjs +1 -0
- package/dist/packem_shared/aiRawRunEscapeHatch-BW7a8kZC.mjs +1 -0
- package/dist/packem_shared/aiRunWithoutLogging-CvHHtEN9.mjs +1 -0
- package/dist/packem_shared/aiToolSideEffectPromptInjection-9eJXRlKt.mjs +1 -0
- package/dist/packem_shared/aiUnboundedGenerationPublic-C17h6sMV.mjs +1 -0
- package/dist/packem_shared/allowUnauthenticatedShardAccessEnabled-BQufF5Kb.mjs +1 -0
- package/dist/packem_shared/argument-derived-sink-DLXFC79t.mjs +1 -0
- package/dist/packem_shared/authApiCallWithoutHeaders-CReJRsGW.mjs +1 -0
- package/dist/packem_shared/authCsrfCheckDisabled-CRIVsvb9.mjs +1 -0
- package/dist/packem_shared/authEmailVerificationDisabled-BjFlnHr2.mjs +1 -0
- package/dist/packem_shared/authScimWithoutTransactions-B5ATiz5A.mjs +1 -0
- package/dist/packem_shared/authSecureCookiesDisabled-By8PVum3.mjs +1 -0
- package/dist/packem_shared/authSessionFreshageZero-DuxX3Ln9.mjs +1 -0
- package/dist/packem_shared/authTrustedOriginsWildcard-BKIh6788.mjs +1 -0
- package/dist/packem_shared/browserAllowPrivateTargets-Cj5sizhv.mjs +1 -0
- package/dist/packem_shared/browserUserUrlWithoutAllowlist-CzDEraJB.mjs +1 -0
- package/dist/packem_shared/callSiteCallers-DArHfQSU.mjs +1 -0
- package/dist/packem_shared/circularFk-DtcWFJxK.mjs +1 -0
- package/dist/packem_shared/classifySensitivity-JnjaTGYi.mjs +1 -0
- package/dist/packem_shared/commitOrderedHardDelete-BPdwOKA7.mjs +1 -0
- package/dist/packem_shared/compareToBaseline-CUG59IOy.mjs +1 -0
- package/dist/packem_shared/containerInstanceKeyFromUserInput-Bl-tAzKV.mjs +1 -0
- package/dist/packem_shared/containerOversizedInstance-Bx89uR7E.mjs +1 -0
- package/dist/packem_shared/containerPublicInternet-BFfZf_P4.mjs +1 -0
- package/dist/packem_shared/containerRuntimeEgressRelaxation-4tMrhq1k.mjs +1 -0
- package/dist/packem_shared/containerStartEnableInternetOverride-mN_kuRtk.mjs +1 -0
- package/dist/packem_shared/crossModuleTableWrite-DjiVTAwK.mjs +1 -0
- package/dist/packem_shared/dedupeCacheKeys-DtBOHffV.mjs +1 -0
- package/dist/packem_shared/dispatch-namespace-BE_LxN7Z.mjs +1 -0
- package/dist/packem_shared/dispatchCycle-CWc5Q0cd.mjs +1 -0
- package/dist/packem_shared/duplicateIndex-Cip6-Rpu.mjs +1 -0
- package/dist/packem_shared/emptyIndex-BnHDcXza.mjs +1 -0
- package/dist/packem_shared/errorWithoutCatalog-BTfvaXHR.mjs +1 -0
- package/dist/packem_shared/exportSinkMisconfigured-JfbAx9AI.mjs +1 -0
- package/dist/packem_shared/externalSourceIncrementalNoDeletePath-BCzm3HzF.mjs +1 -0
- package/dist/packem_shared/externalSourceOnGlobal-CH7xbJ49.mjs +1 -0
- package/dist/packem_shared/externalSourceUnscoped-BxU2uSXk.mjs +1 -0
- package/dist/packem_shared/fanOutBreadth-CBtmZnoh.mjs +1 -0
- package/dist/packem_shared/filterAfterIndexScan-CV8aPq7v.mjs +1 -0
- package/dist/packem_shared/filterOnPrimaryKey-BeHVg4w3.mjs +1 -0
- package/dist/packem_shared/filterWithoutIndex-BGv3jbgg.mjs +1 -0
- package/dist/packem_shared/finding-NrKO8idM.mjs +1 -0
- package/dist/packem_shared/fk-index-DXYS17cc.mjs +1 -0
- package/dist/packem_shared/flagGatesSecurityWithUnsafeDefault-B5FBDF8c.mjs +1 -0
- package/dist/packem_shared/flagReadInSubscription-DabIhYGD.mjs +1 -0
- package/dist/packem_shared/fromServerSchema-KWJd4PLE.mjs +1 -0
- package/dist/packem_shared/geoIndexFieldNotGeopoint-BMQuok2-.mjs +1 -0
- package/dist/packem_shared/geoIndexUnused-D7C9Qr4U.mjs +1 -0
- package/dist/packem_shared/globalTableNearColumnLimit-BFbBBd6A.mjs +1 -0
- package/dist/packem_shared/gradeFromScore-KSt58rj1.mjs +1 -0
- package/dist/packem_shared/hardcodedSecret-Bw_4FYrs.mjs +1 -0
- package/dist/packem_shared/helpers-DdZ_pyR3.mjs +1 -0
- package/dist/packem_shared/hotShard-BwGYZ3Tq.mjs +1 -0
- package/dist/packem_shared/httpActionMissingAuthGuard-DhMIs1EI.mjs +1 -0
- package/dist/packem_shared/httpActionResponseHeaderInjection-mcRYd3Zw.mjs +1 -0
- package/dist/packem_shared/hyperdriveOutsideAction-CPDdGP2g.mjs +1 -0
- package/dist/packem_shared/identityUndeclaredClaimTrusted-D1sEd5lr.mjs +1 -0
- package/dist/packem_shared/imagesUrlSourceFromUserInput-BJXotuyO.mjs +1 -0
- package/dist/packem_shared/indexReferencesUnknownField-DKz4-bla.mjs +1 -0
- package/dist/packem_shared/indexUtilization-CkVPZcVe.mjs +1 -0
- package/dist/packem_shared/insertManyUnsafeUserData-DWE8d_DF.mjs +1 -0
- package/dist/packem_shared/kvUnscopedUserKeyIdor-DhymglIq.mjs +1 -0
- package/dist/packem_shared/mailInboundDispatchWithoutVerify-CWwqXyPX.mjs +1 -0
- package/dist/packem_shared/mailRecipientFromRequestInput-BVXsZ4Xf.mjs +1 -0
- package/dist/packem_shared/maskUncoveredPiiColumn-axEka4nd.mjs +1 -0
- package/dist/packem_shared/maskWeakHashStrategyOnPii-DJasagzX.mjs +1 -0
- package/dist/packem_shared/maskedRelationLeakViaWith-CIFij6vE.mjs +1 -0
- package/dist/packem_shared/mutatorFullRowReplace-BzRpZ47r.mjs +1 -0
- package/dist/packem_shared/mutatorWithoutOwnerScope-BoS81ns0.mjs +1 -0
- package/dist/packem_shared/nondeterministicQueryMutation-Bbb-AGOS.mjs +1 -0
- package/dist/packem_shared/normalizeIdUsedAsAuthorization-BXN-Can6.mjs +1 -0
- package/dist/packem_shared/notifyMissingPushConfig-DeQMoNwm.mjs +1 -0
- package/dist/packem_shared/notifySendOutsideAction-BJrDkr4h.mjs +1 -0
- package/dist/packem_shared/outputProjectionMissingOnPublicRead-DWSeo7oC.mjs +1 -0
- package/dist/packem_shared/ownerFieldFromArgsNotAuth-J8Xbz5uI.mjs +1 -0
- package/dist/packem_shared/paymentCreateWithoutAuthorize-CdenWpXD.mjs +1 -0
- package/dist/packem_shared/paymentWebhookWideTolerance-DVhJB0Ip.mjs +1 -0
- package/dist/packem_shared/plaintextSecretInWranglerVariables-bNkqmNqV.mjs +1 -0
- package/dist/packem_shared/policyReferencesUnknownTable-CIKuRZ5Y.mjs +1 -0
- package/dist/packem_shared/privilegedDispatchUnvalidatedPayload-BM3NtT57.mjs +1 -0
- package/dist/packem_shared/privilegedFanoutFromPublicProcedure-DV188gHQ.mjs +1 -0
- package/dist/packem_shared/procedure-protections-DRQotu9I.mjs +1 -0
- package/dist/packem_shared/procedureWithoutStructuredEvent-CZ_B23nM.mjs +1 -0
- package/dist/packem_shared/publicArgumentUsesAny-BDEvMA8Q.mjs +1 -0
- package/dist/packem_shared/publicMutationWithoutRatelimit-Bd-rRxnz.mjs +1 -0
- package/dist/packem_shared/publicTableRlsOptoutConfusion-CbNk75Xo.mjs +1 -0
- package/dist/packem_shared/queueWithoutDlq-BvHz3Opg.mjs +1 -0
- package/dist/packem_shared/r2sqlOutsideAction-BdLiLOAX.mjs +1 -0
- package/dist/packem_shared/ratelimitDefaultMemoryStore-Dj0Kk7t9.mjs +1 -0
- package/dist/packem_shared/ratelimitKeySpoofableOrGlobal-DHMl74hR.mjs +1 -0
- package/dist/packem_shared/ratelimitMiddlewareFailOpen-Di2t8pDc.mjs +1 -0
- package/dist/packem_shared/relationReferencesUnknownField-Cl6mik8w.mjs +1 -0
- package/dist/packem_shared/relationReferencesUnknownTable-vYjirSxf.mjs +1 -0
- package/dist/packem_shared/rlsUncoveredTable-CZ4ie4gX.mjs +1 -0
- package/dist/packem_shared/selfRescheduleWithoutProgress-Be9d1bQ0.mjs +1 -0
- package/dist/packem_shared/shapeTargetsGlobalTable-Bu3eEDic.mjs +1 -0
- package/dist/packem_shared/shapeUnknownTable-CREfNnWi.mjs +1 -0
- package/dist/packem_shared/signupMutationWithoutDisposableGating-BdKwtxDP.mjs +1 -0
- package/dist/packem_shared/softDeleteIncludeDeletedFromArgs-C7Ugg4zb.mjs +1 -0
- package/dist/packem_shared/sqlInjectionRisk-BYRllgPV.mjs +1 -0
- package/dist/packem_shared/storageGenerateUploadUrlNoContentTypePin-CrwFuo83.mjs +1 -0
- package/dist/packem_shared/storageKeyFromUserArgs-3vkxmI3v.mjs +1 -0
- package/dist/packem_shared/storagePresignedUrlForPrivateContent-C3KeV5tV.mjs +1 -0
- package/dist/packem_shared/storageUploadWithoutContentTypeAllowlist-BXoK_QWE.mjs +1 -0
- package/dist/packem_shared/storageUploadWithoutMaxSize-CW7uKvSi.mjs +1 -0
- package/dist/packem_shared/sweeps-JWMwcakB.mjs +1 -0
- package/dist/packem_shared/tableWithoutInsert-ClJp_jDr.mjs +1 -0
- package/dist/packem_shared/throughRelationMissingUniqueIndex-Cg5e3GkS.mjs +1 -0
- package/dist/packem_shared/topicTooManySubscriptions-CiZhFm9r.mjs +1 -0
- package/dist/packem_shared/ttlFieldNotTimestamp-lnb5nmM6.mjs +1 -0
- package/dist/packem_shared/unboundedCollectOnOpenRange-DHy2RUL7.mjs +1 -0
- package/dist/packem_shared/unboundedLoop-DxN3_apu.mjs +1 -0
- package/dist/packem_shared/unboundedStringArgument-jZnCbwB0.mjs +1 -0
- package/dist/packem_shared/unindexedForeignKey-Dypgn8uH.mjs +1 -0
- package/dist/packem_shared/unindexedRelationTarget-Dj2_NOCm.mjs +1 -0
- package/dist/packem_shared/unrestrictedWhereBranch-CcIBmHik.mjs +1 -0
- package/dist/packem_shared/userCreatingMutationWithoutCaptcha-D4TZEpgz.mjs +1 -0
- package/dist/packem_shared/vectorsNamespaceFromUserInput-BWvGjJzp.mjs +1 -0
- package/dist/packem_shared/workflowDuplicateStepName-B6eAJzwA.mjs +1 -0
- package/dist/packem_shared/workflowUnknownTarget-DEKB5H0g.mjs +1 -0
- package/dist/packem_shared/workflowUnused-DHwwE-1P.mjs +1 -0
- package/package.json +3 -3
- package/dist/packem_shared/AE_METRIC_EVENTS-BM14d0lm.mjs +0 -87
- package/dist/packem_shared/actionFetchSsrf-wbmYgzmz.mjs +0 -26
- package/dist/packem_shared/adminRouteWithoutGuard-UUGBkAjU.mjs +0 -33
- package/dist/packem_shared/aiRawRunEscapeHatch-C29jd32J.mjs +0 -26
- package/dist/packem_shared/aiToolSideEffectPromptInjection-BtD3alqB.mjs +0 -33
- package/dist/packem_shared/aiUnboundedGenerationPublic-CbAcSxLB.mjs +0 -26
- package/dist/packem_shared/allowUnauthenticatedShardAccessEnabled-BcASq-jP.mjs +0 -30
- package/dist/packem_shared/argument-derived-sink-C1xTTqAt.mjs +0 -30
- package/dist/packem_shared/authApiCallWithoutHeaders-BeJhCZaf.mjs +0 -38
- package/dist/packem_shared/authCsrfCheckDisabled-DCf9FSoD.mjs +0 -26
- package/dist/packem_shared/authEmailVerificationDisabled-Dk-Tc5oU.mjs +0 -26
- package/dist/packem_shared/authSecureCookiesDisabled-osJrHW9Y.mjs +0 -26
- package/dist/packem_shared/authSessionFreshageZero-CjufCc_Q.mjs +0 -26
- package/dist/packem_shared/authTrustedOriginsWildcard-ylv4PKzC.mjs +0 -26
- package/dist/packem_shared/browserAllowPrivateTargets-CBvQxLAM.mjs +0 -26
- package/dist/packem_shared/browserUserUrlWithoutAllowlist-CvhA6w59.mjs +0 -26
- package/dist/packem_shared/circularFk-B2freHrP.mjs +0 -84
- package/dist/packem_shared/constraintValidator-Dr9Py3FD.mjs +0 -186
- package/dist/packem_shared/containerInstanceKeyFromUserInput-BUXj2J4w.mjs +0 -19
- package/dist/packem_shared/containerOversizedInstance-5U1VKPRM.mjs +0 -36
- package/dist/packem_shared/containerPublicInternet-CuNerJE5.mjs +0 -30
- package/dist/packem_shared/containerRuntimeEgressRelaxation-B0LlfmDA.mjs +0 -26
- package/dist/packem_shared/containerStartEnableInternetOverride-DDaHZQ1L.mjs +0 -26
- package/dist/packem_shared/duplicateIndex-BOublMSt.mjs +0 -57
- package/dist/packem_shared/emptyIndex-BX8EuEY7.mjs +0 -32
- package/dist/packem_shared/externalSourceOnGlobal-Bg-NfCX9.mjs +0 -30
- package/dist/packem_shared/externalSourceUnscoped-5vT-Bup3.mjs +0 -44
- package/dist/packem_shared/filterWithoutIndex-BYVeJaSs.mjs +0 -31
- package/dist/packem_shared/finding-Dm_zvzS1.mjs +0 -16
- package/dist/packem_shared/fk-index-IUK1ukgs.mjs +0 -7
- package/dist/packem_shared/flagGatesSecurityWithUnsafeDefault-BhIs0shr.mjs +0 -41
- package/dist/packem_shared/fromServerSchema-BiB6JSiW.mjs +0 -59
- package/dist/packem_shared/hardcodedSecret-W2pz1UZB.mjs +0 -35
- package/dist/packem_shared/helpers-BySnKhVB.mjs +0 -31
- package/dist/packem_shared/hotShard-Ir5D0B6J.mjs +0 -48
- package/dist/packem_shared/httpActionMissingAuthGuard-CxipddNx.mjs +0 -35
- package/dist/packem_shared/httpActionResponseHeaderInjection-DOFS7pFT.mjs +0 -39
- package/dist/packem_shared/hyperdriveOutsideAction-BgZqX7Xg.mjs +0 -30
- package/dist/packem_shared/identityUndeclaredClaimTrusted-D8nXV2dd.mjs +0 -32
- package/dist/packem_shared/imagesUrlSourceFromUserInput-YcDQ0b_Y.mjs +0 -19
- package/dist/packem_shared/indexReferencesUnknownField-BSWNngxX.mjs +0 -36
- package/dist/packem_shared/indexUtilization-B5DMQ3bI.mjs +0 -45
- package/dist/packem_shared/insertManyUnsafeUserData-Dn77XpmX.mjs +0 -26
- package/dist/packem_shared/kvUnscopedUserKeyIdor-YWwmfE8X.mjs +0 -19
- package/dist/packem_shared/mailInboundDispatchWithoutVerify-CHSRA8zz.mjs +0 -28
- package/dist/packem_shared/mailRecipientFromRequestInput-Cka2qu5J.mjs +0 -26
- package/dist/packem_shared/maskUncoveredPiiColumn-DjGIPG6M.mjs +0 -61
- package/dist/packem_shared/maskWeakHashStrategyOnPii-1c4q8Opf.mjs +0 -35
- package/dist/packem_shared/maskedRelationLeakViaWith-CPI4s0sl.mjs +0 -76
- package/dist/packem_shared/mutatorFullRowReplace-BJnNDaIV.mjs +0 -26
- package/dist/packem_shared/nondeterministicQueryMutation-GXES1fLp.mjs +0 -35
- package/dist/packem_shared/normalizeIdUsedAsAuthorization-BVPtCpzT.mjs +0 -50
- package/dist/packem_shared/outputProjectionMissingOnPublicRead-Bl5IMx0k.mjs +0 -51
- package/dist/packem_shared/ownerFieldFromArgsNotAuth-mOw3hE5z.mjs +0 -26
- package/dist/packem_shared/paymentCreateWithoutAuthorize-BYm4JLxo.mjs +0 -26
- package/dist/packem_shared/paymentWebhookWideTolerance-D9QQJMJq.mjs +0 -35
- package/dist/packem_shared/plaintextSecretInWranglerVariables-NKO4YkKf.mjs +0 -35
- package/dist/packem_shared/policyReferencesUnknownTable-DtaIEovd.mjs +0 -38
- package/dist/packem_shared/privilegedDispatchUnvalidatedPayload-5Forjckt.mjs +0 -37
- package/dist/packem_shared/privilegedFanoutFromPublicProcedure-D3dL01B8.mjs +0 -26
- package/dist/packem_shared/publicArgumentUsesAny-C71b2NCf.mjs +0 -32
- package/dist/packem_shared/publicMutationWithoutRatelimit-DbIhgi7j.mjs +0 -36
- package/dist/packem_shared/publicTableRlsOptoutConfusion-Bn71yoD4.mjs +0 -38
- package/dist/packem_shared/queueWithoutDlq-CSkGNb_0.mjs +0 -41
- package/dist/packem_shared/r2sqlOutsideAction-CtqxvMuV.mjs +0 -30
- package/dist/packem_shared/ratelimitDefaultMemoryStore-BISChG5C.mjs +0 -26
- package/dist/packem_shared/ratelimitKeySpoofableOrGlobal-DqlHYQQ3.mjs +0 -26
- package/dist/packem_shared/ratelimitMiddlewareFailOpen-CJgDCaUw.mjs +0 -33
- package/dist/packem_shared/relationReferencesUnknownField-CjbLScJ1.mjs +0 -54
- package/dist/packem_shared/relationReferencesUnknownTable-DrorpKYe.mjs +0 -33
- package/dist/packem_shared/rlsUncoveredTable-CxEfZ5eZ.mjs +0 -56
- package/dist/packem_shared/shapeTargetsGlobalTable-DHrf4Koi.mjs +0 -34
- package/dist/packem_shared/shapeUnknownTable-C8aDWFoe.mjs +0 -34
- package/dist/packem_shared/softDeleteIncludeDeletedFromArgs-BLqDKrkM.mjs +0 -38
- package/dist/packem_shared/sqlInjectionRisk-zwytYGLt.mjs +0 -26
- package/dist/packem_shared/storageGenerateUploadUrlNoContentTypePin-Da4L9Ge8.mjs +0 -26
- package/dist/packem_shared/storageKeyFromUserArgs-B86elJgS.mjs +0 -19
- package/dist/packem_shared/storagePresignedUrlForPrivateContent-yGmb8uqz.mjs +0 -47
- package/dist/packem_shared/storageUploadWithoutContentTypeAllowlist-BV-gF1lT.mjs +0 -27
- package/dist/packem_shared/storageUploadWithoutMaxSize-DpxO59wU.mjs +0 -27
- package/dist/packem_shared/tableWithoutInsert-CbbaYIP4.mjs +0 -34
- package/dist/packem_shared/unboundedStringArgument-DThg2-wt.mjs +0 -32
- package/dist/packem_shared/unindexedForeignKey-BgJbKyqK.mjs +0 -45
- package/dist/packem_shared/unindexedRelationTarget-D6eyj6Xx.mjs +0 -53
- package/dist/packem_shared/userCreatingMutationWithoutCaptcha-2DZtWIPb.mjs +0 -42
- package/dist/packem_shared/vectorsNamespaceFromUserInput-CQhr5bVn.mjs +0 -19
- package/dist/packem_shared/workflowDuplicateStepName-ioBxPBCy.mjs +0 -48
- package/dist/packem_shared/workflowUnknownTarget-Cdd7WhKQ.mjs +0 -34
- package/dist/packem_shared/workflowUnused-D0jHxdz9.mjs +0 -38
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import { e as emit } from './finding-Dm_zvzS1.mjs';
|
|
2
|
-
import { i as isPublicWrite } from './helpers-BySnKhVB.mjs';
|
|
3
|
-
|
|
4
|
-
const userCreatingMutationWithoutCaptcha = {
|
|
5
|
-
categories: ["SECURITY"],
|
|
6
|
-
description: "A public `mutation`/`action` that creates a user/session or sends mail has no CAPTCHA / bot check. Account-creating and mail-sending endpoints are prime automated-abuse targets (credential stuffing, mailbox flooding, disposable-account farming).",
|
|
7
|
-
facing: "EXTERNAL",
|
|
8
|
-
level: "WARN",
|
|
9
|
-
name: "user_creating_mutation_without_captcha",
|
|
10
|
-
remediation: "Add a server-verified human check: `.use(verifyTurnstile({ secret, token }))` from `@lunora/auth`, or wrap it with `.use(protectPublic({ rateLimit, captcha }))` from `@lunora/server`. Pair with a rate limit for defense in depth.",
|
|
11
|
-
run: (context) => {
|
|
12
|
-
if (context.procedureProtections === void 0) {
|
|
13
|
-
return [];
|
|
14
|
-
}
|
|
15
|
-
const findings = [];
|
|
16
|
-
for (const procedure of context.procedureProtections) {
|
|
17
|
-
const sensitive = procedure.writesUserTable || procedure.callsMail;
|
|
18
|
-
if (!isPublicWrite(procedure) || !sensitive || procedure.usesCaptcha) {
|
|
19
|
-
continue;
|
|
20
|
-
}
|
|
21
|
-
const reason = procedure.writesUserTable ? "writes a user/session table" : "sends mail";
|
|
22
|
-
findings.push(
|
|
23
|
-
emit(userCreatingMutationWithoutCaptcha, {
|
|
24
|
-
cacheKey: `user_creating_mutation_without_captcha:${procedure.file}:${procedure.exportName}`,
|
|
25
|
-
detail: `Public ${procedure.kind} \`${procedure.exportName}\` (${procedure.file}) ${reason} but has no CAPTCHA check. Add \`.use(verifyTurnstile(...))\` or \`.use(protectPublic({ captcha }))\`.`,
|
|
26
|
-
metadata: {
|
|
27
|
-
callsMail: procedure.callsMail,
|
|
28
|
-
exportName: procedure.exportName,
|
|
29
|
-
file: procedure.file,
|
|
30
|
-
kind: procedure.kind,
|
|
31
|
-
writesUserTable: procedure.writesUserTable
|
|
32
|
-
}
|
|
33
|
-
})
|
|
34
|
-
);
|
|
35
|
-
}
|
|
36
|
-
return findings;
|
|
37
|
-
},
|
|
38
|
-
source: "static",
|
|
39
|
-
title: "Account-creating / mail-sending write without a CAPTCHA"
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
export { userCreatingMutationWithoutCaptcha as default };
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { m as makeArgumentDerivedSinkLint } from './argument-derived-sink-C1xTTqAt.mjs';
|
|
2
|
-
|
|
3
|
-
const vectorsNamespaceFromUserInput = makeArgumentDerivedSinkLint({
|
|
4
|
-
cacheKey: (access) => `vectors_namespace_from_user_input:${access.file}:${access.line.toString()}`,
|
|
5
|
-
categories: ["SECURITY"],
|
|
6
|
-
description: "A `ctx.vectors.query`/`upsert`/`upsertMany` call uses a `namespace` derived from the handler's `args` with no server-side scoping. A Vectorize namespace partitions one index into isolated sub-collections, so an unscoped namespace lets any caller read or poison another tenant's vectors.",
|
|
7
|
-
detail: (access) => `\`ctx.vectors.${access.method}\` in \`${access.exportName}\` (${access.file}:${access.line.toString()}) uses a Vectorize namespace derived from \`args\` with no server-side scoping — any caller can read or poison another tenant's vectors. Derive the namespace from a server-trusted identity (e.g. \`\${ctx.auth.orgId}\`), never from \`args\`.`,
|
|
8
|
-
facing: "EXTERNAL",
|
|
9
|
-
getAccesses: (context) => context.vectorNamespaceAccesses,
|
|
10
|
-
level: "WARN",
|
|
11
|
-
metadata: (access) => {
|
|
12
|
-
return { exportName: access.exportName, file: access.file, line: access.line, method: access.method };
|
|
13
|
-
},
|
|
14
|
-
name: "vectors_namespace_from_user_input",
|
|
15
|
-
remediation: `Derive the \`namespace\` from a server-trusted identity (e.g. \`\${ctx.auth.orgId}\`), never from \`args\`.`,
|
|
16
|
-
title: "Vectorize namespace derived from unscoped user input"
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
export { vectorsNamespaceFromUserInput as default };
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import { e as emit } from './finding-Dm_zvzS1.mjs';
|
|
2
|
-
|
|
3
|
-
const workflowDuplicateStepName = {
|
|
4
|
-
categories: ["SCHEMA"],
|
|
5
|
-
description: "Two durable steps in this workflow share a name. Cloudflare memoizes a step by its name, so on replay the second call returns the first step's cached result instead of running its body — silently skipping the work without an error.",
|
|
6
|
-
facing: "INTERNAL",
|
|
7
|
-
level: "ERROR",
|
|
8
|
-
// eslint-disable-next-line no-secrets/no-secrets -- the lint's rule id, not a credential
|
|
9
|
-
name: "workflow_duplicate_step_name",
|
|
10
|
-
remediation: "Give every `step.do` / `step.sleep` / `step.sleepUntil` / `step.waitForEvent` call in the workflow a unique name. If a step legitimately repeats (e.g. a loop), make the name distinct per iteration by interpolating the item id into the step name.",
|
|
11
|
-
run: (context) => {
|
|
12
|
-
if (context.workflows === void 0) {
|
|
13
|
-
return [];
|
|
14
|
-
}
|
|
15
|
-
const findings = [];
|
|
16
|
-
for (const workflow of context.workflows) {
|
|
17
|
-
const { steps } = workflow;
|
|
18
|
-
if (steps === void 0 || steps.length === 0) {
|
|
19
|
-
continue;
|
|
20
|
-
}
|
|
21
|
-
const firstLineByName = /* @__PURE__ */ new Map();
|
|
22
|
-
const reported = /* @__PURE__ */ new Set();
|
|
23
|
-
for (const step of steps) {
|
|
24
|
-
const firstLine = firstLineByName.get(step.name);
|
|
25
|
-
if (firstLine === void 0) {
|
|
26
|
-
firstLineByName.set(step.name, step.line);
|
|
27
|
-
continue;
|
|
28
|
-
}
|
|
29
|
-
if (reported.has(step.name)) {
|
|
30
|
-
continue;
|
|
31
|
-
}
|
|
32
|
-
reported.add(step.name);
|
|
33
|
-
findings.push(
|
|
34
|
-
emit(workflowDuplicateStepName, {
|
|
35
|
-
cacheKey: `workflow_duplicate_step_name:${workflow.exportName}:${step.name}`,
|
|
36
|
-
detail: `Workflow "${workflow.exportName}" reuses the durable step name "${step.name}" (first at line ${String(firstLine)}, again at line ${String(step.line)}). The second call returns the first's cached result instead of running.`,
|
|
37
|
-
metadata: { firstLine, line: step.line, stepName: step.name, workflow: workflow.exportName }
|
|
38
|
-
})
|
|
39
|
-
);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
return findings;
|
|
43
|
-
},
|
|
44
|
-
source: "static",
|
|
45
|
-
title: "Duplicate durable step name in workflow"
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
export { workflowDuplicateStepName as default };
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { e as emit } from './finding-Dm_zvzS1.mjs';
|
|
2
|
-
|
|
3
|
-
const workflowUnknownTarget = {
|
|
4
|
-
categories: ["SCHEMA"],
|
|
5
|
-
description: 'A `ctx.workflows.get("<name>")` call references a workflow that is not declared by any `defineWorkflow` export in `lunora/workflows.ts`. The name is a typo or points at a removed/renamed workflow — the call throws at runtime.',
|
|
6
|
-
facing: "INTERNAL",
|
|
7
|
-
level: "ERROR",
|
|
8
|
-
name: "workflow_unknown_target",
|
|
9
|
-
remediation: 'Fix the workflow name in the `ctx.workflows.get("…")` call, or add the missing `defineWorkflow` export to `lunora/workflows.ts`.',
|
|
10
|
-
run: (context) => {
|
|
11
|
-
if (context.workflows === void 0 || context.workflowCalls === void 0) {
|
|
12
|
-
return [];
|
|
13
|
-
}
|
|
14
|
-
const declared = new Set(context.workflows.map((workflow) => workflow.exportName));
|
|
15
|
-
const findings = [];
|
|
16
|
-
for (const call of context.workflowCalls) {
|
|
17
|
-
if (call.workflow === "" || declared.has(call.workflow)) {
|
|
18
|
-
continue;
|
|
19
|
-
}
|
|
20
|
-
findings.push(
|
|
21
|
-
emit(workflowUnknownTarget, {
|
|
22
|
-
cacheKey: `workflow_unknown_target:${call.file}:${call.exportName}:${call.workflow}`,
|
|
23
|
-
detail: `\`ctx.workflows.get("${call.workflow}")\` in "${call.exportName}" (${call.file}) references workflow "${call.workflow}", which is not declared in lunora/workflows.ts.`,
|
|
24
|
-
metadata: { exportName: call.exportName, file: call.file, line: call.line, workflow: call.workflow }
|
|
25
|
-
})
|
|
26
|
-
);
|
|
27
|
-
}
|
|
28
|
-
return findings;
|
|
29
|
-
},
|
|
30
|
-
source: "static",
|
|
31
|
-
title: "Workflow call references unknown workflow"
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
export { workflowUnknownTarget as default };
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import { e as emit } from './finding-Dm_zvzS1.mjs';
|
|
2
|
-
|
|
3
|
-
const workflowUnused = {
|
|
4
|
-
categories: ["SCHEMA"],
|
|
5
|
-
description: 'No function starts this workflow via `ctx.workflows.get("<name>")`. It may be triggered through a path the advisor can\'t see (the Cloudflare API, a wrangler invocation, a cross-service binding) — or it may be dead code that still deploys as a billable WorkflowEntrypoint.',
|
|
6
|
-
facing: "INTERNAL",
|
|
7
|
-
level: "INFO",
|
|
8
|
-
name: "workflow_unused",
|
|
9
|
-
remediation: 'If the workflow should be triggered in-app, start it from a mutation/action with `ctx.workflows.get("<name>").create({ params })`. If it is started externally or is no longer needed, this advisory can be ignored (or remove the `defineWorkflow` export).',
|
|
10
|
-
run: (context) => {
|
|
11
|
-
if (context.workflows === void 0) {
|
|
12
|
-
return [];
|
|
13
|
-
}
|
|
14
|
-
const calls = context.workflowCalls ?? [];
|
|
15
|
-
if (calls.some((call) => call.workflow === "")) {
|
|
16
|
-
return [];
|
|
17
|
-
}
|
|
18
|
-
const started = new Set(calls.map((call) => call.workflow));
|
|
19
|
-
const findings = [];
|
|
20
|
-
for (const workflow of context.workflows) {
|
|
21
|
-
if (started.has(workflow.exportName)) {
|
|
22
|
-
continue;
|
|
23
|
-
}
|
|
24
|
-
findings.push(
|
|
25
|
-
emit(workflowUnused, {
|
|
26
|
-
cacheKey: `workflow_unused:${workflow.exportName}`,
|
|
27
|
-
detail: `No function calls \`ctx.workflows.get("${workflow.exportName}")\` — workflow "${workflow.exportName}" is declared but never started in app code.`,
|
|
28
|
-
metadata: { workflow: workflow.exportName }
|
|
29
|
-
})
|
|
30
|
-
);
|
|
31
|
-
}
|
|
32
|
-
return findings;
|
|
33
|
-
},
|
|
34
|
-
source: "static",
|
|
35
|
-
title: "Workflow is never started"
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
export { workflowUnused as default };
|