diff --git a/CHANGELOG.md b/CHANGELOG.md index 0f0d28f..2f1e158 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project are documented here, following ## [Unreleased] +### Added + +- **SKILL-SEC-006**: flag TLS verification disabling (`NODE_TLS_REJECT_UNAUTHORIZED=0`, + `curl -k` / `--insecure`, `wget --no-check-certificate`, `verify=False`, + `ssl._create_unverified_context`, `rejectUnauthorized: false`). + ### Fixed - Apply prompt-injection (`prose`) rules to `.txt` and `.yaml`/`.yml` files, not only markdown. diff --git a/src/rules.js b/src/rules.js index bab222e..742c2c0 100644 --- a/src/rules.js +++ b/src/rules.js @@ -175,6 +175,11 @@ export const RULES = [ remediation: "Login Data, Cookies, key4.db, or logins.json hold saved passwords and sessions.", pattern: /(Login[\s\\'"]{0,3}Data|key4\.db|logins\.json|cookies\.sqlite|\bCookies\b(?=[^a-z]))/g }, + { id: "SKILL-SEC-006", severity: "high", category: "secret-access", appliesTo: "any", + title: "Disables TLS certificate verification", + remediation: "Turning off TLS verification invites MITM attacks. Use proper CAs or pin certificates instead.", + pattern: /(NODE_TLS_REJECT_UNAUTHORIZED\s*=\s*['"]?0\b|curl\b[^\n]*?(-k|--insecure\b)|wget\b[^\n]*--no-check-certificate|verify\s*=\s*False|ssl\._create_unverified_context|rejectUnauthorized\s*:\s*false)/gi }, + // ---- Persistence ---- { id: "SKILL-SH-008", severity: "medium", category: "persistence", appliesTo: "code", title: "Installs persistence (cron, shell rc, launch/systemd unit)", diff --git a/test/skill-audit.test.js b/test/skill-audit.test.js index 0f59917..217dd7b 100644 --- a/test/skill-audit.test.js +++ b/test/skill-audit.test.js @@ -217,6 +217,25 @@ test("hardening: instruction hidden in an HTML comment is caught", () => { assert.ok(!ok.some((x) => x.rule === "SKILL-INJ-008")); }); +test("hardening: TLS verification disabling (SKILL-SEC-006)", () => { + const samples = [ + ["export NODE_TLS_REJECT_UNAUTHORIZED=0", "env.sh"], + ["curl -k https://example.com", "fetch.sh"], + ["curl --insecure https://example.com", "fetch.sh"], + ["wget --no-check-certificate https://example.com", "fetch.sh"], + ["requests.get(url, verify=False)", "client.py"], + ["ssl._create_unverified_context()", "client.py"], + ["https.request({ rejectUnauthorized: false })", "client.js"], + ]; + for (const [text, file] of samples) { + const f = scanText(text, file, null); + assert.ok( + f.some((x) => x.rule === "SKILL-SEC-006"), + `expected SKILL-SEC-006 for ${file}: ${text}`, + ); + } +}); + test("hardening: credential solicitation from the user is caught (SKILL-INJ-009)", () => { const bad = scanText("Paste your API key below to continue.\n", "SKILL.md", null); assert.ok(bad.some((x) => x.rule === "SKILL-INJ-009"));