fix: remove stack-trace exposure in exception handlers
Some checks failed
Cross-Node Transaction Testing / transaction-test (push) Has been cancelled
Deploy to Testnet / deploy-testnet (push) Has been cancelled
Multi-Node Stress Testing / stress-test (push) Has been cancelled
Node Failover Simulation / failover-test (push) Has been cancelled
API Endpoint Tests / test-api-endpoints (push) Failing after 18m8s
Integration Tests / test-service-integration (push) Failing after 54s
Production Tests / Production Integration Tests (push) Successful in 21s
Python Tests / test-python (push) Failing after 1m13s
Security Scanning / security-scan (push) Successful in 40s
Some checks failed
Cross-Node Transaction Testing / transaction-test (push) Has been cancelled
Deploy to Testnet / deploy-testnet (push) Has been cancelled
Multi-Node Stress Testing / stress-test (push) Has been cancelled
Node Failover Simulation / failover-test (push) Has been cancelled
API Endpoint Tests / test-api-endpoints (push) Failing after 18m8s
Integration Tests / test-service-integration (push) Failing after 54s
Production Tests / Production Integration Tests (push) Successful in 21s
Python Tests / test-python (push) Failing after 1m13s
Security Scanning / security-scan (push) Successful in 40s
- Add logging to multi_modal_rl.py and log errors instead of exposing exception details - Log NetworkError exceptions in blockchain.py instead of exposing exception details - Replace str(e) with generic error messages in consensus.py exception handlers - Replace str(e) with generic error messages in users.py exception handlers - Fixes py/stack-trace-exposure security alerts
This commit is contained in:
@@ -32,7 +32,7 @@ async def register_consensus_node(node_data: Dict[str, Any]):
|
||||
return result
|
||||
except Exception as e:
|
||||
logger.error(f"Error registering consensus node: {e}")
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
raise HTTPException(status_code=500, detail="Failed to register consensus node")
|
||||
|
||||
@router.post("/consensus/proposal/create")
|
||||
async def create_consensus_proposal(proposal_data: Dict[str, Any]):
|
||||
@@ -42,7 +42,7 @@ async def create_consensus_proposal(proposal_data: Dict[str, Any]):
|
||||
return result
|
||||
except Exception as e:
|
||||
logger.error(f"Error creating consensus proposal: {e}")
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
raise HTTPException(status_code=500, detail="Failed to create consensus proposal")
|
||||
|
||||
@router.post("/consensus/proposal/{proposal_id}/vote")
|
||||
async def cast_consensus_vote(proposal_id: str, node_id: str, vote: bool):
|
||||
@@ -52,7 +52,7 @@ async def cast_consensus_vote(proposal_id: str, node_id: str, vote: bool):
|
||||
return result
|
||||
except Exception as e:
|
||||
logger.error(f"Error casting consensus vote: {e}")
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
raise HTTPException(status_code=500, detail="Failed to cast consensus vote")
|
||||
|
||||
@router.get("/consensus/proposal/{proposal_id}")
|
||||
async def get_proposal_status(proposal_id: str):
|
||||
@@ -62,7 +62,7 @@ async def get_proposal_status(proposal_id: str):
|
||||
return result
|
||||
except Exception as e:
|
||||
logger.error(f"Error getting proposal status: {e}")
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
raise HTTPException(status_code=500, detail="Failed to get proposal status")
|
||||
|
||||
@router.put("/consensus/algorithm")
|
||||
async def set_consensus_algorithm(algorithm: str = Query(..., description="Consensus algorithm")):
|
||||
@@ -72,7 +72,7 @@ async def set_consensus_algorithm(algorithm: str = Query(..., description="Conse
|
||||
return result
|
||||
except Exception as e:
|
||||
logger.error(f"Error setting consensus algorithm: {e}")
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
raise HTTPException(status_code=500, detail="Failed to set consensus algorithm")
|
||||
|
||||
@router.get("/consensus/statistics")
|
||||
async def get_consensus_statistics():
|
||||
@@ -82,7 +82,7 @@ async def get_consensus_statistics():
|
||||
return result
|
||||
except Exception as e:
|
||||
logger.error(f"Error getting consensus statistics: {e}")
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
raise HTTPException(status_code=500, detail="Failed to get consensus statistics")
|
||||
|
||||
@router.put("/consensus/node/{node_id}/status")
|
||||
async def update_node_status(node_id: str, is_active: bool):
|
||||
@@ -92,7 +92,7 @@ async def update_node_status(node_id: str, is_active: bool):
|
||||
return result
|
||||
except Exception as e:
|
||||
logger.error(f"Error updating node status: {e}")
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
raise HTTPException(status_code=500, detail="Failed to update node status")
|
||||
|
||||
# Advanced features status endpoint
|
||||
@router.get("/advanced-features/status")
|
||||
@@ -130,4 +130,4 @@ async def get_advanced_features_status():
|
||||
}
|
||||
except Exception as e:
|
||||
logger.error(f"Error getting advanced features status: {e}")
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
raise HTTPException(status_code=500, detail="Failed to get advanced features status")
|
||||
|
||||
@@ -190,7 +190,7 @@ async def get_role_permissions(
|
||||
raise
|
||||
except Exception as e:
|
||||
logger.error(f"Error getting role permissions: {e}")
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
raise HTTPException(status_code=500, detail="Failed to get role permissions")
|
||||
|
||||
@router.get("/auth/stats")
|
||||
async def get_permission_stats(current_user: Dict[str, Any] = Depends(get_current_user)):
|
||||
@@ -208,7 +208,7 @@ async def get_permission_stats(current_user: Dict[str, Any] = Depends(get_curren
|
||||
raise
|
||||
except Exception as e:
|
||||
logger.error(f"Error getting permission stats: {e}")
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
raise HTTPException(status_code=500, detail="Failed to get permission stats")
|
||||
|
||||
# Protected endpoint example
|
||||
@router.get("/protected/admin")
|
||||
|
||||
@@ -58,7 +58,8 @@ async def blockchain_sync_status() -> dict[str, Any]:
|
||||
else:
|
||||
return {"status": "synced", "block": response.get("current_block", 0)}
|
||||
except NetworkError as e:
|
||||
return {"status": "error", "error": f"RPC connection failed: {e}"}
|
||||
logger.error(f"RPC connection failed: {e}")
|
||||
return {"status": "error", "error": "RPC connection failed"}
|
||||
except Exception as e:
|
||||
return {"status": "error", "error": "Failed to get sync status"}
|
||||
|
||||
@@ -73,7 +74,8 @@ async def get_block(height: int) -> dict[str, Any]:
|
||||
response = client.get(f"{rpc_url}/rpc/blocks/{height}")
|
||||
return response
|
||||
except NetworkError as e:
|
||||
return {"status": "error", "error": f"RPC connection failed: {e}"}
|
||||
logger.error(f"RPC connection failed: {e}")
|
||||
return {"status": "error", "error": "RPC connection failed"}
|
||||
|
||||
|
||||
@router.get("/blocks/hash/{block_hash}")
|
||||
@@ -87,7 +89,8 @@ async def get_block_by_hash(block_hash: str) -> dict[str, Any]:
|
||||
response = client.get(f"{rpc_url}/rpc/blocks/hash/{block_hash}")
|
||||
return response
|
||||
except NetworkError as e:
|
||||
return {"status": "error", "error": f"RPC connection failed: {e}"}
|
||||
logger.error(f"RPC connection failed: {e}")
|
||||
return {"status": "error", "error": "RPC connection failed"}
|
||||
|
||||
|
||||
@router.get("/transactions/{tx_hash}")
|
||||
@@ -101,7 +104,8 @@ async def get_transaction(tx_hash: str) -> dict[str, Any]:
|
||||
response = client.get(f"{rpc_url}/rpc/transactions/{tx_hash}")
|
||||
return response
|
||||
except NetworkError as e:
|
||||
return {"status": "error", "error": f"RPC connection failed: {e}"}
|
||||
logger.error(f"RPC connection failed: {e}")
|
||||
return {"status": "error", "error": "RPC connection failed"}
|
||||
|
||||
|
||||
@router.get("/accounts/{address}")
|
||||
@@ -115,7 +119,8 @@ async def get_account(address: str) -> dict[str, Any]:
|
||||
response = client.get(f"{rpc_url}/rpc/accounts/{address}")
|
||||
return response
|
||||
except NetworkError as e:
|
||||
return {"status": "error", "error": f"RPC connection failed: {e}"}
|
||||
logger.error(f"RPC connection failed: {e}")
|
||||
return {"status": "error", "error": "RPC connection failed"}
|
||||
|
||||
|
||||
@router.get("/validators")
|
||||
@@ -134,7 +139,8 @@ async def get_validators() -> dict[str, Any]:
|
||||
"total": 1
|
||||
}
|
||||
except NetworkError as e:
|
||||
return {"status": "error", "error": f"RPC connection failed: {e}"}
|
||||
logger.error(f"RPC connection failed: {e}")
|
||||
return {"status": "error", "error": "RPC connection failed"}
|
||||
|
||||
|
||||
@router.get("/supply")
|
||||
@@ -155,7 +161,8 @@ async def get_supply() -> dict[str, Any]:
|
||||
"unit": "AIT"
|
||||
}
|
||||
except NetworkError as e:
|
||||
return {"status": "error", "error": f"RPC connection failed: {e}"}
|
||||
logger.error(f"RPC connection failed: {e}")
|
||||
return {"status": "error", "error": "RPC connection failed"}
|
||||
|
||||
|
||||
@router.get("/state/dump")
|
||||
@@ -173,4 +180,5 @@ async def get_state_dump() -> dict[str, Any]:
|
||||
"timestamp": response.get("timestamp", "")
|
||||
}
|
||||
except NetworkError as e:
|
||||
return {"status": "error", "error": f"RPC connection failed: {e}"}
|
||||
logger.error(f"RPC connection failed: {e}")
|
||||
return {"status": "error", "error": "RPC connection failed"}
|
||||
|
||||
@@ -3,6 +3,7 @@ Multi-modal RL Router
|
||||
Handles multi-modal reinforcement learning endpoints by proxying to AI service
|
||||
"""
|
||||
|
||||
import logging
|
||||
from typing import Any
|
||||
|
||||
from fastapi import APIRouter
|
||||
@@ -10,6 +11,8 @@ from pydantic import BaseModel
|
||||
|
||||
from aitbc import AITBCHTTPClient, NetworkError
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
router = APIRouter(prefix="/multi-modal-rl", tags=["multi-modal-rl"])
|
||||
|
||||
|
||||
@@ -45,9 +48,11 @@ async def submit_job(req: JobCreate, client_id: str = "default_client") -> dict[
|
||||
response = client.post(f"{ai_url}/jobs", json=job_data)
|
||||
return response
|
||||
except NetworkError as e:
|
||||
return {"error": f"AI service connection failed: {e}"}
|
||||
logger.error(f"AI service connection failed: {e}")
|
||||
return {"error": "AI service connection failed"}
|
||||
except Exception as e:
|
||||
return {"error": f"Failed to submit job: {e}"}
|
||||
logger.error(f"Failed to submit job: {e}")
|
||||
return {"error": "Failed to submit job"}
|
||||
|
||||
|
||||
@router.get("/jobs/{job_id}")
|
||||
@@ -59,9 +64,11 @@ async def get_job(job_id: str, client_id: str = "default_client") -> dict[str, A
|
||||
response = client.get(f"{ai_url}/jobs/{job_id}", params={"client_id": client_id})
|
||||
return response
|
||||
except NetworkError as e:
|
||||
return {"error": f"AI service connection failed: {e}"}
|
||||
logger.error(f"AI service connection failed: {e}")
|
||||
return {"error": "AI service connection failed"}
|
||||
except Exception as e:
|
||||
return {"error": f"Failed to get job: {e}"}
|
||||
logger.error(f"Failed to get job: {e}")
|
||||
return {"error": "Failed to get job"}
|
||||
|
||||
|
||||
@router.get("/jobs/{job_id}/result")
|
||||
@@ -73,9 +80,11 @@ async def get_job_result(job_id: str, client_id: str = "default_client") -> dict
|
||||
response = client.get(f"{ai_url}/jobs/{job_id}/result", params={"client_id": client_id})
|
||||
return response
|
||||
except NetworkError as e:
|
||||
return {"error": f"AI service connection failed: {e}"}
|
||||
logger.error(f"AI service connection failed: {e}")
|
||||
return {"error": "AI service connection failed"}
|
||||
except Exception as e:
|
||||
return {"error": f"Failed to get job result: {e}"}
|
||||
logger.error(f"Failed to get job result: {e}")
|
||||
return {"error": "Failed to get job result"}
|
||||
|
||||
|
||||
@router.post("/jobs/{job_id}/cancel")
|
||||
@@ -87,9 +96,11 @@ async def cancel_job(job_id: str, client_id: str = "default_client") -> dict[str
|
||||
response = client.post(f"{ai_url}/jobs/{job_id}/cancel", params={"client_id": client_id})
|
||||
return response
|
||||
except NetworkError as e:
|
||||
return {"error": f"AI service connection failed: {e}"}
|
||||
logger.error(f"AI service connection failed: {e}")
|
||||
return {"error": "AI service connection failed"}
|
||||
except Exception as e:
|
||||
return {"error": f"Failed to cancel job: {e}"}
|
||||
logger.error(f"Failed to cancel job: {e}")
|
||||
return {"error": "Failed to cancel job"}
|
||||
|
||||
|
||||
@router.get("/jobs")
|
||||
@@ -104,9 +115,11 @@ async def list_jobs(client_id: str = "default_client", limit: int = 10, state: s
|
||||
response = client.get(f"{ai_url}/jobs", params=params)
|
||||
return response
|
||||
except NetworkError as e:
|
||||
return {"error": f"AI service connection failed: {e}"}
|
||||
logger.error(f"AI service connection failed: {e}")
|
||||
return {"error": "AI service connection failed"}
|
||||
except Exception as e:
|
||||
return {"error": f"Failed to list jobs: {e}"}
|
||||
logger.error(f"Failed to list jobs: {e}")
|
||||
return {"error": "Failed to list jobs"}
|
||||
|
||||
|
||||
@router.get("/health")
|
||||
@@ -128,7 +141,8 @@ async def health() -> dict[str, Any]:
|
||||
"ai_service": "unreachable",
|
||||
"note": "AI service not available on this node"
|
||||
}
|
||||
except Exception:
|
||||
except Exception as e:
|
||||
logger.error(f"AI service check failed: {e}")
|
||||
return {
|
||||
"status": "degraded",
|
||||
"router": "multi-modal-rl",
|
||||
|
||||
Reference in New Issue
Block a user