feat(security): enhance file path validation and implement non-root D… (#5474)

* feat(security): enhance file path validation and implement non-root Docker user

- Validate resolved full file paths including workspace boundaries in SecureFileStore
- Resolve paths before validation in readFile and writeFile operations
- Run Docker container as non-root flowise user (uid/gid 1001)
- Apply proper file ownership and permissions for application files

Prevents path traversal attacks and follows container security best practices

* Add sensitive system directory validation and Flowise internal file protection

* Update Dockerfile to use default node user

* update validation patterns to include additional system binary directories (/usr/bin, /usr/sbin, /usr/local/bin)

* added isSafeBrowserExecutable function to validate browser executable paths for Playwright and Puppeteer loaders

---------

Co-authored-by: taraka-vishnumolakala <taraka.vishnumolakala@workday.com>
Co-authored-by: Henry Heng <henryheng@flowiseai.com>
Co-authored-by: Henry <hzj94@hotmail.com>
This commit is contained in:
Taraka Vishnumolakala
2025-11-15 10:03:01 -05:00
committed by GitHub
parent 4a642f02d0
commit 2414057c08
5 changed files with 189 additions and 29 deletions
@@ -10,6 +10,7 @@ import { test } from 'linkifyjs'
import { omit } from 'lodash'
import { handleEscapeCharacters, INodeOutputsValue, webCrawl, xmlScrape } from '../../../src'
import { ICommonObject, INode, INodeData, INodeParams } from '../../../src/Interface'
import { isSafeBrowserExecutable } from '../../../src/validator'
class Playwright_DocumentLoaders implements INode {
label: string
@@ -190,11 +191,17 @@ class Playwright_DocumentLoaders implements INode {
async function playwrightLoader(url: string): Promise<Document[] | undefined> {
try {
let docs = []
const executablePath = process.env.PLAYWRIGHT_EXECUTABLE_PATH
if (!isSafeBrowserExecutable(executablePath)) {
throw new Error(`Invalid or unsafe browser executable path: ${executablePath || 'undefined'}. `)
}
const config: PlaywrightWebBaseLoaderOptions = {
launchOptions: {
args: ['--no-sandbox'],
headless: true,
executablePath: process.env.PLAYWRIGHT_EXECUTABLE_FILE_PATH
executablePath: executablePath
}
}
if (waitUntilGoToOption) {