xploitscan-shared-rules 1.7.4 → 1.8.1
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.cjs +160 -11
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.js +156 -11
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -315,6 +315,10 @@ declare const llmCallNoMaxTokens: CustomRule;
|
|
|
315
315
|
declare const graphqlNoDepthLimit: CustomRule;
|
|
316
316
|
declare const graphqlNoComplexityLimit: CustomRule;
|
|
317
317
|
declare const graphqlCSRFDisabled: CustomRule;
|
|
318
|
+
declare const llmOutputToSink: CustomRule;
|
|
319
|
+
declare const secretInLLMPrompt: CustomRule;
|
|
320
|
+
declare const webhookMissingIdempotency: CustomRule;
|
|
321
|
+
declare const middlewareMatcherExcludesApi: CustomRule;
|
|
318
322
|
declare const secretInURLParam: CustomRule;
|
|
319
323
|
declare const secretLoggedToConsole: CustomRule;
|
|
320
324
|
declare const secretInErrorResponse: CustomRule;
|
|
@@ -506,4 +510,4 @@ declare function getObjectProperty(node: ObjectExpression, key: string): {
|
|
|
506
510
|
/** Does this CallExpression spread an expression `matcher` returns true for? */
|
|
507
511
|
declare function callSpreads(call: CallExpression, matcher: (node: Node) => boolean): boolean;
|
|
508
512
|
|
|
509
|
-
export { type AIFilterResult, type Confidence, type CustomRule, type DetectedFramework, type Exposure, type FilteredFinding, type Finding, type GradeResult, type ParsedFile, RULE_IMPACTS, type RuleMatch, type SecurityGrade, type Severity, type TaintMap, allCustomRules, allRules, androidDebuggable, blockingMainThread, buildTaintMap, calculateGrade, callSpreads, callbackHell, classifyExposure, clickjacking, clientComponentSecret, clientSideAuth, commandInjection, complianceMap, consoleLogProduction, corsLocalhost, corsServerless, corsWildcard, dangerousInnerHTML, deprecatedTLS, detectFramework, disabledTLSVerification, djangoDebug, dockerCopySensitive, dockerLatestTag, dockerRunAsRoot, dockerTooManyPorts, dockerfileADDInsteadOfCOPY, dockerfileMissingHealthcheck, dockerfileUnverifiedShellPipe, ecbModeEncryption, electronNavigationUnrestricted, emptyCatchBlock, envNotGitignored, evalUsage, eventListenerLeak, exposedAdminRoutes, exposedAuthSecret, exposedDBCredentials, exposedDatabaseStudio, exposedDebugMode, exposedDockerPorts, exposedEnvFile, exposedGitDir, exposedServerActions, exposedSourceMaps, exposedStackTraces, filterFalsePositives, firebaseClientConfig, flaskSecretKey, freeRules, getObjectProperty, getSnippet, ghaExpressionInjection, ghaPermissionsWriteAll, ghaPullRequestTargetCheckout, ghaThirdPartyActionWithSecrets, githubActionsInjection, graphqlCSRFDisabled, graphqlIntrospection, graphqlNoComplexityLimit, graphqlNoDepthLimit, hardcodedAlgoliaAdminKey, hardcodedAnthropicKey, hardcodedCloudflareToken, hardcodedCohereKey, hardcodedDatadogKey, hardcodedDiscordToken, hardcodedEncryptionKey, hardcodedFastlyToken, hardcodedFireworksKey, hardcodedFlyToken, hardcodedGCPServiceAccount, hardcodedGitHubPAT, hardcodedGitLabToken, hardcodedGroqKey, hardcodedHighlightKey, hardcodedIPAllowlist, hardcodedIntercomToken, hardcodedJWTSecret, hardcodedLinearKey, hardcodedLogtailToken, hardcodedLoopsKey, hardcodedMailgunKey, hardcodedMistralKey, hardcodedNetlifyToken, hardcodedNotionKey, hardcodedOAuthSecret, hardcodedPineconeKey, hardcodedPlivoToken, hardcodedPostmarkKey, hardcodedQdrantKey, hardcodedRailwayToken, hardcodedReplicateKey, hardcodedResendKey, hardcodedSecrets, hardcodedSendGridKey, hardcodedSentryAuthToken, hardcodedShopifyToken, hardcodedSlackToken, hardcodedSupabaseServiceRole, hardcodedTogetherKey, hardcodedTwilioKey, hardcodedVaultToken, hardcodedVercelToken, hardcodedWeaviateKey, hostHeaderRedirect, httpRequestSmuggling, insecureCookies, insecureDeepLink, insecureDeserialization, insecureDirectObjectReference, insecureElectronWindow, insecureFileUpload, insecureGRPC, insecureHTTPMethods, insecurePasswordReset, insecureRandomness, insecureWebSocket, ipcPathTraversal, isCalleeNamed, isMethodCall, javaDeserialization, jwtAlgConfusion, k8sNoResourceLimits, k8sPrivileged, k8sSecretNotEncrypted, lambdaWithoutVPC, largeBundleImport, llmCallNoMaxTokens, llmOutputAsHTML, llmPromptInjection, llmSystemPromptInjection, logInjection, magicNumbers, massAssignment, missingAIRateLimit, missingAuthMiddleware, missingAuthRateLimit, missingBruteForce, missingCSP, missingCSRF, missingCertPinning, missingCloudTrail, missingContentDisposition, missingDBEncryption, missingErrorBoundary, missingFileSizeLimits, missingHSTS, missingHTTPS, missingLockFile, missingOAuthState, missingPagination, missingRequestSizeLimit, missingRequestValidation, missingSRI, missingSecurityMeta, nPlusOneQuery, nextPublicSecret, noRateLimiting, nosqlInjection, openRedirectParams, overlyPermissiveIAM, parseFile, pathTraversal, pickleDeserialization, piiInLogs, prototypePollution, pyDjangoAllowedHostsWildcard, pyDjangoMarkSafe, pyJWTDecodeWeakConfig, pyJinja2AutoescapeOff, pyParamikoAutoAdd, pyRequestsVerifyFalse, pyTempfileMktemp, raceCondition, rdsPubliclyAccessible, reflectedCORSOrigin, regexDos, runCustomRules, s3BucketNoEncryption, scanEntropy, secretInBundleConfig, secretInCLIArgument, secretInErrorResponse, secretInHTMLAttribute, secretInURLParam, secretLoggedToConsole, secretsInCI, securityGroupAllInbound, sensitiveAsyncStorage, sensitiveLocalStorage, sensitiveURLParams, sessionFixation, sqlInjection, ssrfVulnerability, ssti, stripeWebhookUnprotected, supabaseAnonAdmin, supabaseNoRLS, syncFileOps, terraformStateExposed, timingAttack, todoLeftInCode, unencryptedPII, unpinnedGitHubAction, unprotectedAPIRoutes, unprotectedDownload, unsafeObjectAssign, unsanitizedFilenames, unsanitizedHTMLExport, unvalidatedAPIParams, unvalidatedEventData, unvalidatedRedirect, vectorStoreQueryNoUserFilter, vectorStoreUpsertNoMetadata, visitBinary, visitCalls, vulnerableDependencies, weakHashing, weakPasswordRequirements, weakRSAKeySize, webhookSignatureVerification, xssVulnerability, xxeVulnerability };
|
|
513
|
+
export { type AIFilterResult, type Confidence, type CustomRule, type DetectedFramework, type Exposure, type FilteredFinding, type Finding, type GradeResult, type ParsedFile, RULE_IMPACTS, type RuleMatch, type SecurityGrade, type Severity, type TaintMap, allCustomRules, allRules, androidDebuggable, blockingMainThread, buildTaintMap, calculateGrade, callSpreads, callbackHell, classifyExposure, clickjacking, clientComponentSecret, clientSideAuth, commandInjection, complianceMap, consoleLogProduction, corsLocalhost, corsServerless, corsWildcard, dangerousInnerHTML, deprecatedTLS, detectFramework, disabledTLSVerification, djangoDebug, dockerCopySensitive, dockerLatestTag, dockerRunAsRoot, dockerTooManyPorts, dockerfileADDInsteadOfCOPY, dockerfileMissingHealthcheck, dockerfileUnverifiedShellPipe, ecbModeEncryption, electronNavigationUnrestricted, emptyCatchBlock, envNotGitignored, evalUsage, eventListenerLeak, exposedAdminRoutes, exposedAuthSecret, exposedDBCredentials, exposedDatabaseStudio, exposedDebugMode, exposedDockerPorts, exposedEnvFile, exposedGitDir, exposedServerActions, exposedSourceMaps, exposedStackTraces, filterFalsePositives, firebaseClientConfig, flaskSecretKey, freeRules, getObjectProperty, getSnippet, ghaExpressionInjection, ghaPermissionsWriteAll, ghaPullRequestTargetCheckout, ghaThirdPartyActionWithSecrets, githubActionsInjection, graphqlCSRFDisabled, graphqlIntrospection, graphqlNoComplexityLimit, graphqlNoDepthLimit, hardcodedAlgoliaAdminKey, hardcodedAnthropicKey, hardcodedCloudflareToken, hardcodedCohereKey, hardcodedDatadogKey, hardcodedDiscordToken, hardcodedEncryptionKey, hardcodedFastlyToken, hardcodedFireworksKey, hardcodedFlyToken, hardcodedGCPServiceAccount, hardcodedGitHubPAT, hardcodedGitLabToken, hardcodedGroqKey, hardcodedHighlightKey, hardcodedIPAllowlist, hardcodedIntercomToken, hardcodedJWTSecret, hardcodedLinearKey, hardcodedLogtailToken, hardcodedLoopsKey, hardcodedMailgunKey, hardcodedMistralKey, hardcodedNetlifyToken, hardcodedNotionKey, hardcodedOAuthSecret, hardcodedPineconeKey, hardcodedPlivoToken, hardcodedPostmarkKey, hardcodedQdrantKey, hardcodedRailwayToken, hardcodedReplicateKey, hardcodedResendKey, hardcodedSecrets, hardcodedSendGridKey, hardcodedSentryAuthToken, hardcodedShopifyToken, hardcodedSlackToken, hardcodedSupabaseServiceRole, hardcodedTogetherKey, hardcodedTwilioKey, hardcodedVaultToken, hardcodedVercelToken, hardcodedWeaviateKey, hostHeaderRedirect, httpRequestSmuggling, insecureCookies, insecureDeepLink, insecureDeserialization, insecureDirectObjectReference, insecureElectronWindow, insecureFileUpload, insecureGRPC, insecureHTTPMethods, insecurePasswordReset, insecureRandomness, insecureWebSocket, ipcPathTraversal, isCalleeNamed, isMethodCall, javaDeserialization, jwtAlgConfusion, k8sNoResourceLimits, k8sPrivileged, k8sSecretNotEncrypted, lambdaWithoutVPC, largeBundleImport, llmCallNoMaxTokens, llmOutputAsHTML, llmOutputToSink, llmPromptInjection, llmSystemPromptInjection, logInjection, magicNumbers, massAssignment, middlewareMatcherExcludesApi, missingAIRateLimit, missingAuthMiddleware, missingAuthRateLimit, missingBruteForce, missingCSP, missingCSRF, missingCertPinning, missingCloudTrail, missingContentDisposition, missingDBEncryption, missingErrorBoundary, missingFileSizeLimits, missingHSTS, missingHTTPS, missingLockFile, missingOAuthState, missingPagination, missingRequestSizeLimit, missingRequestValidation, missingSRI, missingSecurityMeta, nPlusOneQuery, nextPublicSecret, noRateLimiting, nosqlInjection, openRedirectParams, overlyPermissiveIAM, parseFile, pathTraversal, pickleDeserialization, piiInLogs, prototypePollution, pyDjangoAllowedHostsWildcard, pyDjangoMarkSafe, pyJWTDecodeWeakConfig, pyJinja2AutoescapeOff, pyParamikoAutoAdd, pyRequestsVerifyFalse, pyTempfileMktemp, raceCondition, rdsPubliclyAccessible, reflectedCORSOrigin, regexDos, runCustomRules, s3BucketNoEncryption, scanEntropy, secretInBundleConfig, secretInCLIArgument, secretInErrorResponse, secretInHTMLAttribute, secretInLLMPrompt, secretInURLParam, secretLoggedToConsole, secretsInCI, securityGroupAllInbound, sensitiveAsyncStorage, sensitiveLocalStorage, sensitiveURLParams, sessionFixation, sqlInjection, ssrfVulnerability, ssti, stripeWebhookUnprotected, supabaseAnonAdmin, supabaseNoRLS, syncFileOps, terraformStateExposed, timingAttack, todoLeftInCode, unencryptedPII, unpinnedGitHubAction, unprotectedAPIRoutes, unprotectedDownload, unsafeObjectAssign, unsanitizedFilenames, unsanitizedHTMLExport, unvalidatedAPIParams, unvalidatedEventData, unvalidatedRedirect, vectorStoreQueryNoUserFilter, vectorStoreUpsertNoMetadata, visitBinary, visitCalls, vulnerableDependencies, weakHashing, weakPasswordRequirements, weakRSAKeySize, webhookMissingIdempotency, webhookSignatureVerification, xssVulnerability, xxeVulnerability };
|
package/dist/index.d.ts
CHANGED
|
@@ -315,6 +315,10 @@ declare const llmCallNoMaxTokens: CustomRule;
|
|
|
315
315
|
declare const graphqlNoDepthLimit: CustomRule;
|
|
316
316
|
declare const graphqlNoComplexityLimit: CustomRule;
|
|
317
317
|
declare const graphqlCSRFDisabled: CustomRule;
|
|
318
|
+
declare const llmOutputToSink: CustomRule;
|
|
319
|
+
declare const secretInLLMPrompt: CustomRule;
|
|
320
|
+
declare const webhookMissingIdempotency: CustomRule;
|
|
321
|
+
declare const middlewareMatcherExcludesApi: CustomRule;
|
|
318
322
|
declare const secretInURLParam: CustomRule;
|
|
319
323
|
declare const secretLoggedToConsole: CustomRule;
|
|
320
324
|
declare const secretInErrorResponse: CustomRule;
|
|
@@ -506,4 +510,4 @@ declare function getObjectProperty(node: ObjectExpression, key: string): {
|
|
|
506
510
|
/** Does this CallExpression spread an expression `matcher` returns true for? */
|
|
507
511
|
declare function callSpreads(call: CallExpression, matcher: (node: Node) => boolean): boolean;
|
|
508
512
|
|
|
509
|
-
export { type AIFilterResult, type Confidence, type CustomRule, type DetectedFramework, type Exposure, type FilteredFinding, type Finding, type GradeResult, type ParsedFile, RULE_IMPACTS, type RuleMatch, type SecurityGrade, type Severity, type TaintMap, allCustomRules, allRules, androidDebuggable, blockingMainThread, buildTaintMap, calculateGrade, callSpreads, callbackHell, classifyExposure, clickjacking, clientComponentSecret, clientSideAuth, commandInjection, complianceMap, consoleLogProduction, corsLocalhost, corsServerless, corsWildcard, dangerousInnerHTML, deprecatedTLS, detectFramework, disabledTLSVerification, djangoDebug, dockerCopySensitive, dockerLatestTag, dockerRunAsRoot, dockerTooManyPorts, dockerfileADDInsteadOfCOPY, dockerfileMissingHealthcheck, dockerfileUnverifiedShellPipe, ecbModeEncryption, electronNavigationUnrestricted, emptyCatchBlock, envNotGitignored, evalUsage, eventListenerLeak, exposedAdminRoutes, exposedAuthSecret, exposedDBCredentials, exposedDatabaseStudio, exposedDebugMode, exposedDockerPorts, exposedEnvFile, exposedGitDir, exposedServerActions, exposedSourceMaps, exposedStackTraces, filterFalsePositives, firebaseClientConfig, flaskSecretKey, freeRules, getObjectProperty, getSnippet, ghaExpressionInjection, ghaPermissionsWriteAll, ghaPullRequestTargetCheckout, ghaThirdPartyActionWithSecrets, githubActionsInjection, graphqlCSRFDisabled, graphqlIntrospection, graphqlNoComplexityLimit, graphqlNoDepthLimit, hardcodedAlgoliaAdminKey, hardcodedAnthropicKey, hardcodedCloudflareToken, hardcodedCohereKey, hardcodedDatadogKey, hardcodedDiscordToken, hardcodedEncryptionKey, hardcodedFastlyToken, hardcodedFireworksKey, hardcodedFlyToken, hardcodedGCPServiceAccount, hardcodedGitHubPAT, hardcodedGitLabToken, hardcodedGroqKey, hardcodedHighlightKey, hardcodedIPAllowlist, hardcodedIntercomToken, hardcodedJWTSecret, hardcodedLinearKey, hardcodedLogtailToken, hardcodedLoopsKey, hardcodedMailgunKey, hardcodedMistralKey, hardcodedNetlifyToken, hardcodedNotionKey, hardcodedOAuthSecret, hardcodedPineconeKey, hardcodedPlivoToken, hardcodedPostmarkKey, hardcodedQdrantKey, hardcodedRailwayToken, hardcodedReplicateKey, hardcodedResendKey, hardcodedSecrets, hardcodedSendGridKey, hardcodedSentryAuthToken, hardcodedShopifyToken, hardcodedSlackToken, hardcodedSupabaseServiceRole, hardcodedTogetherKey, hardcodedTwilioKey, hardcodedVaultToken, hardcodedVercelToken, hardcodedWeaviateKey, hostHeaderRedirect, httpRequestSmuggling, insecureCookies, insecureDeepLink, insecureDeserialization, insecureDirectObjectReference, insecureElectronWindow, insecureFileUpload, insecureGRPC, insecureHTTPMethods, insecurePasswordReset, insecureRandomness, insecureWebSocket, ipcPathTraversal, isCalleeNamed, isMethodCall, javaDeserialization, jwtAlgConfusion, k8sNoResourceLimits, k8sPrivileged, k8sSecretNotEncrypted, lambdaWithoutVPC, largeBundleImport, llmCallNoMaxTokens, llmOutputAsHTML, llmPromptInjection, llmSystemPromptInjection, logInjection, magicNumbers, massAssignment, missingAIRateLimit, missingAuthMiddleware, missingAuthRateLimit, missingBruteForce, missingCSP, missingCSRF, missingCertPinning, missingCloudTrail, missingContentDisposition, missingDBEncryption, missingErrorBoundary, missingFileSizeLimits, missingHSTS, missingHTTPS, missingLockFile, missingOAuthState, missingPagination, missingRequestSizeLimit, missingRequestValidation, missingSRI, missingSecurityMeta, nPlusOneQuery, nextPublicSecret, noRateLimiting, nosqlInjection, openRedirectParams, overlyPermissiveIAM, parseFile, pathTraversal, pickleDeserialization, piiInLogs, prototypePollution, pyDjangoAllowedHostsWildcard, pyDjangoMarkSafe, pyJWTDecodeWeakConfig, pyJinja2AutoescapeOff, pyParamikoAutoAdd, pyRequestsVerifyFalse, pyTempfileMktemp, raceCondition, rdsPubliclyAccessible, reflectedCORSOrigin, regexDos, runCustomRules, s3BucketNoEncryption, scanEntropy, secretInBundleConfig, secretInCLIArgument, secretInErrorResponse, secretInHTMLAttribute, secretInURLParam, secretLoggedToConsole, secretsInCI, securityGroupAllInbound, sensitiveAsyncStorage, sensitiveLocalStorage, sensitiveURLParams, sessionFixation, sqlInjection, ssrfVulnerability, ssti, stripeWebhookUnprotected, supabaseAnonAdmin, supabaseNoRLS, syncFileOps, terraformStateExposed, timingAttack, todoLeftInCode, unencryptedPII, unpinnedGitHubAction, unprotectedAPIRoutes, unprotectedDownload, unsafeObjectAssign, unsanitizedFilenames, unsanitizedHTMLExport, unvalidatedAPIParams, unvalidatedEventData, unvalidatedRedirect, vectorStoreQueryNoUserFilter, vectorStoreUpsertNoMetadata, visitBinary, visitCalls, vulnerableDependencies, weakHashing, weakPasswordRequirements, weakRSAKeySize, webhookSignatureVerification, xssVulnerability, xxeVulnerability };
|
|
513
|
+
export { type AIFilterResult, type Confidence, type CustomRule, type DetectedFramework, type Exposure, type FilteredFinding, type Finding, type GradeResult, type ParsedFile, RULE_IMPACTS, type RuleMatch, type SecurityGrade, type Severity, type TaintMap, allCustomRules, allRules, androidDebuggable, blockingMainThread, buildTaintMap, calculateGrade, callSpreads, callbackHell, classifyExposure, clickjacking, clientComponentSecret, clientSideAuth, commandInjection, complianceMap, consoleLogProduction, corsLocalhost, corsServerless, corsWildcard, dangerousInnerHTML, deprecatedTLS, detectFramework, disabledTLSVerification, djangoDebug, dockerCopySensitive, dockerLatestTag, dockerRunAsRoot, dockerTooManyPorts, dockerfileADDInsteadOfCOPY, dockerfileMissingHealthcheck, dockerfileUnverifiedShellPipe, ecbModeEncryption, electronNavigationUnrestricted, emptyCatchBlock, envNotGitignored, evalUsage, eventListenerLeak, exposedAdminRoutes, exposedAuthSecret, exposedDBCredentials, exposedDatabaseStudio, exposedDebugMode, exposedDockerPorts, exposedEnvFile, exposedGitDir, exposedServerActions, exposedSourceMaps, exposedStackTraces, filterFalsePositives, firebaseClientConfig, flaskSecretKey, freeRules, getObjectProperty, getSnippet, ghaExpressionInjection, ghaPermissionsWriteAll, ghaPullRequestTargetCheckout, ghaThirdPartyActionWithSecrets, githubActionsInjection, graphqlCSRFDisabled, graphqlIntrospection, graphqlNoComplexityLimit, graphqlNoDepthLimit, hardcodedAlgoliaAdminKey, hardcodedAnthropicKey, hardcodedCloudflareToken, hardcodedCohereKey, hardcodedDatadogKey, hardcodedDiscordToken, hardcodedEncryptionKey, hardcodedFastlyToken, hardcodedFireworksKey, hardcodedFlyToken, hardcodedGCPServiceAccount, hardcodedGitHubPAT, hardcodedGitLabToken, hardcodedGroqKey, hardcodedHighlightKey, hardcodedIPAllowlist, hardcodedIntercomToken, hardcodedJWTSecret, hardcodedLinearKey, hardcodedLogtailToken, hardcodedLoopsKey, hardcodedMailgunKey, hardcodedMistralKey, hardcodedNetlifyToken, hardcodedNotionKey, hardcodedOAuthSecret, hardcodedPineconeKey, hardcodedPlivoToken, hardcodedPostmarkKey, hardcodedQdrantKey, hardcodedRailwayToken, hardcodedReplicateKey, hardcodedResendKey, hardcodedSecrets, hardcodedSendGridKey, hardcodedSentryAuthToken, hardcodedShopifyToken, hardcodedSlackToken, hardcodedSupabaseServiceRole, hardcodedTogetherKey, hardcodedTwilioKey, hardcodedVaultToken, hardcodedVercelToken, hardcodedWeaviateKey, hostHeaderRedirect, httpRequestSmuggling, insecureCookies, insecureDeepLink, insecureDeserialization, insecureDirectObjectReference, insecureElectronWindow, insecureFileUpload, insecureGRPC, insecureHTTPMethods, insecurePasswordReset, insecureRandomness, insecureWebSocket, ipcPathTraversal, isCalleeNamed, isMethodCall, javaDeserialization, jwtAlgConfusion, k8sNoResourceLimits, k8sPrivileged, k8sSecretNotEncrypted, lambdaWithoutVPC, largeBundleImport, llmCallNoMaxTokens, llmOutputAsHTML, llmOutputToSink, llmPromptInjection, llmSystemPromptInjection, logInjection, magicNumbers, massAssignment, middlewareMatcherExcludesApi, missingAIRateLimit, missingAuthMiddleware, missingAuthRateLimit, missingBruteForce, missingCSP, missingCSRF, missingCertPinning, missingCloudTrail, missingContentDisposition, missingDBEncryption, missingErrorBoundary, missingFileSizeLimits, missingHSTS, missingHTTPS, missingLockFile, missingOAuthState, missingPagination, missingRequestSizeLimit, missingRequestValidation, missingSRI, missingSecurityMeta, nPlusOneQuery, nextPublicSecret, noRateLimiting, nosqlInjection, openRedirectParams, overlyPermissiveIAM, parseFile, pathTraversal, pickleDeserialization, piiInLogs, prototypePollution, pyDjangoAllowedHostsWildcard, pyDjangoMarkSafe, pyJWTDecodeWeakConfig, pyJinja2AutoescapeOff, pyParamikoAutoAdd, pyRequestsVerifyFalse, pyTempfileMktemp, raceCondition, rdsPubliclyAccessible, reflectedCORSOrigin, regexDos, runCustomRules, s3BucketNoEncryption, scanEntropy, secretInBundleConfig, secretInCLIArgument, secretInErrorResponse, secretInHTMLAttribute, secretInLLMPrompt, secretInURLParam, secretLoggedToConsole, secretsInCI, securityGroupAllInbound, sensitiveAsyncStorage, sensitiveLocalStorage, sensitiveURLParams, sessionFixation, sqlInjection, ssrfVulnerability, ssti, stripeWebhookUnprotected, supabaseAnonAdmin, supabaseNoRLS, syncFileOps, terraformStateExposed, timingAttack, todoLeftInCode, unencryptedPII, unpinnedGitHubAction, unprotectedAPIRoutes, unprotectedDownload, unsafeObjectAssign, unsanitizedFilenames, unsanitizedHTMLExport, unvalidatedAPIParams, unvalidatedEventData, unvalidatedRedirect, vectorStoreQueryNoUserFilter, vectorStoreUpsertNoMetadata, visitBinary, visitCalls, vulnerableDependencies, weakHashing, weakPasswordRequirements, weakRSAKeySize, webhookMissingIdempotency, webhookSignatureVerification, xssVulnerability, xxeVulnerability };
|
package/dist/index.js
CHANGED
|
@@ -217,7 +217,11 @@ var RULE_IMPACTS = {
|
|
|
217
217
|
VC203: "An LLM call without max_tokens lets attackers craft inputs that maximize output length, generating expensive responses on every request \u2014 denial-of-wallet that drains your monthly budget or trips rate limits for legitimate users.",
|
|
218
218
|
VC204: "Without a query depth limit, attackers send 100-level-deep nested queries that explode in resolver and DB cost. The server walks every level, the database does too, and a single crafted query takes the service down.",
|
|
219
219
|
VC205: "Even with a depth limit, queries like users(first:1000){posts(first:1000){comments(first:1000)}} are only three levels deep but resolve a billion items. Without complexity analysis, attackers DoS your GraphQL with a single request.",
|
|
220
|
-
VC206: "Apollo Server's csrfPrevention guards against cross-site form-style requests against GraphQL mutations. Disabling it lets any website trigger mutations in a logged-in user's browser \u2014 buying, deleting, or transferring on the victim's behalf."
|
|
220
|
+
VC206: "Apollo Server's csrfPrevention guards against cross-site form-style requests against GraphQL mutations. Disabling it lets any website trigger mutations in a logged-in user's browser \u2014 buying, deleting, or transferring on the victim's behalf.",
|
|
221
|
+
VC207: "Model output is attacker-influenceable via prompt injection. Feeding it into eval, new Function, a shell command, a raw SQL string, or a filesystem path turns a crafted or hallucinated response into remote code execution, command injection, SQL injection, or path traversal \u2014 your most dangerous sinks, driven by untrusted text.",
|
|
222
|
+
VC208: "Interpolating a secret into a prompt ships your API key, token, or password to a third-party model provider, where it persists in their request logs and training-eligible data. A credential that leaves your infrastructure in prompt text should be considered compromised and rotated.",
|
|
223
|
+
VC209: "Webhooks are delivered at-least-once. Without de-duplicating on the event id, a retried or replayed delivery re-runs the side effect \u2014 a customer is charged twice, a record is duplicated, or an entitlement is granted again. Stripe and Svix both retry on any non-2xx, so this fires in normal operation, not just under attack.",
|
|
224
|
+
VC210: "If your auth middleware skips /api, those routes run with no gate unless each one re-checks auth itself. It is the most common way a Next.js app ends up with publicly callable API routes that everyone assumed the middleware was protecting."
|
|
221
225
|
};
|
|
222
226
|
|
|
223
227
|
// src/exposure.ts
|
|
@@ -3685,9 +3689,9 @@ var xxeVulnerability = {
|
|
|
3685
3689
|
));
|
|
3686
3690
|
}
|
|
3687
3691
|
}
|
|
3688
|
-
if (!/parseXml\s*\(/.test(content)) return matches;
|
|
3692
|
+
if (!/parseXml\s*\(/.test(content)) return filterSilenced(matches, content, "VC081");
|
|
3689
3693
|
const ctx = tryParse(content, filePath);
|
|
3690
|
-
if (!ctx) return matches;
|
|
3694
|
+
if (!ctx) return filterSilenced(matches, content, "VC081");
|
|
3691
3695
|
visitCalls(
|
|
3692
3696
|
ctx.parsed,
|
|
3693
3697
|
(callee) => isCalleeNamed(callee, "parseXml") || isCalleeNamed(callee, "parseXML"),
|
|
@@ -3711,7 +3715,7 @@ var xxeVulnerability = {
|
|
|
3711
3715
|
);
|
|
3712
3716
|
}
|
|
3713
3717
|
);
|
|
3714
|
-
return matches;
|
|
3718
|
+
return filterSilenced(matches, content, "VC081");
|
|
3715
3719
|
}
|
|
3716
3720
|
};
|
|
3717
3721
|
var ssti = {
|
|
@@ -3740,7 +3744,7 @@ var ssti = {
|
|
|
3740
3744
|
));
|
|
3741
3745
|
}
|
|
3742
3746
|
if (!/(?:\.compile|\.render|renderString|render_template_string)\s*\(/.test(content)) {
|
|
3743
|
-
return matches;
|
|
3747
|
+
return filterSilenced(matches, content, "VC082");
|
|
3744
3748
|
}
|
|
3745
3749
|
const ctx = tryParse(content, filePath);
|
|
3746
3750
|
if (!ctx) return matches;
|
|
@@ -3779,7 +3783,7 @@ var ssti = {
|
|
|
3779
3783
|
);
|
|
3780
3784
|
}
|
|
3781
3785
|
);
|
|
3782
|
-
return matches;
|
|
3786
|
+
return filterSilenced(matches, content, "VC082");
|
|
3783
3787
|
}
|
|
3784
3788
|
};
|
|
3785
3789
|
var javaDeserialization = {
|
|
@@ -4100,7 +4104,7 @@ var commandInjection = {
|
|
|
4100
4104
|
matches.push(m);
|
|
4101
4105
|
}
|
|
4102
4106
|
}
|
|
4103
|
-
return matches;
|
|
4107
|
+
return filterSilenced(matches, content, "VC094");
|
|
4104
4108
|
}
|
|
4105
4109
|
};
|
|
4106
4110
|
var corsLocalhost = {
|
|
@@ -4402,8 +4406,18 @@ var complianceMap = {
|
|
|
4402
4406
|
// no query depth limit
|
|
4403
4407
|
VC205: { owasp: "A04:2021", cwe: "CWE-770" },
|
|
4404
4408
|
// no query complexity limit
|
|
4405
|
-
VC206: { owasp: "A01:2021", cwe: "CWE-352" }
|
|
4409
|
+
VC206: { owasp: "A01:2021", cwe: "CWE-352" },
|
|
4406
4410
|
// Apollo csrfPrevention: false
|
|
4411
|
+
// VC207–VC208: AI/LLM data-flow
|
|
4412
|
+
VC207: { owasp: "A03:2021", cwe: "CWE-94" },
|
|
4413
|
+
// model output → code/cmd/query/fs sink
|
|
4414
|
+
VC208: { owasp: "A09:2021", cwe: "CWE-532" },
|
|
4415
|
+
// secret interpolated into LLM prompt
|
|
4416
|
+
// VC209–VC210: advisory heuristics
|
|
4417
|
+
VC209: { owasp: "A04:2021", cwe: "CWE-799" },
|
|
4418
|
+
// webhook missing idempotency
|
|
4419
|
+
VC210: { owasp: "A01:2021", cwe: "CWE-862" }
|
|
4420
|
+
// middleware matcher excludes /api
|
|
4407
4421
|
};
|
|
4408
4422
|
var consoleLogProduction = {
|
|
4409
4423
|
id: "VC097",
|
|
@@ -6785,7 +6799,7 @@ var llmPromptInjection = {
|
|
|
6785
6799
|
});
|
|
6786
6800
|
}
|
|
6787
6801
|
}
|
|
6788
|
-
return findings;
|
|
6802
|
+
return filterSilenced(findings, content, "VC198");
|
|
6789
6803
|
}
|
|
6790
6804
|
};
|
|
6791
6805
|
var llmSystemPromptInjection = {
|
|
@@ -6822,7 +6836,7 @@ var llmSystemPromptInjection = {
|
|
|
6822
6836
|
});
|
|
6823
6837
|
}
|
|
6824
6838
|
}
|
|
6825
|
-
return findings;
|
|
6839
|
+
return filterSilenced(findings, content, "VC199");
|
|
6826
6840
|
}
|
|
6827
6841
|
};
|
|
6828
6842
|
var llmOutputAsHTML = {
|
|
@@ -6866,7 +6880,7 @@ var llmOutputAsHTML = {
|
|
|
6866
6880
|
});
|
|
6867
6881
|
}
|
|
6868
6882
|
}
|
|
6869
|
-
return findings;
|
|
6883
|
+
return filterSilenced(findings, content, "VC200");
|
|
6870
6884
|
}
|
|
6871
6885
|
};
|
|
6872
6886
|
var vectorStoreQueryNoUserFilter = {
|
|
@@ -7098,6 +7112,127 @@ var graphqlCSRFDisabled = {
|
|
|
7098
7112
|
return findings;
|
|
7099
7113
|
}
|
|
7100
7114
|
};
|
|
7115
|
+
var LLM_OUTPUT_SHAPE = "(?:choices\\s*\\[\\s*\\d*\\s*\\]?\\s*\\.\\s*message(?:\\s*\\.\\s*content)?|completion(?:\\.text|\\.content)?|message\\s*\\.\\s*content|content_block|delta\\s*\\.\\s*text|generated_text|output_text)";
|
|
7116
|
+
var llmOutputToSink = {
|
|
7117
|
+
id: "VC207",
|
|
7118
|
+
title: "AI/LLM: model output passed to a code, command, query, or file sink",
|
|
7119
|
+
severity: "critical",
|
|
7120
|
+
category: "Injection",
|
|
7121
|
+
description: "Passing model output into eval(), new Function(), a shell command, a raw SQL string, or a filesystem path treats the model's response as trusted code. A prompt-injected or hallucinated response then becomes RCE, command injection, SQL injection, or path traversal \u2014 the model is an attacker-influenced input wired straight into your most dangerous sinks.",
|
|
7122
|
+
check(content, filePath) {
|
|
7123
|
+
if (!LLM_FILE_RE.test(filePath)) return [];
|
|
7124
|
+
if (isTestFile(filePath)) return [];
|
|
7125
|
+
if (!fileUsesLLMSDK(content)) return [];
|
|
7126
|
+
const sinkGroups = [
|
|
7127
|
+
"eval",
|
|
7128
|
+
"new\\s+Function",
|
|
7129
|
+
"(?:child_process\\s*\\.\\s*)?(?:exec|execSync|spawn|spawnSync|execFile|execFileSync)",
|
|
7130
|
+
"(?:\\$queryRawUnsafe|\\$executeRawUnsafe|\\.\\s*(?:query|execute|raw))",
|
|
7131
|
+
"(?:fs\\s*\\.\\s*)?(?:readFile|readFileSync|writeFile|writeFileSync|createReadStream|createWriteStream|unlink|unlinkSync|rm|rmSync)"
|
|
7132
|
+
];
|
|
7133
|
+
const matches = [];
|
|
7134
|
+
for (const sink of sinkGroups) {
|
|
7135
|
+
const re = new RegExp(`\\b${sink}\\s*\\([^;\\n]{0,120}${LLM_OUTPUT_SHAPE}`, "g");
|
|
7136
|
+
matches.push(...findMatches(
|
|
7137
|
+
content,
|
|
7138
|
+
re,
|
|
7139
|
+
llmOutputToSink,
|
|
7140
|
+
filePath,
|
|
7141
|
+
() => "Never pass model output into eval / new Function / a shell command / a raw SQL string / a filesystem path. Treat it as untrusted input: constrain it to a JSON schema or an allowlist, and use parameterized queries and safe path APIs. If this is a reviewed, sandboxed use, add an inline `// VC207-OK: <reason>` comment to silence."
|
|
7142
|
+
));
|
|
7143
|
+
}
|
|
7144
|
+
return filterSilenced(matches, content, "VC207");
|
|
7145
|
+
}
|
|
7146
|
+
};
|
|
7147
|
+
var secretInLLMPrompt = {
|
|
7148
|
+
id: "VC208",
|
|
7149
|
+
title: "AI/LLM: secret or credential interpolated into a model prompt",
|
|
7150
|
+
severity: "high",
|
|
7151
|
+
category: "Information Leakage",
|
|
7152
|
+
description: "Interpolating an environment secret (API key, token, password) into a prompt sends your credential to a third-party model provider, where it can land in their request logs and training-eligible data. Secrets should never be part of prompt text \u2014 pass only the data the model needs to reason about.",
|
|
7153
|
+
check(content, filePath) {
|
|
7154
|
+
if (!LLM_FILE_RE.test(filePath)) return [];
|
|
7155
|
+
if (isTestFile(filePath)) return [];
|
|
7156
|
+
if (!fileUsesLLMSDK(content)) return [];
|
|
7157
|
+
const SECRET_ENV = /\$\{\s*process\.env\.[A-Z0-9_]*(?:KEY|SECRET|TOKEN|PASSWORD|PASSWD|CREDENTIAL|PRIVATE)[A-Z0-9_]*\s*\}/;
|
|
7158
|
+
const PROMPT_CTX = /\b(?:prompt|content|system|user|assistant|messages|instructions?|systemPrompt|userPrompt)\b/i;
|
|
7159
|
+
const lines = content.split("\n");
|
|
7160
|
+
const matches = [];
|
|
7161
|
+
for (let i = 0; i < lines.length; i++) {
|
|
7162
|
+
const line = lines[i];
|
|
7163
|
+
if (!SECRET_ENV.test(line)) continue;
|
|
7164
|
+
const trimmed = line.trimStart();
|
|
7165
|
+
if (trimmed.startsWith("//") || trimmed.startsWith("*") || trimmed.startsWith("#")) continue;
|
|
7166
|
+
const prev = i > 0 ? lines[i - 1] : "";
|
|
7167
|
+
if (!PROMPT_CTX.test(line) && !PROMPT_CTX.test(prev)) continue;
|
|
7168
|
+
matches.push({
|
|
7169
|
+
rule: "VC208",
|
|
7170
|
+
title: secretInLLMPrompt.title,
|
|
7171
|
+
severity: "high",
|
|
7172
|
+
category: "Information Leakage",
|
|
7173
|
+
file: filePath,
|
|
7174
|
+
line: i + 1,
|
|
7175
|
+
snippet: getSnippet(content, i + 1),
|
|
7176
|
+
fix: "Don't put credentials in prompt text \u2014 they get sent to (and logged by) the model provider. Pass only the data the model needs; keep secrets in headers/SDK config. If this env var is genuinely non-sensitive despite its name, add an inline `// VC208-OK: <reason>` comment."
|
|
7177
|
+
});
|
|
7178
|
+
}
|
|
7179
|
+
return filterSilenced(matches, content, "VC208");
|
|
7180
|
+
}
|
|
7181
|
+
};
|
|
7182
|
+
var webhookMissingIdempotency = {
|
|
7183
|
+
id: "VC209",
|
|
7184
|
+
title: "Webhook handler without idempotency / replay protection",
|
|
7185
|
+
severity: "low",
|
|
7186
|
+
category: "Logic",
|
|
7187
|
+
description: "Payment and event webhooks (Stripe, Svix, GitHub, ...) are delivered at-least-once. A handler that performs a side effect (create / charge / grant) without de-duplicating on the event ID can double-process a retried or replayed delivery \u2014 double charges, duplicate records, repeated entitlement grants.",
|
|
7188
|
+
check(content, filePath) {
|
|
7189
|
+
if (!/\.(js|ts|jsx|tsx)$/.test(filePath)) return [];
|
|
7190
|
+
if (isTestFile(filePath)) return [];
|
|
7191
|
+
if (!/constructEvent|new\s+Webhook\s*\(|svix|verifyHeader|x-signature|stripe-signature/i.test(content)) return [];
|
|
7192
|
+
if (!/\.(?:create|update|upsert|insert|delete)\s*\(|INSERT\s+INTO|charges?\.create|subscriptions?\.create|\bgrant|entitlement/i.test(content)) return [];
|
|
7193
|
+
if (/idempoten|event\.id|evt\.id|delivery_?id|alreadyProcessed|processedEvents|ON\s+CONFLICT|INSERT\s+OR\s+IGNORE|\bseen\b|\bprocessed\b/i.test(content)) return [];
|
|
7194
|
+
const m = content.match(/constructEvent|new\s+Webhook\s*\(|verifyHeader/i);
|
|
7195
|
+
if (!m || m.index === void 0) return [];
|
|
7196
|
+
const line = content.substring(0, m.index).split("\n").length;
|
|
7197
|
+
return filterSilenced([{
|
|
7198
|
+
rule: "VC209",
|
|
7199
|
+
title: webhookMissingIdempotency.title,
|
|
7200
|
+
severity: "low",
|
|
7201
|
+
category: "Logic",
|
|
7202
|
+
file: filePath,
|
|
7203
|
+
line,
|
|
7204
|
+
snippet: getSnippet(content, line),
|
|
7205
|
+
fix: "De-duplicate webhook deliveries: persist each event id and skip if already seen, or use a DB unique constraint (INSERT ... ON CONFLICT DO NOTHING). Webhooks are at-least-once \u2014 assume retries. If dedup is handled elsewhere, add an inline `// VC209-OK: <reason>` comment."
|
|
7206
|
+
}], content, "VC209");
|
|
7207
|
+
}
|
|
7208
|
+
};
|
|
7209
|
+
var middlewareMatcherExcludesApi = {
|
|
7210
|
+
id: "VC210",
|
|
7211
|
+
title: "Auth middleware matcher excludes API routes",
|
|
7212
|
+
severity: "info",
|
|
7213
|
+
category: "Authorization",
|
|
7214
|
+
description: "A Next.js middleware that performs authentication but whose config.matcher excludes /api means API routes bypass the middleware entirely. Unless each API route authenticates on its own, they're unprotected. This is an advisory to verify per-route auth \u2014 not a confirmed vulnerability.",
|
|
7215
|
+
check(content, filePath) {
|
|
7216
|
+
if (!/middleware\.(ts|js|mjs)$/.test(filePath)) return [];
|
|
7217
|
+
if (isTestFile(filePath)) return [];
|
|
7218
|
+
if (!/clerkMiddleware|authMiddleware|getToken|getServerSession|NextResponse\.redirect|withAuth|next-auth|\bauth\s*\(/i.test(content)) return [];
|
|
7219
|
+
if (!/matcher\s*:/.test(content)) return [];
|
|
7220
|
+
if (!/\(\?!\s*[^)]*\bapi\b/.test(content)) return [];
|
|
7221
|
+
const m = content.match(/matcher\s*:/);
|
|
7222
|
+
if (!m || m.index === void 0) return [];
|
|
7223
|
+
const line = content.substring(0, m.index).split("\n").length;
|
|
7224
|
+
return filterSilenced([{
|
|
7225
|
+
rule: "VC210",
|
|
7226
|
+
title: middlewareMatcherExcludesApi.title,
|
|
7227
|
+
severity: "info",
|
|
7228
|
+
category: "Authorization",
|
|
7229
|
+
file: filePath,
|
|
7230
|
+
line,
|
|
7231
|
+
snippet: getSnippet(content, line),
|
|
7232
|
+
fix: "Your middleware's matcher excludes /api, so API routes skip it. Either include /api in the matcher, or confirm every API route authenticates on its own (auth() / requireUser / getServerSession). If routes self-authenticate by design, add an inline `// VC210-OK: <reason>` comment."
|
|
7233
|
+
}], content, "VC210");
|
|
7234
|
+
}
|
|
7235
|
+
};
|
|
7101
7236
|
var secretInURLParam = {
|
|
7102
7237
|
id: "VC146",
|
|
7103
7238
|
title: "Secret Passed in URL Query Parameter",
|
|
@@ -7817,6 +7952,12 @@ var allCustomRules = [
|
|
|
7817
7952
|
vectorStoreQueryNoUserFilter,
|
|
7818
7953
|
vectorStoreUpsertNoMetadata,
|
|
7819
7954
|
llmCallNoMaxTokens,
|
|
7955
|
+
// VC207–VC208: AI/LLM data-flow rules
|
|
7956
|
+
llmOutputToSink,
|
|
7957
|
+
secretInLLMPrompt,
|
|
7958
|
+
// VC209–VC210: advisory heuristics
|
|
7959
|
+
webhookMissingIdempotency,
|
|
7960
|
+
middlewareMatcherExcludesApi,
|
|
7820
7961
|
// VC204–VC206: GraphQL server hardening
|
|
7821
7962
|
graphqlNoDepthLimit,
|
|
7822
7963
|
graphqlNoComplexityLimit,
|
|
@@ -8302,11 +8443,13 @@ export {
|
|
|
8302
8443
|
largeBundleImport,
|
|
8303
8444
|
llmCallNoMaxTokens,
|
|
8304
8445
|
llmOutputAsHTML,
|
|
8446
|
+
llmOutputToSink,
|
|
8305
8447
|
llmPromptInjection,
|
|
8306
8448
|
llmSystemPromptInjection,
|
|
8307
8449
|
logInjection,
|
|
8308
8450
|
magicNumbers,
|
|
8309
8451
|
massAssignment,
|
|
8452
|
+
middlewareMatcherExcludesApi,
|
|
8310
8453
|
missingAIRateLimit,
|
|
8311
8454
|
missingAuthMiddleware,
|
|
8312
8455
|
missingAuthRateLimit,
|
|
@@ -8357,6 +8500,7 @@ export {
|
|
|
8357
8500
|
secretInCLIArgument,
|
|
8358
8501
|
secretInErrorResponse,
|
|
8359
8502
|
secretInHTMLAttribute,
|
|
8503
|
+
secretInLLMPrompt,
|
|
8360
8504
|
secretInURLParam,
|
|
8361
8505
|
secretLoggedToConsole,
|
|
8362
8506
|
secretsInCI,
|
|
@@ -8393,6 +8537,7 @@ export {
|
|
|
8393
8537
|
weakHashing,
|
|
8394
8538
|
weakPasswordRequirements,
|
|
8395
8539
|
weakRSAKeySize,
|
|
8540
|
+
webhookMissingIdempotency,
|
|
8396
8541
|
webhookSignatureVerification,
|
|
8397
8542
|
xssVulnerability,
|
|
8398
8543
|
xxeVulnerability
|