feat(llm-security): add .kt .groovy .scala to taint-tracer CODE_EXTENSIONS
This commit is contained in:
parent
037a91276d
commit
50c0cd3065
2 changed files with 84 additions and 0 deletions
|
|
@ -22,6 +22,8 @@ import { SEVERITY } from './lib/severity.mjs';
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// File extension filter — only scan code files, not config/docs
|
// File extension filter — only scan code files, not config/docs
|
||||||
|
// JVM-language support (.kt, .kts, .groovy, .gradle, .scala) is required for
|
||||||
|
// JetBrains plugin scanning — plugin source lives in these languages.
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
const CODE_EXTENSIONS = new Set([
|
const CODE_EXTENSIONS = new Set([
|
||||||
|
|
@ -32,6 +34,9 @@ const CODE_EXTENSIONS = new Set([
|
||||||
'.rb', '.php',
|
'.rb', '.php',
|
||||||
'.go', '.rs',
|
'.go', '.rs',
|
||||||
'.java', '.cs',
|
'.java', '.cs',
|
||||||
|
'.kt', '.kts',
|
||||||
|
'.groovy', '.gradle',
|
||||||
|
'.scala',
|
||||||
'.sh', '.bash', '.zsh',
|
'.sh', '.bash', '.zsh',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
|
||||||
79
plugins/llm-security/tests/scanners/taint-tracer.test.mjs
Normal file
79
plugins/llm-security/tests/scanners/taint-tracer.test.mjs
Normal file
|
|
@ -0,0 +1,79 @@
|
||||||
|
// taint-tracer.test.mjs — JVM-language CODE_EXTENSIONS coverage
|
||||||
|
//
|
||||||
|
// Verifies that the taint-tracer scans Kotlin source files (added in v6.6.0
|
||||||
|
// to support JetBrains plugin scanning). Creates a tmp fixture with an
|
||||||
|
// env-var → child_process.exec flow in a .kt file and asserts the scanner
|
||||||
|
// produces at least one finding.
|
||||||
|
|
||||||
|
import { describe, it, before, after } from 'node:test';
|
||||||
|
import assert from 'node:assert/strict';
|
||||||
|
import { mkdtemp, writeFile, rm } from 'node:fs/promises';
|
||||||
|
import { tmpdir } from 'node:os';
|
||||||
|
import { join } from 'node:path';
|
||||||
|
import { resetCounter } from '../../scanners/lib/output.mjs';
|
||||||
|
import { discoverFiles } from '../../scanners/lib/file-discovery.mjs';
|
||||||
|
import { scan } from '../../scanners/taint-tracer.mjs';
|
||||||
|
|
||||||
|
describe('taint-tracer — Kotlin (.kt) support', () => {
|
||||||
|
let fixtureDir;
|
||||||
|
|
||||||
|
before(async () => {
|
||||||
|
fixtureDir = await mkdtemp(join(tmpdir(), 'llm-security-kt-taint-'));
|
||||||
|
// Plant a source (process.env-equivalent) → sink (exec) flow in Kotlin.
|
||||||
|
// The taint-tracer is language-agnostic at the regex level — it matches
|
||||||
|
// on identifiers like System.getenv, ProcessBuilder, exec. We mirror the
|
||||||
|
// Node.js process.env pattern to exercise the shared source regex.
|
||||||
|
const ktSource = [
|
||||||
|
'class Leak {',
|
||||||
|
' fun run() {',
|
||||||
|
// Same-line source -> sink: process.env flows directly into exec()
|
||||||
|
// Mirrors the JS pattern detected by Pass 2 (same-line CRITICAL).
|
||||||
|
' Runtime.getRuntime().exec(process.env["USER_CMD"])',
|
||||||
|
// Variable-propagation case using generic source label user_input
|
||||||
|
' val tainted = user_input',
|
||||||
|
' child_process.exec(tainted)',
|
||||||
|
' }',
|
||||||
|
'}',
|
||||||
|
''
|
||||||
|
].join('\n');
|
||||||
|
await writeFile(join(fixtureDir, 'Leak.kt'), ktSource, 'utf8');
|
||||||
|
});
|
||||||
|
|
||||||
|
after(async () => {
|
||||||
|
if (fixtureDir) await rm(fixtureDir, { recursive: true, force: true });
|
||||||
|
});
|
||||||
|
|
||||||
|
it('discovers the .kt file', async () => {
|
||||||
|
const discovery = await discoverFiles(fixtureDir);
|
||||||
|
const ktFiles = discovery.files.filter(f => f.ext === '.kt');
|
||||||
|
assert.ok(ktFiles.length >= 1, `Expected ≥1 .kt file discovered, got ${ktFiles.length}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns status ok on Kotlin input', async () => {
|
||||||
|
resetCounter();
|
||||||
|
const discovery = await discoverFiles(fixtureDir);
|
||||||
|
const result = await scan(fixtureDir, discovery);
|
||||||
|
assert.equal(result.status, 'ok', `Expected status 'ok', got '${result.status}'`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('scans the .kt file (files_scanned >= 1)', async () => {
|
||||||
|
resetCounter();
|
||||||
|
const discovery = await discoverFiles(fixtureDir);
|
||||||
|
const result = await scan(fixtureDir, discovery);
|
||||||
|
assert.ok(
|
||||||
|
result.files_scanned >= 1,
|
||||||
|
`Expected files_scanned >= 1 (Kotlin file should be included), got ${result.files_scanned}`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('detects at least one taint flow in Kotlin source', async () => {
|
||||||
|
resetCounter();
|
||||||
|
const discovery = await discoverFiles(fixtureDir);
|
||||||
|
const result = await scan(fixtureDir, discovery);
|
||||||
|
assert.ok(
|
||||||
|
result.findings.length >= 1,
|
||||||
|
`Expected >= 1 taint finding in Kotlin source, got ${result.findings.length}. ` +
|
||||||
|
`Findings: ${result.findings.map(f => f.title).join('; ')}`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
Loading…
Add table
Add a link
Reference in a new issue