mirror of
https://github.com/GMGNAI/gmgn-skills.git
synced 2026-08-20 11:38:07 +00:00
fix(security): defend against prompt injection via token metadata
Address HackenProof report GMGNWM-143, where attacker-controlled token metadata could hijack an AI agent driving gmgn-cli into executing an unauthorized trade. Move guardrails from overridable SKILL.md text into code. - Add src/sanitize.ts: neutralize prompt-injection framing and hidden/control characters in API output (via printResult) and validate create-token metadata - Add src/confirm.ts: code-enforced human confirmation for financial writes (swap, multi-swap, order strategy create, cooking create) — reads a typed "yes" from /dev/tty; automation requires GMGN_ALLOW_AUTOMATED_TRADES=1 + --yes - Harden config.ts: tighten ~/.config/gmgn/.env to 0600 and warn if world-readable - Update SKILL.md files, Readme.md and Readme.zh.md to document the gate, the --yes flag, and untrusted-metadata handling Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
b18d7deb32
commit
fdc7a3fb16
+26
-1
@@ -1,10 +1,35 @@
|
||||
import { config as loadDotenv } from "dotenv";
|
||||
import { chmodSync, existsSync, statSync } from "fs";
|
||||
import { homedir } from "os";
|
||||
import { join } from "path";
|
||||
|
||||
const GLOBAL_ENV_PATH = join(homedir(), ".config", "gmgn", ".env");
|
||||
|
||||
// The credential file holds a plaintext private key and API key. Before loading
|
||||
// it, make sure it is not readable by other users on the machine. If the file is
|
||||
// group/other-accessible we tighten it to 0600 and warn — this reduces the blast
|
||||
// radius of the plaintext-credential storage called out in the security review.
|
||||
function enforceCredentialFilePermissions(path: string): void {
|
||||
if (process.platform === "win32" || !existsSync(path)) return;
|
||||
try {
|
||||
const mode = statSync(path).mode & 0o777;
|
||||
if (mode & 0o077) {
|
||||
chmodSync(path, 0o600);
|
||||
console.error(
|
||||
`[gmgn-cli] Warning: ${path} was accessible to other users (mode ${mode.toString(8)}). ` +
|
||||
`Permissions tightened to 600. Your GMGN private key is stored here in plaintext — ` +
|
||||
`keep this file private and consider a dedicated trading wallet with limited funds.`
|
||||
);
|
||||
}
|
||||
} catch {
|
||||
// Non-fatal: if we cannot stat/chmod, fall through to normal loading.
|
||||
}
|
||||
}
|
||||
|
||||
enforceCredentialFilePermissions(GLOBAL_ENV_PATH);
|
||||
|
||||
// Load global config first (~/.config/gmgn/.env, takes precedence), then project .env (supplements only)
|
||||
loadDotenv({ path: join(homedir(), ".config", "gmgn", ".env"), override: true });
|
||||
loadDotenv({ path: GLOBAL_ENV_PATH, override: true });
|
||||
loadDotenv();
|
||||
|
||||
export interface Config {
|
||||
|
||||
Reference in New Issue
Block a user