nvidia-nat-security 1.6.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
nat/meta/pypi.md ADDED
@@ -0,0 +1,24 @@
1
+ <!--
2
+ SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3
+ SPDX-License-Identifier: Apache-2.0
4
+
5
+ Licensed under the Apache License, Version 2.0 (the "License");
6
+ you may not use this file except in compliance with the License.
7
+ You may obtain a copy of the License at
8
+
9
+ http://www.apache.org/licenses/LICENSE-2.0
10
+
11
+ Unless required by applicable law or agreed to in writing, software
12
+ distributed under the License is distributed on an "AS IS" BASIS,
13
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ See the License for the specific language governing permissions and
15
+ limitations under the License.
16
+ -->
17
+
18
+ ![NVIDIA NeMo Agent Toolkit](https://media.githubusercontent.com/media/NVIDIA/NeMo-Agent-Toolkit/refs/heads/main/docs/source/_static/banner.png "NeMo Agent Toolkit banner image")
19
+
20
+ # NVIDIA NeMo Agent Toolkit Security Subpackage
21
+
22
+ Subpackage for security and red-team interfaces in NeMo Agent Toolkit.
23
+
24
+ For more information about the NVIDIA NeMo Agent Toolkit, please visit the [NeMo Agent Toolkit GitHub Repo](https://github.com/NVIDIA/NeMo-Agent-Toolkit).
@@ -0,0 +1,14 @@
1
+ # SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2
+ # SPDX-License-Identifier: Apache-2.0
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
@@ -0,0 +1,14 @@
1
+ # SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2
+ # SPDX-License-Identifier: Apache-2.0
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
@@ -0,0 +1,19 @@
1
+ # SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2
+ # SPDX-License-Identifier: Apache-2.0
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ """Security CLI command exports."""
16
+
17
+ from nat.plugins.security.cli.red_teaming.red_teaming import red_team_command
18
+
19
+ __all__ = ["red_team_command"]
@@ -0,0 +1,14 @@
1
+ # SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2
+ # SPDX-License-Identifier: Apache-2.0
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
@@ -0,0 +1,138 @@
1
+ # SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2
+ # SPDX-License-Identifier: Apache-2.0
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ """Red teaming CLI command."""
16
+
17
+ from __future__ import annotations
18
+
19
+ import asyncio
20
+ import logging
21
+ from pathlib import Path
22
+
23
+ import click
24
+
25
+ logger = logging.getLogger(__name__)
26
+
27
+
28
+ @click.group(name=__name__, invoke_without_command=True, help="Run red teaming evaluation with multiple scenarios.")
29
+ @click.option(
30
+ "--red_team_config",
31
+ type=click.Path(exists=True, file_okay=True, dir_okay=False, path_type=Path),
32
+ required=False,
33
+ help="A YAML/JSON file containing red teaming configuration (evaluator, scenarios, etc.).",
34
+ )
35
+ @click.option(
36
+ "--config_file",
37
+ type=click.Path(exists=True, file_okay=True, dir_okay=False, path_type=Path),
38
+ required=False,
39
+ help="A JSON/YAML file that sets the parameters for the base workflow. "
40
+ "Overrides base_workflow in red_team_config if both are provided.",
41
+ )
42
+ @click.option(
43
+ "--dataset",
44
+ type=click.Path(exists=True, file_okay=True, dir_okay=False, path_type=Path),
45
+ required=False,
46
+ help="A JSON file with questions and ground truth answers. "
47
+ "Overrides the dataset path in the config file.",
48
+ )
49
+ @click.option(
50
+ "--result_json_path",
51
+ type=str,
52
+ default="$",
53
+ help="A JSON path to extract the result from the workflow. "
54
+ "For example, '$.output' extracts the 'output' field.",
55
+ )
56
+ @click.option(
57
+ "--endpoint",
58
+ type=str,
59
+ default=None,
60
+ help="Use endpoint for running the workflow. Example: http://localhost:8000/generate",
61
+ )
62
+ @click.option(
63
+ "--endpoint_timeout",
64
+ type=int,
65
+ default=300,
66
+ help="HTTP response timeout in seconds. Only relevant if endpoint is specified.",
67
+ )
68
+ @click.option(
69
+ "--reps",
70
+ type=int,
71
+ default=1,
72
+ help="Number of repetitions for the evaluation.",
73
+ )
74
+ @click.option(
75
+ "--override",
76
+ type=(str, str),
77
+ multiple=True,
78
+ help="Override config values for the base workflow config using dot notation "
79
+ "(e.g., --override llms.nim_llm.temperature 0.7)",
80
+ )
81
+ @click.pass_context
82
+ def red_team_command(ctx, **kwargs) -> None:
83
+ """Run red teaming evaluation with multiple scenarios."""
84
+ pass
85
+
86
+
87
+ @red_team_command.result_callback(replace=True)
88
+ def process_red_team_eval(
89
+ processors,
90
+ *,
91
+ red_team_config: Path | None,
92
+ config_file: Path | None,
93
+ dataset: Path | None,
94
+ result_json_path: str,
95
+ endpoint: str | None,
96
+ endpoint_timeout: int,
97
+ reps: int,
98
+ override: tuple[tuple[str, str], ...],
99
+ ):
100
+ """Process the red team eval command and execute the evaluation."""
101
+ from nat.plugins.security.eval.runners.red_teaming_runner import RedTeamingRunner
102
+ from nat.runtime.loader import load_config
103
+
104
+ from .red_teaming_utils import load_red_teaming_config
105
+
106
+ # Must have at least one of these
107
+ if red_team_config is None and config_file is None:
108
+ raise click.ClickException("Either --red_team_config or --config_file must be provided.")
109
+
110
+ # Load configs
111
+ rt_config = None
112
+ if red_team_config is not None:
113
+ rt_config = load_red_teaming_config(red_team_config)
114
+ base_workflow_path = config_file or rt_config.base_workflow
115
+ if base_workflow_path is None:
116
+ raise click.ClickException(
117
+ "No base workflow specified. Set 'base_workflow' in red_team_config or provide --config_file.")
118
+ base_workflow_config = load_config(base_workflow_path)
119
+ else:
120
+ assert config_file is not None
121
+ base_workflow_config = load_config(config_file)
122
+
123
+ # Create and run the runner
124
+ runner = RedTeamingRunner(
125
+ config=rt_config,
126
+ base_workflow_config=base_workflow_config,
127
+ dataset_path=str(dataset) if dataset else None,
128
+ result_json_path=result_json_path,
129
+ endpoint=endpoint,
130
+ endpoint_timeout=endpoint_timeout,
131
+ reps=reps,
132
+ overrides=override,
133
+ )
134
+
135
+ try:
136
+ _ = asyncio.run(runner.run())
137
+ except ValueError as e:
138
+ raise click.ClickException(str(e)) from e
@@ -0,0 +1,73 @@
1
+ # SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2
+ # SPDX-License-Identifier: Apache-2.0
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ """Utility functions for red team evaluation CLI."""
16
+
17
+ from __future__ import annotations
18
+
19
+ import json
20
+ import logging
21
+ from pathlib import Path
22
+
23
+ import yaml
24
+
25
+ from nat.plugins.security.eval.runners.red_teaming_runner import RedTeamingRunnerConfig
26
+
27
+ logger = logging.getLogger(__name__)
28
+
29
+
30
+ def load_red_teaming_config(config_file: Path) -> RedTeamingRunnerConfig:
31
+ """Load a RedTeamingRunnerConfig from a YAML or JSON file.
32
+
33
+ Args:
34
+ config_file: Path to the configuration file (YAML or JSON)
35
+
36
+ Returns:
37
+ Parsed RedTeamingRunnerConfig object
38
+
39
+ Raises:
40
+ ValueError: If the file format is invalid or parsing fails
41
+ FileNotFoundError: If the file doesn't exist
42
+ """
43
+ # Ensure plugins are discovered and registered before parsing the config.
44
+ # This triggers rebuild_annotations() which allows Pydantic to resolve
45
+ # discriminated unions (e.g., _type: nim -> NIMConfig).
46
+ from nat.runtime.loader import PluginTypes
47
+ from nat.runtime.loader import discover_and_register_plugins
48
+ discover_and_register_plugins(PluginTypes.CONFIG_OBJECT)
49
+
50
+ logger.info("Loading red teaming config from: %s", config_file)
51
+
52
+ if not config_file.exists():
53
+ raise FileNotFoundError(f"Red teaming config file not found: {config_file}")
54
+
55
+ with open(config_file, encoding='utf-8') as f:
56
+ if config_file.suffix in ('.yml', '.yaml'):
57
+ config_data = yaml.safe_load(f)
58
+ elif config_file.suffix == '.json':
59
+ config_data = json.load(f)
60
+ else:
61
+ raise ValueError(f"Unsupported file format: {config_file.suffix}. "
62
+ "Use .yml, .yaml, or .json")
63
+
64
+ if not isinstance(config_data, dict):
65
+ raise ValueError(f"Red teaming config file must contain a dictionary, got {type(config_data)}")
66
+
67
+ try:
68
+ config = RedTeamingRunnerConfig(**config_data)
69
+ except Exception as e:
70
+ raise ValueError(f"Failed to parse red teaming config: {e}") from e
71
+
72
+ logger.info("Loaded red teaming config with %d scenarios", len(config.scenarios))
73
+ return config
@@ -0,0 +1,14 @@
1
+ # SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2
+ # SPDX-License-Identifier: Apache-2.0
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
@@ -0,0 +1,14 @@
1
+ # SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2
+ # SPDX-License-Identifier: Apache-2.0
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
@@ -0,0 +1,66 @@
1
+ # SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2
+ # SPDX-License-Identifier: Apache-2.0
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ """Data models for red teaming evaluation output."""
16
+
17
+ from __future__ import annotations
18
+
19
+ from pydantic import Field
20
+
21
+ from nat.data_models.intermediate_step import IntermediateStep
22
+ from nat.plugins.eval.data_models.evaluator_io import EvalOutputItem
23
+
24
+
25
+ class ConditionEvalOutputItem(EvalOutputItem):
26
+ """Evaluation results for a single IntermediateStep that meets the filtering condition.
27
+
28
+ Attributes:
29
+ id: Identifier from the input item.
30
+ score: Average score across all filter conditions.
31
+ reasoning: Reasoning for given score.
32
+ intermediate_step: IntermediateStep selected and evaluated via reduction strategy.
33
+ error_message: Error message if any step of the evaluation has failed.
34
+ """
35
+
36
+ intermediate_step: IntermediateStep | None = Field(
37
+ default=None,
38
+ description="The single IntermediateStep that was selected and evaluated (based on reduction strategy)")
39
+ error_message: str | None = Field(default=None,
40
+ description="Error message if any step of the evaluation has failed")
41
+
42
+ @classmethod
43
+ def empty(cls, id: str, error: str | None = None) -> ConditionEvalOutputItem:
44
+ """Create an empty ConditionEvalOutputItem.
45
+
46
+ Returns:
47
+ Empty ConditionEvalOutputItem instance
48
+ """
49
+ return cls(id=id, score=0.0, reasoning={}, error_message=error, intermediate_step=None)
50
+
51
+
52
+ class RedTeamingEvalOutputItem(EvalOutputItem):
53
+ """Extended evaluation output item for red teaming evaluations.
54
+
55
+ Organizes results by filter condition name, with each condition containing
56
+ its score, the evaluated output, and the single intermediate step that was selected.
57
+
58
+ Attributes:
59
+ id: Identifier from the input item
60
+ score: Average score across all filter conditions
61
+ reasoning: Summary information for compatibility
62
+ results_by_condition: Map from condition name to evaluation results
63
+ """
64
+
65
+ results_by_condition: dict[str, ConditionEvalOutputItem] = Field(
66
+ description="Results organized by filter condition name")