mirror of
https://github.com/simstudioai/sim.git
synced 2026-09-24 15:45:35 +08:00
* fix(security): supabase rpc path validation, ssh stream byte cap, storage quota coverage
* fix(security): scope execution log writes to owning workflow; add env-var workspace membership guard
Closes two cross-tenant vulnerabilities:
1. Workflow log cross-tenant write (route.ts + logging-session.ts):
- Route: SELECT before creating LoggingSession to verify executionId belongs
to the claimed workflowId; reject with 404 if owned by a different workflow.
- LoggingSession: add workflow_id to all UPDATE/SELECT WHERE clauses
(raw SQL marker queries, flushAccumulatedCost, loadExistingCost) so
writes are a no-op if executionId was somehow injected.
2. Env-var workspace membership guard (environment/utils.ts):
- getPersonalAndWorkspaceEnv now calls checkWorkspaceAccess when workspaceId
is provided; throws if the userId is not a member, preventing any future
caller from reading another workspace's decrypted secrets without
explicit membership verification at the call site.
* fix(security): remove fileSize > 0 quota bypass gate; exempt logs context from quota
* chore: remove extraneous inline comments
* fix(security): scope markExecutionAsFailed UPDATE by workflowId; thread workflowId through HITL callers
* fix(security): add personal credential ownership check in sharepoint site route; scope markExecutionAsFailed by workflowId
* fix: remove logs from user-accessible upload contexts; restore distinct biome .next glob
* fix(sharepoint): migrate site route to authorizeCredentialUse
The previous fix only checked userId equality for personal credentials and
workspace membership (via getUserEntityPermissions) for workspace credentials.
authorizeCredentialUse additionally enforces credentialMember access for
workspace-scoped credentials, matching the standard pattern used by all
other tool selector routes.
* fix(logging): make workflowId required in markExecutionAsFailed
Making workflowId optional left a footgun — future callers could silently
omit it and the WHERE clause would degrade to executionId-only, losing the
cross-tenant scoping guarantee. All callers already supply workflowId, so
making it required (with string | undefined for the middle params to keep
call sites unchanged) closes the gap without touching any caller.
* test(security): add tests for cross-tenant log guard, quota bypass fix, and workflowId scoping
- log/route.test.ts: verifies cross-tenant executionId guard returns 404
when the execution belongs to a different workflow, and passes for same
workflow or fresh executions
- multipart/route.test.ts: verifies fileSize:0 no longer bypasses quota
check and that the logs context is rejected at the endpoint level
- logging-session.test.ts: verifies markExecutionAsFailed scopes by both
executionId and workflowId, and that the instance method forwards workflowId
* fix(lint): move IconComponent outside ToolInput to fix noNestedComponentDefinitions
* fix(logging): scope completeWithCancellation and completeWithPause reads by workflowId
Both SELECT queries that check execution status before writing a
terminal result were only filtering on executionId. Adds workflowId
to the WHERE clause so all seven reads and writes in LoggingSession
consistently scope by (workflowId, executionId).
156 lines
3.8 KiB
JSON
156 lines
3.8 KiB
JSON
{
|
|
"$schema": "https://biomejs.dev/schemas/2.0.0-beta.5/schema.json",
|
|
"vcs": { "enabled": true, "clientKind": "git", "useIgnoreFile": false },
|
|
"files": {
|
|
"ignoreUnknown": false,
|
|
"includes": [
|
|
"**",
|
|
"!**/.next",
|
|
"!**/.next",
|
|
"!**/next-env.d.ts",
|
|
"!**/out",
|
|
"!**/dist",
|
|
"!**/build",
|
|
"!**/node_modules",
|
|
"!**/.bun",
|
|
"!**/.cache",
|
|
"!**/.turbo",
|
|
"!**/.DS_Store",
|
|
"!**/*.pem",
|
|
"!**/bun-debug.log*",
|
|
"!**/.env*.local",
|
|
"!**/.env",
|
|
"!**/.vercel",
|
|
"!**/coverage",
|
|
"!**/public/sw.js",
|
|
"!**/public/workbox-*.js",
|
|
"!**/public/worker-*.js",
|
|
"!**/public/fallback-*.js",
|
|
"!**/apps/docs/.source",
|
|
"!**/venv",
|
|
"!**/.venv",
|
|
"!**/uploads",
|
|
"!**/apps/sim/lib/execution/sandbox/bundles/*.cjs"
|
|
]
|
|
},
|
|
"formatter": {
|
|
"enabled": true,
|
|
"useEditorconfig": true,
|
|
"formatWithErrors": false,
|
|
"indentStyle": "space",
|
|
"indentWidth": 2,
|
|
"lineEnding": "lf",
|
|
"lineWidth": 100,
|
|
"attributePosition": "auto",
|
|
"bracketSpacing": true
|
|
},
|
|
"assist": {
|
|
"actions": {
|
|
"source": {
|
|
"organizeImports": {
|
|
"level": "on",
|
|
"options": {
|
|
"groups": [
|
|
[":NODE:", "react", "react/**"],
|
|
":PACKAGE:",
|
|
"@/components/**",
|
|
"@/lib/**",
|
|
"@/app/**",
|
|
":ALIAS:",
|
|
":RELATIVE:"
|
|
]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"linter": {
|
|
"enabled": true,
|
|
"rules": {
|
|
"recommended": true,
|
|
"nursery": {
|
|
"useSortedClasses": "warn"
|
|
},
|
|
"a11y": {
|
|
"noSvgWithoutTitle": "off",
|
|
"useAltText": "off",
|
|
"useKeyWithClickEvents": "off",
|
|
"noRedundantAlt": "off",
|
|
"useSemanticElements": "off",
|
|
"useButtonType": "off",
|
|
"useFocusableInteractive": "off",
|
|
"noStaticElementInteractions": "off",
|
|
"useAriaPropsSupportedByRole": "off",
|
|
"useAriaPropsForRole": "off"
|
|
},
|
|
"suspicious": {
|
|
"noImplicitAnyLet": "off",
|
|
"noArrayIndexKey": "off",
|
|
"noExplicitAny": "off",
|
|
"noControlCharactersInRegex": "off",
|
|
"noThenProperty": "off",
|
|
"noAssignInExpressions": "off",
|
|
"noDocumentCookie": "off"
|
|
},
|
|
"correctness": {
|
|
"useExhaustiveDependencies": "off",
|
|
"noUnusedFunctionParameters": "off",
|
|
"noUnusedVariables": "off"
|
|
},
|
|
"security": {
|
|
"noDangerouslySetInnerHtml": "off"
|
|
},
|
|
"style": {
|
|
"noDescendingSpecificity": "off",
|
|
"noNonNullAssertion": "off",
|
|
"noParameterAssign": "off",
|
|
"useNodejsImportProtocol": "off",
|
|
"useAsConstAssertion": "error",
|
|
"useDefaultParameterLast": "error",
|
|
"useEnumInitializers": "error",
|
|
"useSelfClosingElements": "error",
|
|
"useSingleVarDeclarator": "error",
|
|
"noUnusedTemplateLiteral": "off",
|
|
"useNumberNamespace": "error",
|
|
"noInferrableTypes": "error",
|
|
"noUselessElse": "error"
|
|
},
|
|
"complexity": {
|
|
"noForEach": "off",
|
|
"noUselessFragments": "off",
|
|
"noStaticOnlyClass": "off"
|
|
},
|
|
"performance": {
|
|
"noAccumulatingSpread": "off",
|
|
"noDelete": "error",
|
|
"noImgElement": "off"
|
|
}
|
|
}
|
|
},
|
|
"javascript": {
|
|
"formatter": {
|
|
"jsxQuoteStyle": "single",
|
|
"quoteProperties": "asNeeded",
|
|
"trailingCommas": "es5",
|
|
"semicolons": "asNeeded",
|
|
"arrowParentheses": "always",
|
|
"bracketSameLine": false,
|
|
"quoteStyle": "single",
|
|
"attributePosition": "auto",
|
|
"bracketSpacing": true
|
|
}
|
|
},
|
|
"css": {
|
|
"formatter": {
|
|
"enabled": true,
|
|
"indentWidth": 2
|
|
}
|
|
},
|
|
"json": {
|
|
"formatter": {
|
|
"enabled": true,
|
|
"indentWidth": 2
|
|
}
|
|
}
|
|
}
|