import assert from "node:assert/strict"; import { mkdir, mkdtemp, rm, writeFile } from "node:fs/promises"; import { tmpdir } from "node:os"; import { join } from "node:path"; import test from "node:test"; import { KNOWLEDGE_FS_INTEGRATION_EXACT_PATHS, KNOWLEDGE_FS_INTEGRATION_PREFIXES, evaluateFindings, isKnowledgeFsIntegrationPath, parseAllowlist, scanDirectory, scanIntegrationSurface, scanText, } from "./secret-scan.mjs"; const EXPECTED_NON_SEMANTIC_INTEGRATION_PATHS = [ ".github/dependabot.yml", ".github/workflows/knowledge-fs-ci.yml", "api/.env.example", "api/app_factory.py", "api/commands/__init__.py", "api/controllers/console/__init__.py", "api/controllers/console/workspace/rbac.py", "api/controllers/service_api/__init__.py", "api/core/agent/base_agent_runner.py", "api/core/app/apps/agent_app/runtime_request_builder.py", "api/core/rbac/entities.py", "api/core/tools/__base/tool_runtime.py", "api/core/tools/builtin_tool/_position.yaml", "api/core/workflow/node_runtime.py", "api/core/workflow/nodes/agent_v2/runtime_request_builder.py", "api/extensions/ext_celery.py", "api/extensions/ext_commands.py", "api/models/__init__.py", "api/pyproject.toml", "api/services/account_service.py", "api/services/agent_tool_inner_service.py", "api/services/enterprise/rbac_service.py", "api/services/entities/agent_tool_inner.py", "api/tests/unit_tests/controllers/console/workspace/test_rbac.py", "api/tests/unit_tests/core/agent/test_base_agent_runner.py", "api/tests/unit_tests/core/app/apps/agent_app/test_runtime_request_builder.py", "api/tests/unit_tests/core/workflow/nodes/agent_v2/test_runtime_request_builder.py", "api/tests/unit_tests/core/workflow/nodes/tool/test_tool_node_runtime.py", "api/tests/unit_tests/core/workflow/test_node_runtime.py", "api/tests/unit_tests/services/enterprise/test_rbac_service.py", "api/tests/unit_tests/services/test_account_service.py", "api/tests/unit_tests/services/test_agent_tool_inner_service.py", "api/uv.lock", "dify-agent/src/dify_agent/layers/dify_core_tools/client.py", "dify-agent/tests/local/dify_agent/layers/dify_core_tools/test_client.py", "docker/.env.example", "docker/README.md", "docker/dify-env-sync.py", "docker/dify-env-sync.sh", "docker/docker-compose-template.yaml", "docker/docker-compose.yaml", "docker/envs/core-services/api.env.example", "docker/envs/core-services/knowledge-fs.env.example", "docker/generate_docker_compose", ]; const EXPECTED_INTEGRATION_PREFIXES = [ { path: "knowledge-fs/", workflowPattern: "knowledge-fs/**" }, { path: "packages/contracts/generated/api/console/", workflowPattern: "packages/contracts/generated/api/console/**", }, { path: "packages/contracts/generated/api/service/", workflowPattern: "packages/contracts/generated/api/service/**", }, ]; test("secret scan reports high-confidence credentials without echoing their value", () => { const credential = ["AKIA", "ABCDEFGHIJKLMNOP"].join(""); const findings = scanText({ content: `export const credential = "${credential}";\n`, path: "apps/api/src/config.ts", }); assert.deepEqual( findings.map(({ column, line, path, rule }) => ({ column, line, path, rule })), [ { column: 28, line: 1, path: "apps/api/src/config.ts", rule: "aws-access-key-id", }, ], ); assert.match(findings[0].fingerprint, /^[a-f0-9]{64}$/); assert.equal(Object.hasOwn(findings[0], "value"), false); assert.equal(JSON.stringify(findings).includes(credential), false); }); test("secret scan recognizes JWTs and private keys", () => { const jwt = [ "eyJhbGciOiJSUzI1NiJ9", "eyJzdWIiOiJwcm9kdWN0aW9uLXVzZXIifQ", "signature_material_that_is_long_enough", ].join("."); const privateKey = [ ["-----BEGIN PRIVATE", " KEY-----"].join(""), "synthetic-key-material-for-a-secret-scan-unit-test", ["-----END PRIVATE", " KEY-----"].join(""), ].join("\n"); const findings = scanText({ content: `${jwt}\n${privateKey}\n`, path: "fixtures/input.txt", }); assert.deepEqual( findings.map(({ line, rule }) => ({ line, rule })), [ { line: 1, rule: "jwt" }, { line: 2, rule: "private-key" }, ], ); }); test("secret scan recognizes Dify KnowledgeFS credentials without flagging database names", () => { const credential = ["kfs_", "Aa0", "b".repeat(40)].join(""); const findings = scanText({ content: [ `raw_credential = "${credential}"`, 'index_name = "kfs_control_space_tenant_state_updated_idx"', 'table_name = "kfs_capability_issuance_reservations"', 'ann_table = "kfs_ann_dense_0123456789abcdef0123456789abcdef"', ].join("\n"), path: "api/services/knowledge_fs/credential_service.py", }); assert.deepEqual( findings.map(({ line, rule }) => ({ line, rule })), [{ line: 1, rule: "dify-knowledge-fs-credential" }], ); }); test("secret scan accepts every valid character class distribution in a Dify credential", () => { const credentials = [ ["kfs_", "a".repeat(43)].join(""), ["kfs_", "A".repeat(43)].join(""), ["kfs_", "7".repeat(43)].join(""), ["kfs_", "-".repeat(43)].join(""), ["kfs_", "aA".repeat(21), "_"].join(""), ]; const findings = scanText({ content: credentials.join("\n"), path: "api/services/knowledge_fs/credential_service.py", }); assert.deepEqual( findings.map(({ line, rule }) => ({ line, rule })), credentials.map((_, index) => ({ line: index + 1, rule: "dify-knowledge-fs-credential", })), ); }); test("integration surface keeps a complete auditable list of non-semantic touchpoints", () => { assert.deepEqual(KNOWLEDGE_FS_INTEGRATION_EXACT_PATHS, EXPECTED_NON_SEMANTIC_INTEGRATION_PATHS); assert.deepEqual(KNOWLEDGE_FS_INTEGRATION_PREFIXES, EXPECTED_INTEGRATION_PREFIXES); for (const path of EXPECTED_NON_SEMANTIC_INTEGRATION_PATHS) { assert.equal(isKnowledgeFsIntegrationPath(path), true, `scanner is missing ${path}`); } for (const prefix of EXPECTED_INTEGRATION_PREFIXES) { assert.equal( isKnowledgeFsIntegrationPath(`${prefix.path}representative-file.txt`), true, `scanner is missing ${prefix.path}`, ); } }); test("allowlist entries are exact, justified, and cannot exclude a whole production file", () => { const credential = ["ghp_", "abcdefghijklmnopqrstuvwxyz0123456789"].join(""); const [finding] = scanText({ content: `const token = "${credential}";\n`, path: "contracts/public-test-vector.json", }); const allowlist = parseAllowlist({ entries: [ { fingerprint: finding.fingerprint, line: finding.line, path: finding.path, reason: "Published synthetic interoperability vector.", rule: finding.rule, }, ], version: 1, }); assert.deepEqual(evaluateFindings([finding], allowlist), { staleAllowlistEntries: [], unallowedFindings: [], }); assert.throws( () => parseAllowlist({ entries: [ { path: "apps/api/src/**", reason: "Do not scan production.", rule: "*", }, ], version: 1, }), /exact path, line, rule, fingerprint, and reason/, ); }); test("changed or removed allowlisted values fail closed", () => { const token = ["xoxb-", "123456789012-abcdefghijklmnopqrstuvwxyz"].join(""); const [finding] = scanText({ content: token, path: "contracts/vector.json" }); const allowlist = parseAllowlist({ entries: [ { fingerprint: "0".repeat(64), line: finding.line, path: finding.path, reason: "Published synthetic interoperability vector.", rule: finding.rule, }, ], version: 1, }); const result = evaluateFindings([finding], allowlist); assert.deepEqual(result.unallowedFindings, [finding]); assert.deepEqual(result.staleAllowlistEntries, allowlist.entries); }); test("directory scan includes production and test sources but skips build output", async () => { const root = await mkdtemp(join(tmpdir(), "knowledge-fs-secret-scan-")); try { await mkdir(join(root, "apps/api/src"), { recursive: true }); await mkdir(join(root, "packages/api/src"), { recursive: true }); await mkdir(join(root, "node_modules/vendor"), { recursive: true }); await mkdir(join(root, "coverage"), { recursive: true }); const productionToken = ["AIza", "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"].join(""); const testToken = ["sk_live_", "abcdefghijklmnopqrstuvwxyz0123456789"].join(""); await writeFile(join(root, "apps/api/src/config.ts"), productionToken); await writeFile(join(root, "packages/api/src/config.test.ts"), testToken); await writeFile(join(root, "node_modules/vendor/index.js"), productionToken); await writeFile(join(root, "coverage/report.json"), productionToken); const findings = await scanDirectory(root); assert.deepEqual( findings.map(({ path, rule }) => ({ path, rule })), [ { path: "apps/api/src/config.ts", rule: "google-api-key" }, { path: "packages/api/src/config.test.ts", rule: "stripe-live-secret" }, ], ); } finally { await rm(root, { force: true, recursive: true }); } }); test("integration scan covers the complete KnowledgeFS and Dify integration surface", async () => { const root = await mkdtemp(join(tmpdir(), "knowledge-fs-integration-secret-scan-")); const token = ["AKIA", "ABCDEFGHIJKLMNOP"].join(""); const expectedPaths = [ "knowledge-fs/apps/api/src/config.ts", "api/app_factory.py", "api/controllers/console/knowledge_fs/resources.py", "api/extensions/ext_knowledge_fs_observability.py", "api/models/knowledge_fs.py", "api/repositories/sqlalchemy_knowledge_fs_control_space_repository.py", "api/services/knowledge_fs/credential_service.py", "api/tasks/knowledge_fs_lifecycle_tasks.py", "api/migrations/versions/2026_07_21_add_knowledge_fs.py", "docker/docker-compose.yaml", "docker/envs/core-services/knowledge-fs.env.example", ]; try { for (const path of expectedPaths) { await mkdir(join(root, path, ".."), { recursive: true }); await writeFile(join(root, path), token); } await mkdir(join(root, "api/services/unrelated"), { recursive: true }); await writeFile(join(root, "api/services/unrelated/config.py"), token); const findings = await scanIntegrationSurface(root); assert.deepEqual( findings.map(({ path }) => path), expectedPaths.toSorted(), ); } finally { await rm(root, { force: true, recursive: true }); } });