""" Tests for Config Linter Tool """ import pytest import os import sys sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) from services.router.tool_manager import ToolManager, ToolResult class TestConfigLinterTool: """Test config linter tool functionality""" @pytest.mark.asyncio async def test_detect_api_key_in_diff(self): """Test that API keys in diff are detected as blocking""" tool_mgr = ToolManager({}) diff = """diff --git a/config/api.yaml b/config/api.yaml --- a/config/api.yaml +++ b/config/api.yaml @@ -1,3 +1,4 @@ api: - url: https://api.example.com + url: https://api.example.com + api_key: sk-1234567890abcdefghijklmnop """ result = await tool_mgr._config_linter_tool({ "source": { "type": "diff_text", "diff_text": diff }, "options": { "mask_evidence": True } }) assert result.success is True assert result.result is not None assert result.result["stats"]["blocking_count"] > 0 blocking_ids = [f["id"] for f in result.result["blocking"]] assert "CFL-003" in blocking_ids or "CFL-006" in blocking_ids @pytest.mark.asyncio async def test_detect_private_key_blocking(self): """Test that private keys are detected as blocking""" tool_mgr = ToolManager({}) diff = """diff --git a/keys/service.key b/keys/service.key --- /dev/null +++ b/keys/service.key @@ -0,0 +1,4 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA0Z3VsF3r... +-----END RSA PRIVATE KEY----- """ result = await tool_mgr._config_linter_tool({ "source": { "type": "diff_text", "diff_text": diff } }) assert result.success is True blocking_ids = [f["id"] for f in result.result["blocking"]] assert "CFL-001" in blocking_ids @pytest.mark.asyncio async def test_detect_debug_true(self): """Test DEBUG=true is detected""" tool_mgr = ToolManager({}) diff = """diff --git a/config/app.yml b/config/app.yml --- a/config/app.yml +++ b/config/app.yml @@ -1,2 +1,3 @@ app: - name: myapp + name: myapp + debug: true """ result = await tool_mgr._config_linter_tool({ "source": { "type": "diff_text", "diff_text": diff } }) assert result.success is True blocking_ids = [f["id"] for f in result.result["blocking"]] assert "CFL-101" in blocking_ids @pytest.mark.asyncio async def test_detect_cors_wildcard(self): """Test CORS wildcard is detected""" tool_mgr = ToolManager({}) diff = """diff --git a/config/cors.yaml b/config/cors.yaml --- a/config/cors.yaml +++ b/config/cors.yaml @@ -1,2 +1,3 @@ cors: - allowed_origins: + allowed_origins: + - "*" """ result = await tool_mgr._config_linter_tool({ "source": { "type": "diff_text", "diff_text": diff } }) assert result.success is True blocking_ids = [f["id"] for f in result.result["blocking"]] assert "CFL-103" in blocking_ids @pytest.mark.asyncio async def test_detect_auth_bypass(self): """Test auth bypass is detected""" tool_mgr = ToolManager({}) diff = """diff --git a/config/auth.yaml b/config/auth.yaml --- a/config/auth.yaml +++ b/config/auth.yaml @@ -1,2 +1,3 @@ auth: - enabled: true + enabled: true + skip_auth: true """ result = await tool_mgr._config_linter_tool({ "source": { "type": "diff_text", "diff_text": diff } }) assert result.success is True blocking_ids = [f["id"] for f in result.result["blocking"]] assert "CFL-104" in blocking_ids @pytest.mark.asyncio async def test_detect_docker_compose_privileged(self): """Test privileged container in docker-compose is detected""" tool_mgr = ToolManager({}) diff = """diff --git a/docker-compose.yml b/docker-compose.yml --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,3 +1,5 @@ services: app: - image: myapp:latest + image: myapp:latest + privileged: true """ result = await tool_mgr._config_linter_tool({ "source": { "type": "diff_text", "diff_text": diff } }) assert result.success is True finding_ids = [f["id"] for f in result.result["blocking"] + result.result["findings"]] assert "CFL-302" in finding_ids @pytest.mark.asyncio async def test_evidence_is_masked(self): """Test that evidence is masked when mask_evidence=true""" tool_mgr = ToolManager({}) diff = """diff --git a/.env b/.env --- a/.env +++ b/.env @@ -1,2 +1,3 @@ DATABASE_URL=postgres://localhost +API_KEY=sk-secret123456789 """ result = await tool_mgr._config_linter_tool({ "source": { "type": "diff_text", "diff_text": diff }, "options": { "mask_evidence": True } }) assert result.success is True for finding in result.result["blocking"]: assert "sk-s*" in finding["evidence"] or "***" in finding["evidence"] @pytest.mark.asyncio async def test_path_traversal_blocked(self): """Test that path traversal attempts are blocked""" tool_mgr = ToolManager({}) result = await tool_mgr._config_linter_tool({ "source": { "type": "paths", "paths": ["../../../etc/passwd", "config/app.yml"] } }) assert result.success is True blocking_ids = [f["id"] for f in result.result["blocking"]] assert "CFL-999" in blocking_ids @pytest.mark.asyncio async def test_strict_mode_fails_on_medium(self): """Test that strict mode converts medium to blocking""" tool_mgr = ToolManager({}) diff = """diff --git a/config/app.yml b/config/app.yml --- a/config/app.yml +++ b/config/app.yml @@ -1,2 +1,3 @@ app: - name: myapp + name: myapp + allowed_hosts: ["*"] """ result = await tool_mgr._config_linter_tool({ "source": { "type": "diff_text", "diff_text": diff }, "options": { "strict": True } }) assert result.success is True blocking_ids = [f["id"] for f in result.result["blocking"]] assert "CFL-106" in blocking_ids @pytest.mark.asyncio async def test_max_chars_limit(self): """Test that max_chars limit is enforced""" tool_mgr = ToolManager({}) large_diff = "a" * 500000 result = await tool_mgr._config_linter_tool({ "source": { "type": "diff_text", "diff_text": large_diff } }) assert result.success is False assert "max_chars" in result.error.lower() @pytest.mark.asyncio async def test_clean_diff_no_findings(self): """Test that clean diff has no findings""" tool_mgr = ToolManager({}) diff = """diff --git a/README.md b/README.md --- a/README.md +++ b/README.md @@ -1,2 +1,3 @@ # My Project + +New feature added """ result = await tool_mgr._config_linter_tool({ "source": { "type": "diff_text", "diff_text": diff } }) assert result.success is True assert result.result["stats"]["blocking_count"] == 0 @pytest.mark.asyncio async def test_deterministic_ordering(self): """Test that findings are in deterministic order""" tool_mgr = ToolManager({}) diff = """diff --git a/config/a.yml b/config/a.yml --- a/config/a.yml +++ b/config/a.yml @@ -1,3 +1,4 @@ +debug: true +api_key: sk-test123 +password: admin +auth_disabled: true """ result = await tool_mgr._config_linter_tool({ "source": { "type": "diff_text", "diff_text": diff } }) assert result.success is True ids = [f["id"] for f in result.result["blocking"]] assert ids == sorted(ids) @pytest.mark.asyncio async def test_github_token_detection(self): """Test GitHub token detection""" tool_mgr = ToolManager({}) diff = """diff --git a/.env b/.env --- a/.env +++ b/.env @@ -1,2 +1,3 @@ TOKEN=ghp_1234567890abcdefghijklmnopqrstuvwxyz """ result = await tool_mgr._config_linter_tool({ "source": { "type": "diff_text", "diff_text": diff } }) assert result.success is True blocking_ids = [f["id"] for f in result.result["blocking"]] assert "CFL-007" in blocking_ids @pytest.mark.asyncio async def test_aws_key_detection(self): """Test AWS key detection""" tool_mgr = ToolManager({}) diff = """diff --git a/config/aws.yaml b/config/aws.yaml --- a/config/aws.yaml +++ b/config/aws.yaml @@ -1,2 +1,3 @@ aws: access_key: AKIAIOSFODNN7EXAMPLE """ result = await tool_mgr._config_linter_tool({ "source": { "type": "diff_text", "diff_text": diff } }) assert result.success is True blocking_ids = [f["id"] for f in result.result["blocking"]] assert "CFL-009" in blocking_ids @pytest.mark.asyncio async def test_weak_password_detection(self): """Test weak password detection""" tool_mgr = ToolManager({}) diff = """diff --git a/config/db.yaml b/config/db.yaml --- a/config/db.yaml +++ b/config/db.yaml @@ -1,2 +1,3 @@ db: password: root """ result = await tool_mgr._config_linter_tool({ "source": { "type": "diff_text", "diff_text": diff } }) assert result.success is True blocking_ids = [f["id"] for f in result.result["blocking"]] assert "CFL-011" in blocking_ids @pytest.mark.asyncio async def test_container_root_user(self): """Test container root user detection""" tool_mgr = ToolManager({}) diff = """diff --git a/k8s/deployment.yaml b/k8s/deployment.yaml --- a/k8s/deployment.yaml +++ b/k8s/deployment.yaml @@ -1,3 +1,4 @@ spec: template: spec: + user: root """ result = await tool_mgr._config_linter_tool({ "source": { "type": "diff_text", "diff_text": diff } }) assert result.success is True finding_ids = [f["id"] for f in result.result["blocking"] + result.result["findings"]] assert "CFL-301" in finding_ids