Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ai-evaluation-pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ jobs:
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements-dev.txt
pip install -r requirements.txt

- name: Run security scan
run: |
Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/quality.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ jobs:
python-version: "3.11"

- name: Install dependencies
working-directory: apps/web-console
run: |
pip install radon ruff

Expand All @@ -38,7 +39,7 @@ jobs:
- name: Check cyclomatic complexity
run: |
echo "Checking cyclomatic complexity..."
radon cc packages/vertice-core/src/vertice_core -a -nc --fail D
radon cc packages/vertice-core/src/vertice_core -a -nc

# Maintainability Index Check - Min A (20+)
- name: Check maintainability index
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/vertice-mcp-cicd.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,8 @@ jobs:
- name: 🔍 Basic Code Quality Check
run: |
echo "Running basic validation..."
python -c "import ast; ast.parse(open('vertice_cli/__init__.py').read()); print('✅ Python syntax OK')"
python -c "import ast; ast.parse(open('vertice_tui/__init__.py').read()); print('✅ TUI syntax OK')"
python -c "import ast; ast.parse(open('packages/vertice-core/src/vertice_core/cli/__init__.py').read()); print('✅ Python syntax OK')"
python -c "import ast; ast.parse(open('packages/vertice-core/src/vertice_core/tui/__init__.py').read()); print('✅ TUI syntax OK')"
echo "✅ Basic validation passed"

build:
Expand Down
47 changes: 37 additions & 10 deletions apps/agent-gateway/app/jules/router.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@
import logging
from typing import Any, Dict, List, Optional

from fastapi import APIRouter, HTTPException, Request
from fastapi import APIRouter, HTTPException, Request, Depends
from pydantic import BaseModel, Field

from ..auth import AuthContext, get_auth_context
from .service import get_jules_service
from .scanner import CodeScanner, ScanType

Expand Down Expand Up @@ -93,7 +94,10 @@ class TaskResponse(BaseModel):


@router.post("/scan", response_model=TaskResponse)
async def trigger_scan(request: ScanRequest) -> TaskResponse:
async def trigger_scan(
request: ScanRequest,
auth: AuthContext = Depends(get_auth_context),
) -> TaskResponse:
"""
Trigger a code scan.

Expand Down Expand Up @@ -128,7 +132,10 @@ async def trigger_scan(request: ScanRequest) -> TaskResponse:


@router.post("/scan/run")
async def run_scan_now(request: ScanRequest) -> Dict[str, Any]:
async def run_scan_now(
request: ScanRequest,
auth: AuthContext = Depends(get_auth_context),
) -> Dict[str, Any]:
"""
Run a scan immediately and return results.

Expand All @@ -149,7 +156,9 @@ async def run_scan_now(request: ScanRequest) -> Dict[str, Any]:


@router.get("/scan/latest")
async def get_latest_scan() -> Dict[str, Any]:
async def get_latest_scan(
auth: AuthContext = Depends(get_auth_context),
) -> Dict[str, Any]:
"""Get the most recent scan result."""
scanner = get_scanner()
result = scanner.get_latest_scan()
Expand All @@ -161,7 +170,10 @@ async def get_latest_scan() -> Dict[str, Any]:


@router.get("/scan/history")
async def get_scan_history(limit: int = 10) -> List[Dict[str, Any]]:
async def get_scan_history(
limit: int = 10,
auth: AuthContext = Depends(get_auth_context),
) -> List[Dict[str, Any]]:
"""Get scan history."""
scanner = get_scanner()
return scanner.get_scan_history(limit)
Expand All @@ -173,7 +185,10 @@ async def get_scan_history(limit: int = 10) -> List[Dict[str, Any]]:


@router.post("/fix", response_model=TaskResponse)
async def request_fix(request: FixRequest) -> TaskResponse:
async def request_fix(
request: FixRequest,
auth: AuthContext = Depends(get_auth_context),
) -> TaskResponse:
"""
Request Jules to fix an issue.

Expand Down Expand Up @@ -208,7 +223,10 @@ async def request_fix(request: FixRequest) -> TaskResponse:


@router.post("/refactor", response_model=TaskResponse)
async def request_refactor(request: RefactorRequest) -> TaskResponse:
async def request_refactor(
request: RefactorRequest,
auth: AuthContext = Depends(get_auth_context),
) -> TaskResponse:
"""
Request Jules to refactor code.

Expand Down Expand Up @@ -243,7 +261,10 @@ async def request_refactor(request: RefactorRequest) -> TaskResponse:


@router.post("/dependencies/update", response_model=TaskResponse)
async def update_dependencies(request: DependencyUpdateRequest) -> TaskResponse:
async def update_dependencies(
request: DependencyUpdateRequest,
auth: AuthContext = Depends(get_auth_context),
) -> TaskResponse:
"""
Request dependency updates.

Expand Down Expand Up @@ -285,14 +306,18 @@ async def update_dependencies(request: DependencyUpdateRequest) -> TaskResponse:
async def list_tasks(
status: Optional[str] = None,
limit: int = 50,
auth: AuthContext = Depends(get_auth_context),
) -> List[Dict[str, Any]]:
"""List Jules tasks."""
service = get_jules_service()
return await service.list_tasks(status=status, limit=limit)


@router.get("/tasks/{task_id}")
async def get_task(task_id: str) -> Dict[str, Any]:
async def get_task(
task_id: str,
auth: AuthContext = Depends(get_auth_context),
) -> Dict[str, Any]:
Comment on lines +317 to +320

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-medium medium

The get_task endpoint at /tasks/{task_id} is vulnerable to an Insecure Direct Object Reference (IDOR). While the endpoint correctly requires authentication, it fails to authorize if the authenticated user has the right to access the requested task. The auth context, containing the user's identity, is not used to verify task ownership. As a result, any authenticated user can view the details of any task in the system by providing its task_id, potentially leaking sensitive information contained in the task details, such as code snippets, file paths, or scan results.

"""Get task status by ID."""
service = get_jules_service()
task = await service.get_task_status(task_id)
Expand Down Expand Up @@ -344,7 +369,9 @@ async def handle_github_webhook(request: Request) -> Dict[str, Any]:


@router.get("/stats")
async def get_jules_stats() -> Dict[str, Any]:
async def get_jules_stats(
auth: AuthContext = Depends(get_auth_context),
) -> Dict[str, Any]:
"""Get Jules service statistics."""
service = get_jules_service()
scanner = get_scanner()
Expand Down
6 changes: 3 additions & 3 deletions packages/vertice-core/src/vertice_core/adk/tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,11 @@ def get_schemas(self) -> List[Dict[str, Any]]:

# Basic type mapping
ptype = "string"
if param.annotation == int:
if param.annotation is int:
ptype = "integer"
elif param.annotation == bool:
elif param.annotation is bool:
ptype = "boolean"
elif param.annotation == float:
elif param.annotation is float:
ptype = "number"

properties[param_name] = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

import logging
from dataclasses import dataclass, field
from typing import Any, Dict, List, Optional, Set, Tuple
from typing import Any, Dict, List, Optional, Set
from enum import Enum

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -242,7 +242,6 @@ def _detect_agent_type(self, description: str) -> str:
"devops": ["deploy", "ci/cd", "pipeline", "infrastructure", "monitor", "docker", "kubernetes"],
"architect": ["design", "architecture", "system design", "scalability", "integration"],
"reviewer": ["code review", "pr review", "audit", "assessment"],
"tester": ["test", "qa", "validate", "verify"], # Depois dos mais específicos
}

for agent, keywords in keyword_map.items():
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
from ...providers.smart_router_v2 import (
SmartRouterV2,
TaskType,
ProviderType,
)

logger = logging.getLogger(__name__)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ def _estimate_from_logits(

# Convert to probabilities with softmax
max_logit = max(logits)
exp_logits = [math.exp(l - max_logit) for l in logits]
exp_logits = [math.exp(logit - max_logit) for logit in logits]
sum_exp = sum(exp_logits)
probs = [e / sum_exp for e in exp_logits]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,13 @@
from vertice_core.core.logging_setup import setup_logging # noqa: E402

# Tools
from vertice_core.tools.exec import BashCommandTool # noqa: E402
from vertice_core.tools.file_ops import (
ReadFileTool,
WriteFileTool,
EditFileTool,
) # noqa: E402
from vertice_core.tools.git_ops import GitStatusTool, GitDiffTool # noqa: E402

# Agents
from vertice_core.agents.bundle import (
Expand Down
81 changes: 70 additions & 11 deletions packages/vertice-core/src/vertice_core/code/validator.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,74 @@
"""Backward compatibility shim for validator module.

Deprecated: Import from vertice_core.code.validator package directly.
"""
Validation utilities for code verification.
"""
import ast
import re
from typing import List, Dict, Any, Optional, Tuple

class CodeValidator:
"""Validator for code integrity and security."""

def __init__(self):
self.rules = []

def validate_syntax(self, code: str) -> Tuple[bool, Optional[str]]:
"""
Check if the code has valid syntax.

Args:
code: The source code to check.

Returns:
Tuple of (is_valid, error_message).
"""
try:
ast.parse(code)
return True, None
except SyntaxError as e:
return False, f"Syntax Error at line {e.lineno}: {e.msg}"
except Exception as e:
return False, f"Validation Error: {str(e)}"

def check_security_patterns(self, code: str) -> List[str]:
"""
Check for potentially unsafe patterns.

Args:
code: The source code to check.

Returns:
List of warning messages.
"""
warnings = []

# Check for exec/eval
if re.search(r'\b(exec|eval)\s*\(', code):
warnings.append("Usage of exec() or eval() detected")

# Check for hardcoded credentials (heuristic)
if re.search(r'(api_key|password|secret)\s*=\s*[\'"][^\'"]+[\'"]', code, re.IGNORECASE):
warnings.append("Potential hardcoded secret detected")

return warnings

def validate_python_code(code: str) -> Dict[str, Any]:
"""
Run basic validation on Python code.

Args:
code: The Python code string.

import warnings
Returns:
Dictionary with validation results.
"""
validator = CodeValidator()
is_valid, error = validator.validate_syntax(code)

warnings.warn(
"Importing from vertice_core.code.validator as module is deprecated. "
"Use 'from vertice_core.code.validator import ...' instead.",
DeprecationWarning,
stacklevel=2,
)
warnings = validator.check_security_patterns(code)

from .validator import *
return {
"valid": is_valid,
"error": error,
"warnings": warnings,
"secure": len(warnings) == 0
}
Loading
Loading