Skip to content

Commit 983a7c7

Browse files
Merge remote-tracking branch 'upstream/v2' into feat/intent-node/config-output-reason
2 parents df360a5 + 479701a commit 983a7c7

File tree

4 files changed

+90
-17
lines changed

4 files changed

+90
-17
lines changed

apps/common/utils/tool_code.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ def init_sandbox_dir():
7171
os.remove(sandbox_conf_file_path)
7272
banned_hosts = CONFIG.get("SANDBOX_PYTHON_BANNED_HOSTS", '').strip()
7373
allow_dl_paths = CONFIG.get("SANDBOX_PYTHON_ALLOW_DL_PATHS",'').strip()
74+
allow_dl_open = CONFIG.get("SANDBOX_PYTHON_ALLOW_DL_OPEN",'0')
7475
allow_subprocess = CONFIG.get("SANDBOX_PYTHON_ALLOW_SUBPROCESS", '0')
7576
allow_syscall = CONFIG.get("SANDBOX_PYTHON_ALLOW_SYSCALL", '0')
7677
if banned_hosts:
@@ -81,6 +82,7 @@ def init_sandbox_dir():
8182
with open(sandbox_conf_file_path, "w") as f:
8283
f.write(f"SANDBOX_PYTHON_BANNED_HOSTS={banned_hosts}\n")
8384
f.write(f"SANDBOX_PYTHON_ALLOW_DL_PATHS={','.join(sorted(set(filter(None, sys.path + _sandbox_python_sys_path + allow_dl_paths.split(',')))))}\n")
85+
f.write(f"SANDBOX_PYTHON_ALLOW_DL_OPEN={allow_dl_open}\n")
8486
f.write(f"SANDBOX_PYTHON_ALLOW_SUBPROCESS={allow_subprocess}\n")
8587
f.write(f"SANDBOX_PYTHON_ALLOW_SYSCALL={allow_syscall}\n")
8688
os.system(f"chmod -R 550 {_sandbox_path}")

installer/sandbox.c

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,18 @@
2222
#include <pty.h>
2323
#include <stdint.h>
2424
#include <stdbool.h>
25+
#include <execinfo.h>
2526

2627
#define CONFIG_FILE ".sandbox.conf"
2728
#define KEY_BANNED_HOSTS "SANDBOX_PYTHON_BANNED_HOSTS"
2829
#define KEY_ALLOW_DL_PATHS "SANDBOX_PYTHON_ALLOW_DL_PATHS"
30+
#define KEY_ALLOW_DL_OPEN "SANDBOX_PYTHON_ALLOW_DL_OPEN"
2931
#define KEY_ALLOW_SUBPROCESS "SANDBOX_PYTHON_ALLOW_SUBPROCESS"
3032
#define KEY_ALLOW_SYSCALL "SANDBOX_PYTHON_ALLOW_SYSCALL"
3133

3234
static char *banned_hosts = NULL;
3335
static char *allow_dl_paths = NULL;
36+
static int allow_dl_open = 0;
3437
static int allow_subprocess = 0; // 默认禁止
3538
static int allow_syscall = 0;
3639

@@ -39,6 +42,7 @@ static void load_sandbox_config() {
3942
if (dladdr((void *)load_sandbox_config, &info) == 0 || !info.dli_fname) {
4043
banned_hosts = strdup("");
4144
allow_dl_paths = strdup("");
45+
allow_dl_open = 0;
4246
allow_subprocess = 0;
4347
allow_syscall = 0;
4448
return;
@@ -53,6 +57,7 @@ static void load_sandbox_config() {
5357
if (!fp) {
5458
banned_hosts = strdup("");
5559
allow_dl_paths = strdup("");
60+
allow_dl_open = 0;
5661
allow_subprocess = 0;
5762
allow_syscall = 0;
5863
return;
@@ -62,6 +67,7 @@ static void load_sandbox_config() {
6267
if (allow_dl_paths) { free(allow_dl_paths); allow_dl_paths = NULL; }
6368
banned_hosts = strdup("");
6469
allow_dl_paths = strdup("");
70+
allow_dl_open = 0;
6571
allow_subprocess = 0;
6672
allow_syscall = 0;
6773
while (fgets(line, sizeof(line), fp)) {
@@ -80,6 +86,8 @@ static void load_sandbox_config() {
8086
} else if (strcmp(key, KEY_ALLOW_DL_PATHS) == 0) {
8187
free(allow_dl_paths);
8288
allow_dl_paths = strdup(value); // 逗号分隔字符串
89+
} else if (strcmp(key, KEY_ALLOW_DL_OPEN) == 0) {
90+
allow_dl_open = atoi(value);
8391
} else if (strcmp(key, KEY_ALLOW_SUBPROCESS) == 0) {
8492
allow_subprocess = atoi(value);
8593
} else if (strcmp(key, KEY_ALLOW_SYSCALL) == 0) {
@@ -519,6 +527,7 @@ long syscall(long number, ...) {
519527
#endif
520528
case SYS_fchmodat:
521529
case SYS_mprotect:
530+
case SYS_pkey_mprotect:
522531
#ifdef SYS_open
523532
case SYS_open:
524533
#endif
@@ -543,7 +552,24 @@ long syscall(long number, ...) {
543552
/**
544553
* 限制加载动态链接库
545554
*/
546-
static int is_in_allow_dl_paths(const char *filename) {
555+
static int called_from_python_import() {
556+
if (allow_dl_open) return 1;
557+
void *buf[32];
558+
int n = backtrace(buf, 32);
559+
for (int i = 0; i < n; i++) {
560+
Dl_info info;
561+
if (dladdr(buf[i], &info) && info.dli_sname) {
562+
if (strstr(info.dli_sname, "PyImport") ||
563+
strstr(info.dli_sname, "_PyImport")) {
564+
return 1;
565+
}
566+
}
567+
}
568+
throw_permission_denied_err(true, "open dynamic link library");
569+
return 0;
570+
}
571+
static int is_allow_dl(const char *filename) {
572+
if (!called_from_python_import()) return 0;
547573
if (!filename || !*filename) return 1;
548574
ensure_config_loaded();
549575
if (!allow_dl_paths || !*allow_dl_paths) return 0;
@@ -570,7 +596,7 @@ static int is_in_allow_dl_paths(const char *filename) {
570596
}
571597
void *dlopen(const char *filename, int flag) {
572598
RESOLVE_REAL(dlopen);
573-
if (is_sandbox_user() && !is_in_allow_dl_paths(filename)) {
599+
if (is_sandbox_user() && !is_allow_dl(filename)) {
574600
throw_permission_denied_err(true, "access file %s", filename);
575601
}
576602
return real_dlopen(filename, flag);
@@ -580,7 +606,7 @@ void *__dlopen(const char *filename, int flag) {
580606
}
581607
void *dlmopen(Lmid_t lmid, const char *filename, int flags) {
582608
RESOLVE_REAL(dlmopen);
583-
if (is_sandbox_user() && !is_in_allow_dl_paths(filename)) {
609+
if (is_sandbox_user() && !is_allow_dl(filename)) {
584610
throw_permission_denied_err(true, "access file %s", filename);
585611
}
586612
return real_dlmopen(lmid, filename, flags);
@@ -602,7 +628,7 @@ void* mmap(void *addr, size_t len, int prot, int flags, int fd, off_t off) {
602628
throw_permission_denied_err(true, "mmap(readlink failed)");
603629
}
604630
real_path[n] = '\0';
605-
if (!is_in_allow_dl_paths(real_path)) {
631+
if (!is_allow_dl(real_path)) {
606632
throw_permission_denied_err(true, "mmap %s", real_path);
607633
}
608634
}

ui/src/components/ai-chat/index.vue

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,14 @@ provide('getSelectModelList', (params: any) => {
208208
return loadSharedApi({ type: 'model', systemType: 'workspace' }).getSelectModelList(params)
209209
}
210210
})
211+
provide('chatUserProfile', () => {
212+
if (props.type === 'ai-chat') {
213+
if (chatUser.chat_profile?.authentication_type === 'login') {
214+
return chatUser.getChatUserProfile()
215+
}
216+
}
217+
return Promise.resolve(null)
218+
})
211219
212220
const transcribing = ref<boolean>(false)
213221
defineOptions({ name: 'AiChat' })
@@ -798,16 +806,6 @@ const handleScroll = () => {
798806
}
799807
}
800808
}
801-
onBeforeMount(() => {
802-
window.chatUserProfile = () => {
803-
if (props.type === 'ai-chat') {
804-
if (chatUser.chat_profile?.authentication_type === 'login') {
805-
return chatUser.getChatUserProfile()
806-
}
807-
}
808-
return Promise.resolve(null)
809-
}
810-
})
811809
812810
function parseTransform(transformStr: string) {
813811
const result = { scale: 1, translateX: 0, translateY: 0, translateZ: 0 }

ui/src/components/markdown/HtmlRander.vue

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
</template>
1010

1111
<script setup lang="ts">
12-
import { computed, ref, onMounted, onBeforeUnmount } from 'vue'
13-
12+
import { computed, ref, onMounted, onBeforeUnmount, inject } from 'vue'
13+
const chatUserProfile = inject('chatUserProfile') as any
1414
const htmlRef = ref<HTMLIFrameElement>()
1515
const props = withDefaults(
1616
defineProps<{
@@ -37,6 +37,40 @@ function createIframeHtml(sourceHtml: string) {
3737
* { margin: 0; padding: 0; box-sizing: border-box; }
3838
html, body { margin: 0 !important; padding: 0 !important; overflow: hidden; }
3939
</style>
40+
<script>
41+
const _INSTANCE_ID = '${instanceId}';
42+
window.chatUserProfile=function chatUserProfile() {
43+
return new Promise((resolve, reject) => {
44+
const requestId = Date.now() + '_' + Math.random()
45+
46+
function handler(e) {
47+
const data = e.data
48+
49+
if (
50+
data?.type === 'chatUserProfile:response' &&
51+
data.requestId === requestId
52+
) {
53+
window.removeEventListener('message', handler)
54+
resolve(data.data)
55+
}
56+
}
57+
window.addEventListener('message', handler)
58+
parent.postMessage(
59+
{
60+
type: 'chatUserProfile',
61+
requestId,
62+
instanceId: _INSTANCE_ID
63+
},
64+
'*'
65+
)
66+
67+
setTimeout(() => {
68+
window.removeEventListener('message', handler)
69+
reject(new Error('timeout'))
70+
}, 10000)
71+
})
72+
}
73+
<\/script>
4074
</head>
4175
<body>
4276
${sourceHtml}
@@ -46,7 +80,6 @@ const INSTANCE_ID = '${instanceId}';
4680
function sendMessage(message) {
4781
parent.postMessage({ type: 'chatMessage', instanceId: INSTANCE_ID, message }, '*');
4882
}
49-
5083
let lastSentHeight = 0;
5184
let timer = null;
5285
@@ -88,6 +121,20 @@ function onMessage(e: MessageEvent) {
88121
if (e.data.type === 'chatMessage') {
89122
props.sendMessage?.(e.data.message, 'new')
90123
}
124+
if (e.data?.type === 'chatUserProfile') {
125+
const iframe = htmlRef.value
126+
if (!iframe) return
127+
chatUserProfile().then((ok: any) => {
128+
iframe.contentWindow?.postMessage(
129+
{
130+
type: 'chatUserProfile:response',
131+
requestId: e.data.requestId,
132+
data: ok,
133+
},
134+
'*',
135+
)
136+
})
137+
}
91138
}
92139
93140
onMounted(() => {

0 commit comments

Comments
 (0)