最新资讯
bloomberg.com 科技股抛售后,Anthropic IPO 估值承压 dev.to 当“按设计工作”成为问题:Claude Code 与 .NET 用户机密 dev.to 用代理修复 3500 个 Sonar 问题花 44 美元,让结果可信花 520 美元 dev.to 底层陷阱:为何企业 AI 使用率跑赢其 EBIT 影响 thenewstack.io Cursor 推出全托管应用部署,对标 Lovable 与 Replit techrepublic.com METR 评估显示 Anthropic 模型进展近乎翻倍,IT 采购方需关注什么 bloomberg.com Nvidia AI 芯片出口成为民主党国会关注目标 computerworld.com Meta 撤回争议性企业 AI 条款 bloomberg.com 台积电据报考虑生产先进 AI 存储芯片 www.infoq.com Yelp 为 AI Assistant 融合原生与服务器驱动 UI computerworld.com 英国监管机构:企业须为自家 AI 代理的错误负责 siliconangle.com Atomicwork 推出面向企业 IT 与安全的认证 AI 同事市场
多元动态
登录 注册
大模型 dev.to · @the bomber

把语音指令转为安全操作:先正则,后语言模型

原文 我的收藏

作者为自建家庭自动化服务器设计两段式过滤:先用严格正则白名单匹配有限动作(开灯、备份、状态查询),不匹配即拒绝,再交给 LLM 补全细节,以降低提示注入转为任意 shell 命令的风险;文中未提供攻击测试或量化评估。

AI推荐理由 提出先用严格正则白名单做确定性闸门、再由 LLM 补全参数的两段式语音指令过滤,以降低提示注入导致任意命令执行的风险,思路具体且可复用;但为个人小项目,未给出攻击测试或量化评估。

63

正文

Introduction I built a tiny voice‑controlled home automation server for my own website. The goal was simple: speak a command, have the server execute a safe action (turn a light on, start a backup, etc.). The tricky part is making sure the spoken text can’t be turned into an arbitrary shell command. My solution is a two‑step filter – a strict regular‑expression whitelist first, then a language‑model (LLM) to fill in the details. Why regex first? Regular expressions give me a deterministic gate. Anything that doesn’t match a known pattern is rejected before it ever reaches the LLM. This prevents prompt injection attacks where a user tries to sneak a malicious instruction into the natural‑language prompt. In my experience the overhead of a few regex checks is negligible compared to the round‑trip to the OpenAI API. Designing the command grammar I started by listing the actions I actually want to expose: light on|off backup now status From that list I wrote a single regex that captures the intent and the arguments: // commandRegex.js export const commandRegex = /^(light)\s+(living|kitchen|bedroom)\s+(on|off)$|^(backup)\s+now$|^(status)\s+(nginx|postgres)$/i; Enter fullscreen mode Exit fullscreen mode The pattern is deliberately simple – each branch matches one of the allowed commands. If a spoken phrase doesn’t match, the request is dropped with a 400 response. Hooking up the speech recognizer On the client side I use the Web Speech API because it works in Chrome without any extra libraries. The recognizer sends the raw transcript to my Node server via a POST request. // public/voice.js const btn = document.getElementById('talk'); const recognition = new (window.SpeechRecognition || window.webkitSpeechRecognition)(); recognition.lang = 'en-US'; recognition.interimResults = false; btn.onclick = () => recognition.start(); recognition.onresult = e => { const transcript = e.results[0][0].transcript.trim(); fetch('/api/command', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({text: transcript}) }) .then(r => r.json()) .then(console.log); }; Enter fullscreen mode Exit fullscreen mode The server receives {"text":"light kitchen on"} and runs it through the regex. Using a language model for intent Once the regex validates the shape, I still need to translate the captured groups into concrete parameters (e.g., which GPIO pin controls the kitchen light). I keep that mapping in a JSON file and ask the LLM to produce the final command string. The prompt is static and never includes user‑provided text directly. // intentResolver.js import {Configuration, OpenAIApi} from 'openai'; import {commandRegex} from './commandRegex.js'; import pinMap from './pinMap.json'; const openai = new OpenAIApi(new Configuration({apiKey: process.env.OPENAI_API_KEY})); export async function resolveIntent(rawText) { const match = rawText.match(commandRegex); if (!match) throw new Error('Invalid command'); // Extract intent and args from the regex groups const [_, intent, room, state, backup, statusService] = match; // Build a deterministic prompt – no user text interpolation const prompt = `You are a helper that converts structured intent data into a shell command. Intent: ${intent || backup || statusService} Parameters: ${JSON.stringify({room, state, service: statusService})} Return only the command, nothing else.`; const response = await openai.createChatCompletion({ model: 'gpt-4o-mini', messages: [{role: 'user', content: prompt}], temperature: 0, }); const command = response.data.choices[0].message.content.trim(); return command; } Enter fullscreen mode Exit fullscreen mode Because the prompt never contains the raw transcript, the LLM cannot be tricked into echoing back malicious text. The only variable data it sees are the intent name and a sanitized JSON object. Safety checks Even after the LLM returns a command, I run a final whitelist of allowed shell snippets. This is a second line of defense in case the model hallucinates. // safeCommands.js export const safeCommands = [ /^gpio write \d+ (1|0)$/, // turn a pin on/off /^rsync -avz .* backup$/, // run a backup /^systemctl status (nginx|postgres)$/ ]; export function isSafe(cmd) { return safeCommands.some(rx => rx.test(cmd)); } Enter fullscreen mode Exit fullscreen mode If isSafe returns false, the request is logged and rejected. Putting it together The Express route ties all pieces together: // server.js import express from 'express'; import {resolveIntent} from './intentResolver.js'; import {isSafe} from './safeCommands.js'; import {exec} from 'child_process'; const app = express(); app.use(express.json()); app.post('/api/command', async (req, res) => { const {text} = req.body; try { const cmd = await resolveIntent(text); if (!isSafe(cmd)) throw new Error('Command failed safety check'); exec(cmd, (err, stdout, stderr) => { if (err) return res.status(500).json({error: err.message}); res.json({output: stdout || stderr}); }); } catch (e) { console.error(e); res.status(400).json({error: e.message}); } }); app.listen(3000, () => console.log('Voice command server listening on :3000')); Enter fullscreen mode Exit fullscreen mode All the heavy lifting is deterministic: regex → intent → LLM prompt → safety whitelist → exec. Deployment considerations I run this server on a Raspberry Pi at home, but the same code works on any Linux box. A few practical tips: Environment isolation – use a systemd service that runs the Node process as a non‑root user. Rate limiting – the Web Speech API can be noisy; a simple token bucket middleware prevents abuse. Logging – store the raw transcript, the resolved command, and the safety check result. This makes debugging prompt‑injection attempts easier. Model cost – because the prompt is tiny and temperature is 0, the cost per request is a few fractions of a cent. Conclusion By front‑loading a strict regex filter, I keep the attack surface small enough that the LLM can be used safely for natural‑language expansion. The pattern works for any limited command set: define a grammar, whitelist the resulting shell, and let the model fill in the boring details. I’ve been running this for months with no false positives, and the approach scales nicely when I add new devices – just extend the regex and the safe‑command list. I build sites and automations for small businesses at dreamfuturestech.com.

来源报道 · 1 篇 · 以下链接均前往原始媒体

← 返回精选动态 原文

更多内容