Conversation
…ols-view tab persistence
- Add post-exec debug sleep trap to Gemini agent (parity with Codex) - Remove hardcoded HOME=/root from Gemini (container.py handles it) - New OpenCode agent: opencode run --non-interactive, JSON MCP config, provider-agnostic - Register OpenCode in factory and __init__ - Add unit tests: 19 Codex, 17 Gemini, 26 OpenCode, 12 factory (84 total)
6ed4963 to
b98af97
Compare
- Use exact-line match for FLOW_SUCCESS_SENTINEL to prevent false positives when agent greps/cats source files containing the sentinel string (flow_orchestrator.py, container.py) - Bypass server-side justification enforcement during async re-execution of approved tools (_bypass_approval_var) to avoid rejecting replays that lack justification in tool_args - Gate getUsers()/getTeams() in approval-policy-dialog behind _hasAdvancedApprovals() to avoid 404s in OSS single-user mode
- Add PolicyGenerationService using litellm for provider-agnostic LLM calls - Add POST /api/v1/policies/generate endpoint (prompt-based) - Add POST /api/v1/policies/generate-from-audit endpoint (audit-log-based) - Add 'preloop policy generate' CLI command with --from-audit-logs, --file, --output flags - Add 'preloop agents discover' CLI command scanning 8 AI agent configs - Add policy-generate-dialog.ts frontend component - Add generatePolicy/generatePolicyFromAudit API functions - Add litellm>=1.50.0 dependency - LLM prompts reuse existing MCP servers, approval policies, and tool rules
…low execution - Add _get_project_id() helper to GitLabTracker (fixes AttributeError in create_commit_status, add/remove_mr_award_emoji) - Fix discussion.notes access in create_mr_discussion for python-gitlab v4+ (notes is a manager, not a list) - Use mr.changes.get instead of mr.changes for MR diff fetching (manager not callable in v4+) - Add trigger_project_id (singular) to execution context so container.py git clone fallback works
…ault, DB lock, changelog - Sentinel: add PRELOOP_AGENT_EXEC_START marker to suppress detection during prompt echo; restructure instruction so sentinel is not on its own line; add detailed [Sentinel] logging for diagnostics - OpenCode: limit envsubst to $PRELOOP_MCP_URL and $PRELOOP_API_TOKEN to prevent $schema corruption; use raw prompt in single-quoted heredoc - Agents: default AGENT_POST_EXEC_SLEEP to 0 (codex, gemini, opencode) - Approvals: claim-then-execute pattern in get_approval_status to release FOR UPDATE lock before tool execution - Changelog: fix tool name check_approval_status -> get_approval_status - Tests: fix test_dynamic_fastmcp hanging (missing super()._list_tools mock)
…ing, desktop notifs, loading state - ApprovalEvent: use naive datetime.utcnow for TIMESTAMP WITHOUT TIME ZONE column - Proxied-tool wrapper: read justification from _justification_var instead of already-stripped arguments - Policy generation endpoints: wrap sync LLM calls in asyncio.to_thread - Desktop notifications: always emit for flow executions and approvals (remove isDesktopNotificationsEnabled gate) - flow-view: wrap reference data loading in try/finally to prevent stuck loading - Add 38 tests for PolicyGenerationService and generation endpoints
- Gemini agent: emit PRELOOP_AGENT_EXEC_START before CLI command so orchestrator sentinel detection works correctly - OpenCode agent: same fix — emit PRELOOP_AGENT_EXEC_START before CLI command - invitation-management-view: set isLoading=false when feature disabled (prevents infinite spinner), gate render() on featureEnabled - team-management-view: gate render() on featureEnabled - user-management-view: gate render() on featureEnabled
| "poll_interval_seconds": poll_interval, | ||
| "timeout_seconds": policy.timeout_seconds or 300, | ||
| "channels": notification_channels, | ||
| "approval_url": approval_url, |
There was a problem hiding this comment.
[HIGH Security]
Affected files:
backend/preloop/services/approval_helper.py:343
Returning approval_url (which includes the approval token) to the calling agent in the async response leaks the bearer token back to the requester. That allows the agent to self-approve (or share the link), which defeats the approval boundary.
Recommendation:
Do not include the approval URL/token in tool responses. Return only request_id and metadata, and deliver the approval link exclusively via trusted notification channels or a server-side UI for authenticated approvers.
|
|
||
| # Create prompt file to avoid shell escaping issues. | ||
| # The single-quoted heredoc delimiter preserves content literally. | ||
| cat > /tmp/prompt.txt << 'PROMPT_EOF' |
There was a problem hiding this comment.
[HIGH Security]
Affected files:
backend/preloop/agents/opencode.py:386
The prompt is written via a fixed heredoc delimiter. If the prompt contains a line PROMPT_EOF, the heredoc terminates early and the remaining prompt lines are interpreted as shell code, allowing command injection before OpenCode runs. Prompts can originate from external events.
Recommendation:
Use a randomized delimiter (e.g., UUID), or write the prompt via a safe mechanism (base64 decode, or a Python heredoc) so delimiter injection is impossible.
🔍 Preloop Code ReviewLast Updated: 2026-02-18 02:33:44 UTC 📝 SummaryThis PR adds async approvals, per-tool justification enforcement, and OpenCode agent support. The direction is solid, but two high-severity security issues need to be addressed before merge. ✅ What Looks Good
|
Note
High Risk
Two high-severity security issues were found (approval token exposure and prompt delimiter injection) that should be fixed before merge.
Overview
Adds async approval mode with polling, server-side justification enforcement, and OpenCode agent support, plus related docs and tests.
Also updates agent scripts and log sentinel handling for more reliable execution checks.
Written by Preloop PR Reviewer for commit 5ae66b2. Updates automatically on new commits.