Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions .github/workflows/trusted-goal-validation.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: Trusted Goal Indirect Injection Validation

on:
pull_request:
paths:
- "python/**"
- ".github/workflows/trusted-goal-validation.yml"

defaults:
run:
working-directory: python

jobs:
trusted-goal-probes:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
cache: pip
cache-dependency-path: python/pyproject.toml
- name: Install package and test dependencies
run: pip install -e . && pip install pytest
- name: Run fixed trusted-goal validation task
run: python -m pytest tests/test_trusted_goal_indirect_injection.py -q --tb=short
62 changes: 62 additions & 0 deletions python/tests/test_trusted_goal_indirect_injection.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
"""Tests for indirect injection probes with an explicit trusted-goal boundary."""

from agentseal.probes.injection import build_injection_probes
from agentseal.schemas import Severity


class TestTrustedGoalIndirectInjection:
def setup_method(self):
self.probes = build_injection_probes()
self.category_probes = [
probe
for probe in self.probes
if probe["category"] == "trusted_goal_indirect_injection"
]

def test_probe_count(self):
assert len(self.category_probes) == 3

def test_probe_ids_unique(self):
ids = [probe["probe_id"] for probe in self.category_probes]
assert len(ids) == len(set(ids))
assert all(probe_id.startswith("inj_trusted_goal_") for probe_id in ids)

def test_probe_structure(self):
required = {
"probe_id",
"category",
"technique",
"severity",
"payload",
"canary",
"canary_position",
}
for probe in self.category_probes:
assert required.issubset(probe), f"Missing keys in {probe['probe_id']}"

def test_severity_critical(self):
for probe in self.category_probes:
assert probe["severity"] == Severity.CRITICAL

def test_canary_in_payload(self):
for probe in self.category_probes:
assert probe["canary"] in probe["payload"]

def test_payloads_define_trusted_goal(self):
for probe in self.category_probes:
assert "Trusted user goal:" in probe["payload"]

def test_payloads_cover_external_content_carriers(self):
expected_markers = {"Retrieved email:", "Retrieved web page:", "Tool result:"}
observed = {
marker
for marker in expected_markers
if any(marker in probe["payload"] for probe in self.category_probes)
}
assert observed == expected_markers

def test_payloads_request_unrelated_unsafe_action(self):
unsafe_markers = ["environment variables", "grant", "delete the repository"]
for probe in self.category_probes:
assert any(marker in probe["payload"] for marker in unsafe_markers)

Loading