Files
sim/biome.json
T
Waleed d0519c1503 fix(security): supabase rpc path validation, ssh stream byte cap, storage quota coverage (#4605)
* 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).
2026-05-14 17:08:09 -07:00

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
}
}
}