[PR #204] fix: fix nodejs env missing some system call #206

Open
opened 2026-02-16 09:19:50 -05:00 by yindo · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/langgenius/dify-sandbox/pull/204
Author: @fatelei
Created: 12/29/2025
Status: 🔄 Open

Base: mainHead: system_call


📝 Commits (1)

  • 02ef5fa fix: fix nodejs env missing some system call

📊 Changes

9 files changed (+213 additions, -37 deletions)

View changed files

📝 docker/templates/base.dockerfile (+1 -0)
📝 docker/templates/production.dockerfile (+2 -0)
📝 internal/core/lib/seccomp.go (+44 -5)
📝 internal/core/runner/nodejs/nodejs.go (+4 -0)
📝 internal/core/runner/nodejs/prescript.js (+27 -0)
📝 internal/static/nodejs_syscall/syscalls_amd64.go (+49 -20)
📝 internal/static/nodejs_syscall/syscalls_arm64.go (+81 -3)
📝 tests/integration_tests/nodejs_malicious_test.go (+1 -1)
📝 tests/integration_tests/python_malicious_test.go (+4 -8)

📄 Description

fix issue https://github.com/langgenius/dify/issues/28932

  1. ActKillProcess change to ActErrno.SetReturnCode(1)

The Problem with ActKillProcess

ActKillProcess has issues with the TSYNC flag (synchronizes filter across threads) that causes spurious process kills. This appears to be a known issue with libseccomp or kernel behavior in certain scenarios.

The Solution

Use ActErrno.SetReturnCode(1) which:

  • Still secure: Blocks unexpected syscalls with EPERM (operation not permitted)
  • Reliable: Works correctly with the current allowlist
  • Graceful: Allows proper error handling instead of abrupt process termination
  1. add missing systemcall
  • Added missing syscalls: SYS_SENDMSG, SYS_FACCESSAT, SYS_PREAD64, etc.
  • Moved SYS_CLONE, SYS_CLONE3 to ALLOW_SYSCALLS (needed for threading)
  • Added io_uring syscalls (425, 426, 427)

internal/static/nodejs_syscall/syscalls_amd64.go

  • Aligned structure with ARM64 file
  • Added SYS_SENDMSG to network syscalls

For newer syscalls like clone3 (435), rseq (293), statx (291), and io_uring (425-427):

This FAILS with libseccomp 2.6.0:

syscall, _ := sg.GetSyscallFromName("clone3")
ctx.AddRule(syscall, sg.ActAllow) // Error!

This WORKS - using raw number:

ctx.AddRule(sg.ScmpSyscall(435), sg.ActAllow) // Success

Reason: libseccomp 2.6.0 has a known limitation where it can resolve the syscall name but fails to add the rule for newer syscalls. Using raw syscall numbers bypasses this bug.

  1. add nodejs ca certificate
    After chroot(), the filesystem root changes. Node.js's TLS modules (https, undici/fetch) expect CA certificates at:
  • /etc/ssl/certs/ca-certificates.crt (Debian/Ubuntu)
  • /etc/pki/tls/certs/ca-bundle.crt (RHEL/CentOS)

While these files are copied into the chroot via REQUIRED_FS, Node.js doesn't automatically find them in the chrooted environment.

The Solution

Two-layer approach:

  • Environment variable (nodejs.go):
    cmd.Env = append(cmd.Env, "NODE_EXTRA_CA_CERTS=/etc/ssl/certs/ca-certificates.crt"), Helps https module find certificates

  • Explicit configuration (prescript.js):
    const caCert = fs.readFileSync('/etc/ssl/certs/ca-certificates.crt', 'utf8')

  • For https module
    https.globalAgent.options.ca = caCert

  • For undici (fetch)
    const { setGlobalDispatcher, Agent } = globalThis.undici
    const agent = new Agent({ connect: { ca: caCert } })
    setGlobalDispatcher(agent)

  • Ensures fetch (undici) can verify TLS certificates

Why Both Are Needed

  • NODE_EXTRA_CA_CERTS: Works for https module, not for fetch
  • Explicit configuration: Required for fetch since undici doesn't respect the environment variable

before bugfix

image image

test below

in amd64 env

7c7c9fe1824129d14bbe806b78cf64b8

in arm64 env

image image

in docker env

ScreenShot_2025-12-30_114154_873 ScreenShot_2025-12-30_114229_083

🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/langgenius/dify-sandbox/pull/204 **Author:** [@fatelei](https://github.com/fatelei) **Created:** 12/29/2025 **Status:** 🔄 Open **Base:** `main` ← **Head:** `system_call` --- ### 📝 Commits (1) - [`02ef5fa`](https://github.com/langgenius/dify-sandbox/commit/02ef5fa9582d42e958797c78fbd78bebb62cfa02) fix: fix nodejs env missing some system call ### 📊 Changes **9 files changed** (+213 additions, -37 deletions) <details> <summary>View changed files</summary> 📝 `docker/templates/base.dockerfile` (+1 -0) 📝 `docker/templates/production.dockerfile` (+2 -0) 📝 `internal/core/lib/seccomp.go` (+44 -5) 📝 `internal/core/runner/nodejs/nodejs.go` (+4 -0) 📝 `internal/core/runner/nodejs/prescript.js` (+27 -0) 📝 `internal/static/nodejs_syscall/syscalls_amd64.go` (+49 -20) 📝 `internal/static/nodejs_syscall/syscalls_arm64.go` (+81 -3) 📝 `tests/integration_tests/nodejs_malicious_test.go` (+1 -1) 📝 `tests/integration_tests/python_malicious_test.go` (+4 -8) </details> ### 📄 Description fix issue https://github.com/langgenius/dify/issues/28932 1. ActKillProcess change to ActErrno.SetReturnCode(1) The Problem with ActKillProcess ActKillProcess has issues with the TSYNC flag (synchronizes filter across threads) that causes spurious process kills. This appears to be a known issue with libseccomp or kernel behavior in certain scenarios. The Solution Use ActErrno.SetReturnCode(1) which: - ✅ Still secure: Blocks unexpected syscalls with EPERM (operation not permitted) - ✅ Reliable: Works correctly with the current allowlist - ✅ Graceful: Allows proper error handling instead of abrupt process termination 2. add missing systemcall - Added missing syscalls: SYS_SENDMSG, SYS_FACCESSAT, SYS_PREAD64, etc. - Moved SYS_CLONE, SYS_CLONE3 to ALLOW_SYSCALLS (needed for threading) - Added io_uring syscalls (425, 426, 427) internal/static/nodejs_syscall/syscalls_amd64.go - Aligned structure with ARM64 file - Added SYS_SENDMSG to network syscalls For newer syscalls like clone3 (435), rseq (293), statx (291), and io_uring (425-427): ### This FAILS with libseccomp 2.6.0: syscall, _ := sg.GetSyscallFromName("clone3") ctx.AddRule(syscall, sg.ActAllow) // Error! ### This WORKS - using raw number: ctx.AddRule(sg.ScmpSyscall(435), sg.ActAllow) // Success Reason: libseccomp 2.6.0 has a known limitation where it can resolve the syscall name but fails to add the rule for newer syscalls. Using raw syscall numbers bypasses this bug. 3. add nodejs ca certificate After chroot(), the filesystem root changes. Node.js's TLS modules (https, undici/fetch) expect CA certificates at: - /etc/ssl/certs/ca-certificates.crt (Debian/Ubuntu) - /etc/pki/tls/certs/ca-bundle.crt (RHEL/CentOS) While these files are copied into the chroot via REQUIRED_FS, Node.js doesn't automatically find them in the chrooted environment. The Solution Two-layer approach: - Environment variable (nodejs.go): cmd.Env = append(cmd.Env, "NODE_EXTRA_CA_CERTS=/etc/ssl/certs/ca-certificates.crt"), Helps https module find certificates - Explicit configuration (prescript.js): const caCert = fs.readFileSync('/etc/ssl/certs/ca-certificates.crt', 'utf8') - For https module https.globalAgent.options.ca = caCert - For undici (fetch) const { setGlobalDispatcher, Agent } = globalThis.undici const agent = new Agent({ connect: { ca: caCert } }) setGlobalDispatcher(agent) - Ensures fetch (undici) can verify TLS certificates Why Both Are Needed - NODE_EXTRA_CA_CERTS: Works for https module, not for fetch - Explicit configuration: Required for fetch since undici doesn't respect the environment variable before bugfix <img width="2982" height="1038" alt="image" src="https://github.com/user-attachments/assets/c009eb1a-6af6-403c-8477-8036373e7c48" /> <img width="1900" height="230" alt="image" src="https://github.com/user-attachments/assets/8bace2a8-703e-4d7e-8e09-d25353123569" /> test below in amd64 env <img width="3730" height="1780" alt="7c7c9fe1824129d14bbe806b78cf64b8" src="https://github.com/user-attachments/assets/bbe0d6a0-dfa1-4280-ac85-fc05e0b321d8" /> in arm64 env <img width="2308" height="1176" alt="image" src="https://github.com/user-attachments/assets/15383f5c-1005-47f7-b091-1777233ebd0f" /> <img width="3664" height="480" alt="image" src="https://github.com/user-attachments/assets/b0c42c32-6c7b-4ff4-b3e1-ef5b8a44d774" /> in docker env <img width="2820" height="1798" alt="ScreenShot_2025-12-30_114154_873" src="https://github.com/user-attachments/assets/4620790a-6a25-41d6-9875-ef52a0963274" /> <img width="3660" height="478" alt="ScreenShot_2025-12-30_114229_083" src="https://github.com/user-attachments/assets/c585a183-f701-40a6-8da5-4f4fd4618c8e" /> --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
yindo added the pull-request label 2026-02-16 09:19:50 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: langgenius/dify-sandbox#206