-
-
Notifications
You must be signed in to change notification settings - Fork 526
feat(scan): add PostHog telemetry for scan entry points #2600
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
kevinmessiaen
wants to merge
24
commits into
main
Choose a base branch
from
cursor/scan-posthog-telemetry-91d2
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from 23 commits
Commits
Show all changes
24 commits
Select commit
Hold shift + click to select a range
d2b6469
feat(garak): integrate garak scan
kevinmessiaen 7f50ee2
refactor(scan): extract garak async bridge into _bridge.py
kevinmessiaen 17050fe
feat(scan): add GiskardJudgeGenerator bridging garak judges to Giskard
kevinmessiaen 86dc9ea
feat(scan): wire Giskard generator into garak judges, skip keyless de…
kevinmessiaen b92daa5
feat(scan): emit skip results for keyless garak detectors
kevinmessiaen 2ad6b5f
fix(scan): set base generator attrs so garak judges can call GiskardJ…
kevinmessiaen 912d9f4
fix(scan): import BaseGenerator from package root; document key handling
kevinmessiaen d0bbe43
Merge branch 'main' into feat/garak-scan-integration
kevinmessiaen 9a50551
feat(scan): record garak scan duration on SuiteResult
cursoragent 59469d9
style(scan): apply ruff format to garak adapter
cursoragent 866aea1
fix(scan): address Gemini review on garak integration
cursoragent a688dfb
fix(scan): keep garak optional for CI checks and add garak-test group…
kevinmessiaen 0cd6212
Merge branch 'main' into feat/garak-scan-integration
kevinmessiaen 3a7366d
chore: update THIRD_PARTY_NOTICES.md
kevinmessiaen 362bf0a
fix(scan): copy garak probe tags onto scenario results (#2584)
kevinmessiaen ca247d3
fix(scan): name garak check results after probe detector plugins (#2585)
kevinmessiaen 3479aa1
feat(lidar): integrate lidar scan into third_party_scan (#2588)
kevinmessiaen 6561af2
Merge branch 'main' into feat/garak-scan-integration
kevinmessiaen bc94ea6
optimize probe execution in GarakScanAdapter
henchaves 81ef53b
test(scan): cover garak probe thread-pool deadlock; use context-manag…
kevinmessiaen 4a370b4
Merge branch 'main' into feat/garak-scan-integration
kevinmessiaen 52acf2c
Update libs/giskard-scan/src/giskard/scan/integrations/garak/_adapter.py
kevinmessiaen ff7025c
feat(scan): add PostHog telemetry for scan entry points
cursoragent a4cf777
refactor(scan): unify telemetry shape and relax anonymisation
cursoragent File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,55 @@ | ||
| # giskard-scan | ||
|
|
||
| Agent vulnerability scanner — red teaming, prompt injection, adversarial scenario generation. | ||
|
|
||
| ## Third-party scanners (experimental) | ||
|
|
||
| `third_party_scan` runs an external security scanner against a Giskard target and | ||
| returns a `SuiteResult`. Only [garak](https://github.com/NVIDIA/garak) is supported | ||
| today, and it ships as an optional extra: | ||
|
|
||
| ```bash | ||
| pip install giskard-scan[garak] | ||
| ``` | ||
|
|
||
| ```python | ||
| import asyncio | ||
|
|
||
| from giskard.scan import third_party_scan | ||
|
|
||
|
|
||
| def target(inputs: str) -> str: | ||
| # Your agent / model call. Structured (BaseModel) inputs also work. | ||
| return call_my_agent(inputs) | ||
|
|
||
|
|
||
| result = asyncio.run( | ||
| third_party_scan( | ||
| target, | ||
| tool="garak", | ||
| description="A helpful assistant", # required; lidar builds its target profile from this, garak ignores it | ||
| probes=["probes.goodside.ThreatenJSON"], # omit to run all active probes | ||
| target_mode="multiturn", # "singleturn" skips garak's iterative probes | ||
| ) | ||
| ) | ||
|
|
||
| print(result) | ||
| ``` | ||
|
|
||
| Probes run in parallel; the target is invoked concurrently, so it must be safe to | ||
| call from multiple threads (per-conversation state is tracked in the `Trace`, not on | ||
| the target). | ||
|
|
||
| ### API keys and LLM-judge detectors | ||
|
|
||
| Some garak detectors need an LLM or a third-party API to score a probe: | ||
|
|
||
| - **LLM-judge detectors** (garak's `judge.*`, e.g. refusal detection) normally require | ||
| their own OpenAI key. Instead, they are automatically backed by Giskard's default | ||
| generator (`giskard.checks.get_default_generator()`), so they run with the same | ||
| credentials as the rest of Giskard — no separate OpenAI key needed. | ||
| - **Detectors that need a third-party API key** you have not set (for example | ||
| `perspective.*`, which needs `PERSPECTIVE_API_KEY`) are **skipped** rather than | ||
| silently dropping the whole probe. Each skipped detector surfaces as a skip result | ||
| (`CheckResult.skip`) in the returned `SuiteResult`, with the missing key named in the | ||
| message, so the rest of the probe's detectors still run. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| """Aggregate, non-identifying properties for PostHog (no names, messages, or content).""" | ||
|
|
||
| from __future__ import annotations | ||
|
|
||
| from collections import Counter | ||
| from typing import Any | ||
|
|
||
| from .generators.base import ScenarioGenerator, TargetMode | ||
|
|
||
|
|
||
| def generator_type_counts(generators: list[ScenarioGenerator]) -> dict[str, int]: | ||
| return dict(Counter(type(generator).__name__ for generator in generators)) | ||
|
|
||
|
|
||
| def suite_scan_shape_properties( | ||
| *, | ||
| scan_kind: str, | ||
| language_count: int, | ||
| target_mode: TargetMode, | ||
| generator_count: int, | ||
| scenario_count: int, | ||
| generator_types: dict[str, int], | ||
| parallel: bool, | ||
| max_concurrency: int | None, | ||
| **extra: Any, | ||
| ) -> dict[str, Any]: | ||
| return { | ||
| "integration": "giskard-scan", | ||
| "scan_kind": scan_kind, | ||
| "language_count": language_count, | ||
| "target_mode": target_mode, | ||
| "generator_count": generator_count, | ||
| "scenario_count": scenario_count, | ||
| "generator_types": generator_types, | ||
| "parallel": parallel, | ||
| "max_concurrency": max_concurrency, | ||
| **extra, | ||
| } | ||
|
|
||
|
|
||
| def third_party_scan_shape_properties( | ||
| *, | ||
| tool: str, | ||
| language_count: int | None, | ||
| target_mode: TargetMode, | ||
| has_probe_filter: bool, | ||
| has_tag_filter: bool, | ||
| ) -> dict[str, Any]: | ||
| return { | ||
| "integration": "giskard-scan", | ||
| "scan_kind": f"third_party_{tool}", | ||
| "tool": tool, | ||
| "language_count": language_count, | ||
| "target_mode": target_mode, | ||
| "has_probe_filter": has_probe_filter, | ||
| "has_tag_filter": has_tag_filter, | ||
| } | ||
18 changes: 18 additions & 0 deletions
18
libs/giskard-scan/src/giskard/scan/integrations/__init__.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| """Third-party scanner integrations for giskard.scan (experimental).""" | ||
|
|
||
| from typing import Any, Protocol | ||
|
|
||
| from giskard.checks import SuiteResult, Target, Trace | ||
|
|
||
| from ._entry_point import third_party_scan | ||
|
|
||
|
|
||
| class ScanAdapter(Protocol): | ||
| async def run[InputType, OutputType, TraceType: Trace]( # pyright: ignore[reportMissingTypeArgument] | ||
| self, | ||
| target: Target[InputType, OutputType, TraceType], | ||
| **kwargs: Any, | ||
| ) -> SuiteResult: ... | ||
|
|
||
|
|
||
| __all__ = ["ScanAdapter", "third_party_scan"] |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The
generatorslist returned by the registries can contain both generator classes (e.g.,HallucinationScenarioGenerator) and generator instances (e.g.,GCGInjectionScenarioGenerator()). Callingtype(generator).__name__on a class returns"type"instead of the actual class name, which will corrupt the telemetry data.We should check if the generator is a class (using
isinstance(generator, type)) and usegenerator.__name__in that case, falling back totype(generator).__name__for instances.