diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..cd91926 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,5 @@ +# Dataset files are hashed into each dataset's croissant.json and into release +# checksums, so their bytes must be the same on every platform: always LF. +datasets/**/*.csv text eol=lf +datasets/**/*.json text eol=lf +data_validation/reference_data/*.csv text eol=lf diff --git a/.github/workflows/datasets-release.yml b/.github/workflows/datasets-release.yml new file mode 100644 index 0000000..f2997a2 --- /dev/null +++ b/.github/workflows/datasets-release.yml @@ -0,0 +1,90 @@ +name: datasets-release + +# Cuts a versioned datasets release when a tag datasets-v is pushed +# (the version must equal CITATION.cff's). It re-runs every check, builds one +# zip per dataset plus an all-datasets zip, writes SHA256SUMS, attests build +# provenance for every file with Sigstore (verify with `gh attestation +# verify --repo GenAI-Security-Project/GenAI-Data-Security-Initiative`), +# and publishes a GitHub release. With the repository enabled in Zenodo's +# GitHub integration, Zenodo archives each release and mints a DOI. +on: + push: + tags: + - 'datasets-v*' + +permissions: + contents: write + id-token: write + attestations: write + +jobs: + release: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + + - name: Set up Python + uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 + with: + python-version: '3.11' + + - name: Install requirements + run: python -m pip install --quiet -r data_validation/requirements.txt -r data_validation/requirements-croissant.txt + + - name: Tag matches CITATION.cff + id: version + run: | + tag_version="${GITHUB_REF_NAME#datasets-v}" + cff_version=$(sed -nE 's/^version:[[:space:]]*"?([^"[:space:]]+)"?.*/\1/p' CITATION.cff) + if [ "$tag_version" != "$cff_version" ]; then + echo "::error::tag $GITHUB_REF_NAME does not match CITATION.cff version $cff_version" + exit 1 + fi + echo "version=$tag_version" >> "$GITHUB_OUTPUT" + + - name: Every check passes + run: | + python data_validation/run_all_checks.py + python data_validation/qc_tools/consistency_check.py + python data_validation/croissant/build_croissant.py --check + python data_validation/croissant/check_croissant.py + + - name: Build archives and checksums + env: + VERSION: ${{ steps.version.outputs.version }} + run: | + mkdir dist + for croissant in datasets/*/croissant.json; do + name=$(basename "$(dirname "$croissant")") + git archive --format=zip -o "dist/owasp-dsgai-${name}-${VERSION}.zip" HEAD \ + "datasets/${name}" datasets/_shared CITATION.cff LICENSE + done + git archive --format=zip -o "dist/owasp-dsgai-datasets-${VERSION}.zip" HEAD \ + datasets data_validation/reference_data data_validation/schemas CITATION.cff LICENSE + (cd dist && sha256sum ./*.zip > SHA256SUMS) + cat dist/SHA256SUMS + + - name: Attest build provenance (Sigstore) + uses: actions/attest-build-provenance@4d101475d8b20a2381f78447822ac1eab6504dd8 # v4.2.2 + with: + subject-path: 'dist/*' + + - name: Publish the GitHub release + env: + GH_TOKEN: ${{ github.token }} + VERSION: ${{ steps.version.outputs.version }} + run: | + { + echo "Datasets release ${VERSION} of the OWASP GenAI Data Security Initiative." + echo + echo "Each dataset archive contains the dataset folder (with its MLCommons Croissant 1.1 metadata), the shared DSGAI taxonomy, CITATION.cff and the licence." + echo + echo "Verify a download:" + echo + echo '```' + echo "sha256sum -c SHA256SUMS --ignore-missing" + echo "gh attestation verify --repo ${GITHUB_REPOSITORY}" + echo '```' + } > notes.md + gh release create "$GITHUB_REF_NAME" dist/* --title "Datasets ${VERSION}" --notes-file notes.md diff --git a/.github/workflows/datasets-validate-all.yml b/.github/workflows/datasets-validate-all.yml index fb5bc3f..3359d8d 100644 --- a/.github/workflows/datasets-validate-all.yml +++ b/.github/workflows/datasets-validate-all.yml @@ -128,3 +128,25 @@ jobs: python data_validation/qc_tools/ner_pii_scan.py echo '```' } >> "$GITHUB_STEP_SUMMARY" + + # MLCommons Croissant 1.1 metadata: up to date with the data (checksums, + # fields, dates), valid per mlcroissant, and loadable record by record. + croissant: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + + - name: Set up Python + uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 + with: + python-version: '3.11' + + - name: Install requirements + run: python -m pip install --quiet -r data_validation/requirements-croissant.txt + + - name: croissant.json files are up to date + run: python data_validation/croissant/build_croissant.py --check + + - name: Validate and load every Croissant file + run: python data_validation/croissant/check_croissant.py diff --git a/.zenodo.json b/.zenodo.json new file mode 100644 index 0000000..898c223 --- /dev/null +++ b/.zenodo.json @@ -0,0 +1,11 @@ +{ + "title": "OWASP GenAI Data Security Initiative: datasets", + "upload_type": "dataset", + "description": "Vulnerability, exploit-technique, risk-assessment, agent-trace, prompt-injection test-case and RAG fixture datasets for generative-AI data security, mapped to the OWASP GenAI Data Security (DSGAI) risk taxonomy, MITRE ATLAS, the OWASP Top 10 for LLM and Agentic Applications, NIST AI 100-2 and CWE. Each dataset ships MLCommons Croissant 1.1 metadata with Responsible AI fields.", + "creators": [{"name": "OWASP GenAI Data Security Initiative"}], + "license": "cc-by-sa-4.0", + "keywords": ["generative AI", "AI security", "data security", "OWASP", "DSGAI", "prompt injection", "LLM vulnerabilities"], + "related_identifiers": [ + {"identifier": "https://github.com/GenAI-Security-Project/GenAI-Data-Security-Initiative", "relation": "isSupplementTo", "scheme": "url"} + ] +} diff --git a/CITATION.cff b/CITATION.cff new file mode 100644 index 0000000..3b34a85 --- /dev/null +++ b/CITATION.cff @@ -0,0 +1,21 @@ +cff-version: 1.2.0 +title: "OWASP GenAI Data Security Initiative: datasets" +message: "If you use these datasets, please cite them as below." +type: dataset +authors: + - name: "OWASP GenAI Data Security Initiative" +repository-code: "https://github.com/GenAI-Security-Project/GenAI-Data-Security-Initiative" +url: "https://genai.owasp.org/initiatives/ai-data-security-initiative/" +license: CC-BY-SA-4.0 +# The datasets release version. A release is cut by tagging datasets-v +# (see .github/workflows/datasets-release.yml); the tag must match this value. +version: "1.0.0" +date-released: "2026-10-09" +keywords: + - generative AI + - AI security + - data security + - OWASP + - DSGAI + - prompt injection + - LLM vulnerabilities diff --git a/data_validation/README.md b/data_validation/README.md index 5e0b0da..b6bb24f 100644 --- a/data_validation/README.md +++ b/data_validation/README.md @@ -76,6 +76,7 @@ After the automated checks pass, contributions are reviewed by cybersecurity and | `anomaly_detector.py` | A DSGAI entry most of a dataset maps to, records with far more mappings than usual, and one severity or category value dominating a dataset (datasets of 10+ records) | | `online_check.py` | Runs weekly (`datasets-online-checks` workflow), not on PRs, because it needs the network. **Fails** on a CVE the CVE Program has rejected or doesn't know, a withdrawn GHSA, a dead cited link (with the Wayback Machine snapshot to use instead), or a CVE in CISA KEV whose entry isn't marked `exploited_in_the_wild`. Reports every CVE's EPSS v4 score and KEV status. These change daily, so they're reported, not stored | | `ner_pii_scan.py` | Person names (and, in `incident_dataset`, organisation names) found by named-entity recognition (Microsoft Presidio + spaCy) in the datasets that require anonymization. Warnings only, in the CI job summary; reviewed false positives go in `reference_data/ner_allowlist.txt`. Optional dependencies: `requirements-ner.txt` | +| `croissant/build_croissant.py`, `croissant/check_croissant.py` | Generate each dataset's MLCommons Croissant 1.1 metadata (with RAI fields) and check it in CI: up to date with the data, valid per `mlcroissant`, and loadable record by record | | `consistency_check.py` | **Fails** on internal references (`DSGAI-VULN-…`, `DSGAI-EXP-…`, `DSGAI-RA-…`) that point at no existing entry; notes CVEs cited by exploits that have no vulnerability entry | --- @@ -117,6 +118,7 @@ data_validation/ ├── run_all_checks.py One command for everything (CI runs this) ├── validators/ Shared checks; each also runs on its own ├── qc_tools/ Reports for reviewers +├── croissant/ Croissant 1.1 metadata generator and checker ├── schemas/ Schemas for datasets without their own schema.json │ (the rest are pointers to the dataset-local schemas) ├── reference_data/ DSGAI, MITRE ATLAS, CWE, OWASP Top 10, NIST AI 100-2, SPDX and diff --git a/data_validation/croissant/build_croissant.py b/data_validation/croissant/build_croissant.py new file mode 100644 index 0000000..0cee86e --- /dev/null +++ b/data_validation/croissant/build_croissant.py @@ -0,0 +1,333 @@ +""" +Generates datasets//croissant.json, the MLCommons Croissant 1.1 +metadata (with the Responsible AI vocabulary) for each published dataset. + +Croissant makes a dataset machine-readable for ML tooling and dataset +search: what the files are, their checksums, how to load the records, and +RAI documentation (limitations, biases, intended uses, personal data, +collection). NeurIPS 2026 requires it, RAI fields included, for dataset +submissions. + + python build_croissant.py # write every croissant.json + python build_croissant.py --check # fail if any is out of date (CI) + +The descriptive and RAI text lives in DATASETS below; file lists, SHA-256 +checksums, record fields and dates are derived from the repository, so the +output is deterministic and only changes when the data does. CI validates +every file with `mlcroissant validate` and loads records through it. +Requires: mlcroissant (requirements-croissant.txt). + +incident_dataset (no entries yet) and crossframework_mapping_dataset +(superseded by the GenAI Crosswalk) are not described. +""" +from __future__ import annotations + +import argparse +import csv +import hashlib +import json +import re +import sys +from datetime import datetime +from pathlib import Path + +REPO_ROOT = Path(__file__).resolve().parents[2] +DATASETS_ROOT = REPO_ROOT / "datasets" +REPO_URL = "https://github.com/GenAI-Security-Project/GenAI-Data-Security-Initiative" +LICENSE_BY_SA = "https://creativecommons.org/licenses/by-sa/4.0/" +LICENSE_BY = "https://creativecommons.org/licenses/by/4.0/" +CROISSANT_1_1 = "http://mlcommons.org/croissant/1.1" +MAINTENANCE = ("Maintained by the OWASP GenAI Data Security Initiative (Workstream 5). Contributions arrive as " + "pull requests and must pass data_validation/run_all_checks.py in CI and peer review; weekly online " + "checks re-verify cited CVEs, advisories and links. Versioned releases carry SHA-256 checksums.") + +# Per-dataset description and Responsible AI documentation. Keep these true +# to the data: when a dataset changes shape, update its entry here. +DATASETS: dict[str, dict] = { + "vulnerability_dataset": { + "title": "DSGAI Vulnerability Dataset", + "description": ( + "Publicly disclosed vulnerabilities in LLM and GenAI applications (CVE-tracked issues and significant " + "published research disclosures), each mapped to the OWASP GenAI Data Security (DSGAI) risk taxonomy, " + "the OWASP Top 10 for LLM Applications (2025 and 2026 editions), CWE and CVSS."), + "index": "index.csv", + "license": [LICENSE_BY_SA], + "collection": ("Curated by initiative contributors from public sources: NVD and CVE records, vendor and " + "GitHub security advisories, and peer-reviewed or widely cited research. Every entry cites " + "its sources; CVSS vectors and scores are taken from NVD or the assigning CNA."), + "collection_type": ["Secondary Data analysis", "Manual Human Curator"], + "limitations": [ + "Covers only publicly disclosed issues; undisclosed and vendor-internal vulnerabilities are absent by design.", + "Not exhaustive: a curated sample, not a census of GenAI CVEs. Absence of a product does not imply it is secure.", + "DSGAI and OWASP mappings are expert judgments reviewed by peers, not mechanically derived.", + ], + "biases": [ + "Skews toward open-source Python LLM frameworks and inference servers (agent frameworks are about half of " + "the entries), because CVE assignment concentrates there; closed SaaS assistants appear only through " + "public research disclosures.", + "Skews toward High and Critical severity: low-severity issues are rarely publicised or assigned CVEs.", + "Disclosure dates cluster in 2023-2025, the period the corpus was assembled for.", + ], + "use_cases": [ + "Mapping real GenAI vulnerabilities to DSGAI risks for threat modelling and control prioritisation.", + "Evaluation and regression data for GenAI security scanners and LLM-application security reviews.", + "Not intended for exploit development; entries describe issues at advisory level of detail.", + ], + "pii": ("No personal data. Entries describe software vulnerabilities and cite public advisories; researcher " + "names appear only where a cited public source credits them."), + "social_impact": ("Helps defenders prioritise GenAI data-security controls. All issues are already public, " + "so the dataset adds aggregation and mapping rather than new attack capability."), + }, + "exploit_dataset": { + "title": "DSGAI Exploit Technique Dataset", + "description": ( + "Publicly documented attack techniques against GenAI systems, one technique class per entry (how an attacker " + "does something, not a product-specific flaw), mapped to MITRE ATLAS, the DSGAI taxonomy and the OWASP " + "Top 10 for LLM Applications. Most entries follow MITRE ATLAS techniques; the rest are research-derived " + "technique families ATLAS does not track separately."), + "index": "index.csv", + "license": [LICENSE_BY_SA], + "collection": ("Curated from the MITRE ATLAS catalog and published research (papers, vendor advisories, " + "conference talks). Each entry cites its sources and links related vulnerability entries."), + "collection_type": ["Secondary Data analysis", "Manual Human Curator"], + "limitations": [ + "Describes techniques at the level of public literature; it is not a playbook and omits weaponised detail.", + "ATLAS-derived entries track the ATLAS release they were written against; a monthly job flags retired IDs.", + "Severity is a qualitative judgment of the technique class, not a CVSS score.", + ], + "biases": [ + "About 70% of entries come from the MITRE ATLAS catalog, so coverage follows ATLAS's own emphasis.", + "Weighted toward prompt-injection, jailbreak and poisoning techniques, which dominate the published literature.", + ], + "use_cases": [ + "Red-team planning and coverage analysis of GenAI defences against known technique classes.", + "Linking techniques to concrete vulnerabilities and to DSGAI risks in threat models.", + ], + "pii": "No personal data.", + "social_impact": ("Techniques are already public; the dataset organises them for defenders. Dual-use " + "risk is limited by keeping entries at catalog-level detail."), + }, + "riskassessment_dataset": { + "title": "DSGAI Risk Assessment Dataset", + "description": ( + "Structured risk assessments of GenAI deployment archetypes: for each representative architecture, the " + "DSGAI risks with inherent and residual ratings and rationale, existing controls, control gaps, and " + "alignments to security and AI-governance frameworks."), + "index": "index.csv", + "license": [LICENSE_BY_SA], + "collection": ("Written by initiative contributors as synthetic-but-realistic templates of common deployment " + "patterns, informed by public guidance and practitioner experience; peer reviewed."), + "collection_type": ["Manual Human Curator"], + "limitations": [ + "Every entry is a synthetic template of a deployment archetype, not an assessment of a real organisation.", + "Ratings and control gaps are expert judgments for the described archetype; a real deployment needs its own assessment.", + ], + "biases": [ + "Sector coverage is uneven: cross-sector templates are the largest group, followed by financial " + "services and SaaS; several sectors have a single template.", + "Framework alignments reflect the frameworks contributors know best.", + ], + "use_cases": [ + "Starting points and worked examples for GenAI risk assessments and DSGAI training.", + "Benchmark scenarios for comparing control coverage across deployment patterns.", + ], + "pii": "No personal data: the scenarios are synthetic and describe archetypes, not organisations or people.", + "social_impact": "Lowers the cost of structured GenAI risk assessment for smaller organisations.", + }, + "agentdataflow_toolexchange_traces": { + "title": "Agent Data Flow and Tool Exchange Traces", + "description": ( + "Sanitized traces of agentic AI tool calls, plugin data exchanges and delegation chains: typed spans, " + "data classes and sensitivity, findings mapped to DSGAI risks, and a provenance tier with cited evidence."), + "index": "index.csv", + "license": [LICENSE_BY_SA], + "collection": ("Constructed by contributors as minimal traces of documented agent and MCP behaviour, or as " + "explicitly hypothetical scenarios; each declares its provenance tier and cites evidence."), + "collection_type": ["Manual Human Curator", "Document analysis"], + "limitations": [ + "Very small: a handful of traces so far, all of unintentional failures; adversarial traces are not yet included.", + "Traces are reconstructions from public documentation or hypothetical, not captured production telemetry.", + ], + "biases": ["Centred on MCP-based tool ecosystems, where most public agent data-flow documentation exists."], + "use_cases": [ + "Studying how sensitive data moves through agent tool calls, and testing agent data-flow analysers.", + "Worked examples for DSGAI06 and related agent data-exchange risks.", + ], + "pii": ("No personal data. Payload values are synthetic placeholders; validate.py fails any trace containing " + "credential, internal-hostname or real-address patterns."), + "social_impact": "Supports safer agent designs by making data-exchange failure modes concrete.", + }, + "promptinj_dataextraction_testcases": { + "title": "Prompt Injection and Data Extraction Test Cases", + "description": ( + "Adversarial prompts with expected secure and vulnerable behaviour, for red-teaming and regression " + "testing of GenAI data-security controls. Current suites are Turkish-language: adapted cases from a public " + "corpus, contrastive attack/benign-control pairs, and a small hand-written set with English glosses."), + "index": None, + "published": "2026-03-23", + "manifests": ["tr_altaysec_turkish_llm_injection/manifest.csv", + "tr_turkish_conversation_prompt_injection_pairs/manifest.csv"], + "license": [LICENSE_BY_SA, LICENSE_BY], + "collection": ("Contributed suites. Most cases adapt public CC BY 4.0 corpora (attribution and source " + "hashes are kept in each case's provenance); the adaptation adds DSGAI mappings, expected " + "behaviours and sandbox prerequisites. A small set was written for this dataset."), + "collection_type": ["Secondary Data analysis", "Manual Human Curator"], + "limitations": [ + "Almost entirely Turkish; results do not transfer to other languages without new cases.", + "Expected behaviours are defensive test expectations, not observed results for any model.", + "Lexical deduplication only; paraphrased near-duplicates may remain.", + ], + "biases": [ + "Weighted toward system-prompt extraction and direct data extraction; other categories have fewer cases.", + "Reflects the attack styles of its source corpora (authority and urgency framing, morphological and " + "cross-lingual bypasses).", + ], + "use_cases": [ + "Sandboxed red-team exercises and regression tests for prompt-injection and data-extraction defences.", + "Evaluating multilingual (Turkish) robustness of guardrails. Do not run against production systems.", + ], + "pii": ("Synthetic data only: secrets and identifiers in prompts are placeholders, and cases were screened " + "for real personal data and live-secret patterns."), + "social_impact": ("Adversarial prompts are dual-use; they are published at the level already public in " + "their source corpora so defenders can test non-English guardrail gaps."), + }, + "rag_dataset": { + "title": "RAG Poisoning and Retrieval Integrity Dataset", + "description": ( + "Synthetic documents and test fixtures for retrieval-augmented generation: poisoned documents, integrity " + "and redaction tests, cross-tenant probes, each with expected secure and vulnerable retrieval behaviour."), + "index": None, + "published": "2026-03-23", + "license": [LICENSE_BY_SA], + "collection": "Written by contributors as synthetic, safe-to-ingest regression fixtures.", + "collection_type": ["Manual Human Curator"], + "limitations": ["A single fixture so far; it demonstrates the format more than it covers the space."], + "biases": ["Covers one poisoning pattern (a false policy value plus a harmless canary instruction)."], + "use_cases": ["Regression tests for RAG ingestion quarantine, retrieval filtering and context resilience."], + "pii": "No personal data; all content is synthetic and labelled as such in each record's metadata.", + "social_impact": "Fixtures use harmless canaries so they cannot cause harm if ingested by mistake.", + }, +} + + +def sha256(path: Path) -> str: + """SHA-256 of the file as the repository stores and serves it. + + .gitattributes keeps dataset CSV and JSON files LF in the repository, but + a Windows checkout (core.autocrlf) or a csv-module writer may leave CRLF + in a working copy; hashing LF-normalized bytes gives the same checksum + on every platform, matching the downloaded file.""" + return hashlib.sha256(path.read_bytes().replace(b"\r\n", b"\n")).hexdigest() + + +def entry_dates(dataset: Path) -> list[str]: + dates = [] + for path in dataset.rglob("*.json"): + if "fixtures" in path.parts or path.name.endswith("schema.json") or path.name == "croissant.json": + continue + for value in re.findall(r'"date_added":\s*"(\d{4}-\d{2}-\d{2})"', path.read_text(encoding="utf-8")): + dates.append(value) + return sorted(dates) + + +def csv_record_set(mlc, rs_id: str, file_id: str, path: Path): + columns = next(csv.reader(path.open(encoding="utf-8"))) + fields = [mlc.Field(id=f"{rs_id}/{c}", name=c, data_types=[mlc.DataType.TEXT], + source=mlc.Source(file_object=file_id, extract=mlc.Extract(column=c))) + for c in columns] + return mlc.RecordSet(id=rs_id, name=rs_id, fields=fields, + description=f"One record per row of {path.name}; list-valued columns are joined with '|'.") + + +def build(name: str, spec: dict, version: str) -> dict: + import mlcroissant as mlc + dataset = DATASETS_ROOT / name + distribution, record_sets = [], [] + for csv_rel in ([spec["index"]] if spec.get("index") else []) + spec.get("manifests", []): + path = dataset / csv_rel + file_id = csv_rel + distribution.append(mlc.FileObject(id=file_id, name=file_id, content_url=csv_rel, + encoding_formats=["text/csv"], sha256=sha256(path))) + rs_id = "index" if csv_rel == spec.get("index") else csv_rel.split("/")[0] + record_sets.append(csv_record_set(mlc, rs_id, file_id, path)) + for schema in sorted(dataset.rglob("*schema.json")): + rel = schema.relative_to(dataset).as_posix() + if "fixtures" in rel: + continue + distribution.append(mlc.FileObject(id=rel, name=rel, content_url=rel, encoding_formats=["application/json"], + sha256=sha256(schema), description="JSON Schema for the records")) + globs = sorted({p.relative_to(dataset).parent.as_posix() for p in dataset.rglob("*.json") + if p.parent.name in ("entries", "cases")}) + for g in globs: + distribution.append(mlc.FileSet(id=f"{g}/", name=f"{g}/", includes=[f"{g}/*.json"], + encoding_formats=["application/json"], description="One JSON record per file")) + # Dates come from the records (date_added); a dataset whose records carry + # none states its publication date in DATASETS. Nothing is read from git, + # so the output is the same in a shallow CI clone. + dates = entry_dates(dataset) + published = dates[0] if dates else spec["published"] + modified = dates[-1] if dates else None + url = f"{REPO_URL}/tree/main/datasets/{name}" + metadata = mlc.Metadata( + name=name, + description=f"{spec['title']}. {spec['description']}", + url=url, + license=spec["license"], + conforms_to=[CROISSANT_1_1], + version=version, + cite_as=(f"OWASP GenAI Data Security Initiative. {spec['title']} (version {version}). " + f"OWASP GenAI Security Project. {url}"), + date_published=datetime.fromisoformat(published) if published else None, + date_modified=datetime.fromisoformat(modified) if modified else None, + distribution=distribution, + record_sets=record_sets, + data_collection=spec["collection"], + data_collection_type=spec["collection_type"], + data_limitations=spec["limitations"], + data_biases=spec["biases"], + data_use_cases=spec["use_cases"], + personal_sensitive_information=[spec["pii"]], + data_social_impact=spec["social_impact"], + data_release_maintenance_plan=MAINTENANCE, + ) + issues = metadata.issues + if issues.errors: + raise SystemExit(f"{name}: {issues.report()}") + return metadata.to_json() + + +def release_version() -> str: + """The datasets release version, from CITATION.cff.""" + match = re.search(r"^version:\s*['\"]?([^'\"\s]+)", (REPO_ROOT / "CITATION.cff").read_text(encoding="utf-8"), re.M) + if not match: + raise SystemExit("CITATION.cff has no version") + return match.group(1) + + +def render(data: dict) -> str: + return json.dumps(data, indent=2, ensure_ascii=False, default=str) + "\n" + + +def main(argv: list[str] | None = None) -> int: + parser = argparse.ArgumentParser(description="Generate Croissant 1.1 metadata for the datasets") + parser.add_argument("--check", action="store_true", help="Fail if any croissant.json is out of date") + args = parser.parse_args(argv) + version = release_version() + stale = [] + for name, spec in DATASETS.items(): + target = DATASETS_ROOT / name / "croissant.json" + text = render(build(name, spec, version)) + if args.check: + if not target.is_file() or target.read_text(encoding="utf-8") != text: + stale.append(target.relative_to(REPO_ROOT).as_posix()) + else: + target.write_text(text, encoding="utf-8", newline="") # LF on every platform + print(f"wrote {target.relative_to(REPO_ROOT).as_posix()}") + if stale: + print("Out of date (run python data_validation/croissant/build_croissant.py): " + ", ".join(stale)) + return 1 + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/data_validation/croissant/check_croissant.py b/data_validation/croissant/check_croissant.py new file mode 100644 index 0000000..3f78082 --- /dev/null +++ b/data_validation/croissant/check_croissant.py @@ -0,0 +1,46 @@ +""" +Validates every datasets/*/croissant.json with mlcroissant and loads each +record set through it, checking the record count matches the CSV it reads. +A file that validates but cannot actually load its data fails here. + + python check_croissant.py +""" +from __future__ import annotations + +import csv +import json +import sys +from pathlib import Path + +DATASETS_ROOT = Path(__file__).resolve().parents[2] / "datasets" + + +def main() -> int: + import mlcroissant as mlc + failures = 0 + files = sorted(DATASETS_ROOT.glob("*/croissant.json")) + for path in files: + meta = json.loads(path.read_text(encoding="utf-8")) + try: + dataset = mlc.Dataset(jsonld=str(path)) + except mlc.ValidationError as exc: + print(f"FAIL {path.parent.name}: {exc}") + failures += 1 + continue + for record_set in meta.get("recordSet", []): + rs_id = record_set["@id"] + file_id = record_set["field"][0]["source"]["fileObject"]["@id"] + with open(path.parent / file_id, newline="", encoding="utf-8") as fh: + expected = sum(1 for _ in csv.DictReader(fh)) + loaded = sum(1 for _ in dataset.records(record_set=rs_id)) + status = "PASS" if loaded == expected else "FAIL" + failures += status == "FAIL" + print(f"{status} {path.parent.name}/{rs_id}: {loaded} record(s) loaded, {expected} expected") + if not meta.get("recordSet"): + print(f"PASS {path.parent.name}: metadata valid (no record set)") + print(f"{len(files)} Croissant file(s), {failures} failure(s)") + return 1 if failures or not files else 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/data_validation/requirements-croissant.txt b/data_validation/requirements-croissant.txt new file mode 100644 index 0000000..420294d --- /dev/null +++ b/data_validation/requirements-croissant.txt @@ -0,0 +1,2 @@ +# Optional: only for data_validation/croissant/build_croissant.py and its CI check. +mlcroissant>=1.1.0,<1.2 diff --git a/data_validation/tests/test_standards.py b/data_validation/tests/test_standards.py index 3aa7136..83da9f2 100644 --- a/data_validation/tests/test_standards.py +++ b/data_validation/tests/test_standards.py @@ -76,3 +76,21 @@ def test_nist_table_matches_the_publication(): assert len(NIST_IDS) == 30 == len(set(NIST_IDS)) objectives = [i for i in NIST_IDS if len(i.split(".")[1]) == 2] assert objectives == ["NISTAML.01", "NISTAML.02", "NISTAML.03", "NISTAML.04", "NISTAML.05"] + + +def test_every_published_dataset_has_croissant_metadata(): + """A dataset folder with records needs a croissant.json (build_croissant.py makes it).""" + sys.path.insert(0, str(Path(__file__).resolve().parent.parent / "croissant")) + from build_croissant import DATASETS + with_records = {p.parent.name for p in DATASETS_ROOT.glob("*/*.json")} | \ + {p.parents[1].name for p in DATASETS_ROOT.glob("*/entries/*.json")} | \ + {p.parents[2].name for p in DATASETS_ROOT.glob("*/*/cases/*.json")} + with_records -= {"_shared"} + assert with_records <= set(DATASETS), f"no Croissant description for {sorted(with_records - set(DATASETS))}" + for name in DATASETS: + assert (DATASETS_ROOT / name / "croissant.json").is_file(), name + + +def test_citation_version_is_semver(): + text = (DATASETS_ROOT.parent / "CITATION.cff").read_text(encoding="utf-8") + assert re.search(r'^version: "\d+\.\d+\.\d+"$', text, re.M) diff --git a/data_validation/validators/_common.py b/data_validation/validators/_common.py index 8a3e16e..c8e6b42 100644 --- a/data_validation/validators/_common.py +++ b/data_validation/validators/_common.py @@ -59,8 +59,8 @@ def format(self, base: Path | None = None) -> str: def is_data_file(path: Path, root: Path) -> bool: - """A JSON file under root that holds data, not a schema or a test fixture.""" - if path.suffix != ".json" or path.name == "schema.json" or path.name.endswith(".schema.json"): + """A JSON file under root that holds data, not a schema, Croissant metadata or a test fixture.""" + if path.suffix != ".json" or path.name in ("schema.json", "croissant.json") or path.name.endswith(".schema.json"): return False rel = path.relative_to(root).parts[:-1] return not any(p in SKIP_DIRS or p.startswith((".", "_")) for p in rel) diff --git a/datasets/README.md b/datasets/README.md index c02e25f..9f78017 100644 --- a/datasets/README.md +++ b/datasets/README.md @@ -11,10 +11,31 @@ Community-contributed datasets supporting research, benchmarking, and practical | `crossframework_mapping_dataset` | Machine-readable DSGAI-to-framework control mappings | Superseded by the [GenAI Crosswalk](https://github.com/GenAI-Security-Project/crosswalk) | | `agentdataflow_toolexchange_traces` | Sanitized agentic AI tool call and delegation chain traces | Accepting contributions | +## Metadata, releases and citation + +**Croissant.** Every published dataset folder has a `croissant.json`: [MLCommons Croissant 1.1](https://docs.mlcommons.org/croissant/) metadata with Responsible AI fields (limitations, biases, intended uses, personal data, collection, maintenance). ML tooling can load the records from it directly: + +```python +import mlcroissant as mlc +records = mlc.Dataset(jsonld="datasets/vulnerability_dataset/croissant.json").records(record_set="index") +``` + +The files are generated by [`data_validation/croissant/build_croissant.py`](../data_validation/croissant/build_croissant.py), which also holds each dataset's RAI text. CI fails when one is out of date, for example after an entry changes the dataset's `index.csv`, so regenerate after editing entries. + +**Releases.** Versioned releases are cut by tagging `datasets-v`, where the version must equal the one in [`CITATION.cff`](../CITATION.cff). The release workflow re-runs every check and publishes one zip per dataset plus an all-datasets zip, with `SHA256SUMS` and a Sigstore build-provenance attestation for each file. To verify a download: + +```bash +sha256sum -c SHA256SUMS --ignore-missing +gh attestation verify owasp-dsgai-vulnerability_dataset-1.0.0.zip --repo GenAI-Security-Project/GenAI-Data-Security-Initiative +``` + +**Citation.** Cite the datasets with [`CITATION.cff`](../CITATION.cff) (GitHub's "Cite this repository" button), or with the per-dataset `citeAs` in each `croissant.json`. With the repository enabled in Zenodo's GitHub integration, each release is archived on Zenodo with a DOI; [`.zenodo.json`](../.zenodo.json) supplies its metadata. + ## How to Contribute 1. Fork this repository 2. Add your data to the appropriate dataset folder following the formatting guidelines in that folder's README -3. Submit a pull request with a description of your contribution +3. Run `python data_validation/run_all_checks.py`, and regenerate the dataset's `index.csv` (where it has a `build_index.py`) and `croissant.json` (`python data_validation/croissant/build_croissant.py`, which needs `pip install -r data_validation/requirements-croissant.txt`) +4. Submit a pull request with a description of your contribution For questions or to discuss contributions, join `#team-genai-data-security-initiative` on the [OWASP Slack workspace](https://owasp.slack.com). diff --git a/datasets/agentdataflow_toolexchange_traces/croissant.json b/datasets/agentdataflow_toolexchange_traces/croissant.json new file mode 100644 index 0000000..3586886 --- /dev/null +++ b/datasets/agentdataflow_toolexchange_traces/croissant.json @@ -0,0 +1,365 @@ +{ + "@context": { + "@language": "en", + "@vocab": "https://schema.org/", + "citeAs": "cr:citeAs", + "column": "cr:column", + "conformsTo": "dct:conformsTo", + "cr": "http://mlcommons.org/croissant/", + "rai": "http://mlcommons.org/croissant/RAI/", + "data": { + "@id": "cr:data", + "@type": "@json" + }, + "dataType": { + "@id": "cr:dataType", + "@type": "@vocab" + }, + "dct": "http://purl.org/dc/terms/", + "equivalentProperty": "cr:equivalentProperty", + "examples": { + "@id": "cr:examples", + "@type": "@json" + }, + "extract": "cr:extract", + "field": "cr:field", + "fileProperty": "cr:fileProperty", + "fileObject": "cr:fileObject", + "fileSet": "cr:fileSet", + "format": "cr:format", + "includes": "cr:includes", + "isLiveDataset": "cr:isLiveDataset", + "jsonPath": "cr:jsonPath", + "key": "cr:key", + "md5": "cr:md5", + "parentField": "cr:parentField", + "path": "cr:path", + "recordSet": "cr:recordSet", + "references": "cr:references", + "regex": "cr:regex", + "repeated": "cr:repeated", + "replace": "cr:replace", + "samplingRate": "cr:samplingRate", + "sc": "https://schema.org/", + "separator": "cr:separator", + "source": "cr:source", + "subField": "cr:subField", + "transform": "cr:transform" + }, + "@type": "sc:Dataset", + "name": "agentdataflow_toolexchange_traces", + "description": "Agent Data Flow and Tool Exchange Traces. Sanitized traces of agentic AI tool calls, plugin data exchanges and delegation chains: typed spans, data classes and sensitivity, findings mapped to DSGAI risks, and a provenance tier with cited evidence.", + "conformsTo": "http://mlcommons.org/croissant/1.1", + "citeAs": "OWASP GenAI Data Security Initiative. Agent Data Flow and Tool Exchange Traces (version 1.0.0). OWASP GenAI Security Project. https://github.com/GenAI-Security-Project/GenAI-Data-Security-Initiative/tree/main/datasets/agentdataflow_toolexchange_traces", + "dateModified": "2026-09-15", + "datePublished": "2026-08-07", + "license": "https://creativecommons.org/licenses/by-sa/4.0/", + "rai:dataBiases": "Centred on MCP-based tool ecosystems, where most public agent data-flow documentation exists.", + "rai:dataCollection": "Constructed by contributors as minimal traces of documented agent and MCP behaviour, or as explicitly hypothetical scenarios; each declares its provenance tier and cites evidence.", + "rai:dataCollectionType": [ + "Manual Human Curator", + "Document analysis" + ], + "rai:dataLimitations": [ + "Very small: a handful of traces so far, all of unintentional failures; adversarial traces are not yet included.", + "Traces are reconstructions from public documentation or hypothetical, not captured production telemetry." + ], + "rai:dataReleaseMaintenancePlan": "Maintained by the OWASP GenAI Data Security Initiative (Workstream 5). Contributions arrive as pull requests and must pass data_validation/run_all_checks.py in CI and peer review; weekly online checks re-verify cited CVEs, advisories and links. Versioned releases carry SHA-256 checksums.", + "rai:dataSocialImpact": "Supports safer agent designs by making data-exchange failure modes concrete.", + "rai:dataUseCases": [ + "Studying how sensitive data moves through agent tool calls, and testing agent data-flow analysers.", + "Worked examples for DSGAI06 and related agent data-exchange risks." + ], + "rai:personalSensitiveInformation": "No personal data. Payload values are synthetic placeholders; validate.py fails any trace containing credential, internal-hostname or real-address patterns.", + "url": "https://github.com/GenAI-Security-Project/GenAI-Data-Security-Initiative/tree/main/datasets/agentdataflow_toolexchange_traces", + "version": "1.0.0", + "distribution": [ + { + "@type": "cr:FileObject", + "@id": "index.csv", + "name": "index.csv", + "contentUrl": "index.csv", + "encodingFormat": "text/csv", + "sha256": "e6f02ff2e11f9b3bd6381eb3d4900ffafc52a82fa2f4598f8092e75bbc97297b" + }, + { + "@type": "cr:FileObject", + "@id": "schema.json", + "name": "schema.json", + "description": "JSON Schema for the records", + "contentUrl": "schema.json", + "encodingFormat": "application/json", + "sha256": "6a6af36f6f5dadb4569993f8731c76de5d5ef6dcf110cd67f68524f3d73b03a9" + }, + { + "@type": "cr:FileSet", + "@id": "entries/", + "name": "entries/", + "description": "One JSON record per file", + "encodingFormat": "application/json", + "includes": "entries/*.json" + } + ], + "recordSet": [ + { + "@type": "cr:RecordSet", + "@id": "index", + "name": "index", + "description": "One record per row of index.csv; list-valued columns are joined with '|'.", + "field": [ + { + "@type": "cr:Field", + "@id": "index/trace_id", + "name": "trace_id", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "index.csv" + }, + "extract": { + "column": "trace_id" + } + } + }, + { + "@type": "cr:Field", + "@id": "index/title", + "name": "title", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "index.csv" + }, + "extract": { + "column": "title" + } + } + }, + { + "@type": "cr:Field", + "@id": "index/category", + "name": "category", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "index.csv" + }, + "extract": { + "column": "category" + } + } + }, + { + "@type": "cr:Field", + "@id": "index/disposition", + "name": "disposition", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "index.csv" + }, + "extract": { + "column": "disposition" + } + } + }, + { + "@type": "cr:Field", + "@id": "index/provenance_tier", + "name": "provenance_tier", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "index.csv" + }, + "extract": { + "column": "provenance_tier" + } + } + }, + { + "@type": "cr:Field", + "@id": "index/primary_dsgai", + "name": "primary_dsgai", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "index.csv" + }, + "extract": { + "column": "primary_dsgai" + } + } + }, + { + "@type": "cr:Field", + "@id": "index/dsgai_mapping", + "name": "dsgai_mapping", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "index.csv" + }, + "extract": { + "column": "dsgai_mapping" + } + } + }, + { + "@type": "cr:Field", + "@id": "index/owasp_llm_top10_mapping", + "name": "owasp_llm_top10_mapping", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "index.csv" + }, + "extract": { + "column": "owasp_llm_top10_mapping" + } + } + }, + { + "@type": "cr:Field", + "@id": "index/agent_framework", + "name": "agent_framework", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "index.csv" + }, + "extract": { + "column": "agent_framework" + } + } + }, + { + "@type": "cr:Field", + "@id": "index/tool_protocol", + "name": "tool_protocol", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "index.csv" + }, + "extract": { + "column": "tool_protocol" + } + } + }, + { + "@type": "cr:Field", + "@id": "index/span_count", + "name": "span_count", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "index.csv" + }, + "extract": { + "column": "span_count" + } + } + }, + { + "@type": "cr:Field", + "@id": "index/finding_count", + "name": "finding_count", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "index.csv" + }, + "extract": { + "column": "finding_count" + } + } + }, + { + "@type": "cr:Field", + "@id": "index/max_sensitivity", + "name": "max_sensitivity", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "index.csv" + }, + "extract": { + "column": "max_sensitivity" + } + } + }, + { + "@type": "cr:Field", + "@id": "index/data_classes", + "name": "data_classes", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "index.csv" + }, + "extract": { + "column": "data_classes" + } + } + }, + { + "@type": "cr:Field", + "@id": "index/evidence_count", + "name": "evidence_count", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "index.csv" + }, + "extract": { + "column": "evidence_count" + } + } + }, + { + "@type": "cr:Field", + "@id": "index/primary_evidence", + "name": "primary_evidence", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "index.csv" + }, + "extract": { + "column": "primary_evidence" + } + } + }, + { + "@type": "cr:Field", + "@id": "index/date_added", + "name": "date_added", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "index.csv" + }, + "extract": { + "column": "date_added" + } + } + }, + { + "@type": "cr:Field", + "@id": "index/tags", + "name": "tags", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "index.csv" + }, + "extract": { + "column": "tags" + } + } + } + ] + } + ] +} diff --git a/datasets/agentdataflow_toolexchange_traces/index.csv b/datasets/agentdataflow_toolexchange_traces/index.csv index 8def48d..89f3f51 100644 --- a/datasets/agentdataflow_toolexchange_traces/index.csv +++ b/datasets/agentdataflow_toolexchange_traces/index.csv @@ -1,4 +1,4 @@ -trace_id,title,category,disposition,provenance_tier,primary_dsgai,dsgai_mapping,owasp_llm_top10_mapping,agent_framework,tool_protocol,span_count,finding_count,max_sensitivity,data_classes,evidence_count,primary_evidence,date_added,tags -DSGAI-TRACE-mcp-declared-effect-flip-stale-autoapproval,Tool re-declares itself destructive after an agent has already auto-approved it,tool_call,unintentional_failure,derived_from_public_documentation,DSGAI06,DSGAI06|DSGAI05|DSGAI07,LLM06:2025|LLM03:2025|LLM03:2026|LLM04:2026,custom,mcp,10,4,high,tool_output|tool_schema,4,https://modelcontextprotocol.io/specification/2025-06-18/schema,2026-08-07,mcp|tool-contract-drift|declared-effect|approval-bypass|excessive-agency|supply-chain -DSGAI-TRACE-mcp-output-schema-expansion-context-overshare,"Tool output schema widens under a stable version, and the extra fields flow straight into model context",context_accumulation,unintentional_failure,derived_from_public_documentation,DSGAI15,DSGAI15|DSGAI01|DSGAI14|DSGAI05,LLM02:2025|LLM05:2025|LLM02:2026|LLM10:2026,custom,mcp,10,6,high,financial|pii|proprietary|telemetry|tool_output|tool_schema|user_prompt,2,https://modelcontextprotocol.io/specification/2025-06-18/server/tools,2026-08-07,mcp|tool-contract-drift|output-schema|context-window|over-sharing|telemetry-leakage -DSGAI-TRACE-overbroad-search-context-egress-self-report-gap,Over-broad search scope leaks an HR document through a full-context email the agent's own record does not mention,tool_call,unintentional_failure,hypothetical,DSGAI06,DSGAI06|DSGAI15,,custom,,7,2,high,file_path|financial|pii|retrieved_document|telemetry|token|tool_output|user_prompt,0,,2026-09-15,workspace-search|email-egress|context-oversharing|observability-gap|self-report-divergence +trace_id,title,category,disposition,provenance_tier,primary_dsgai,dsgai_mapping,owasp_llm_top10_mapping,agent_framework,tool_protocol,span_count,finding_count,max_sensitivity,data_classes,evidence_count,primary_evidence,date_added,tags +DSGAI-TRACE-mcp-declared-effect-flip-stale-autoapproval,Tool re-declares itself destructive after an agent has already auto-approved it,tool_call,unintentional_failure,derived_from_public_documentation,DSGAI06,DSGAI06|DSGAI05|DSGAI07,LLM06:2025|LLM03:2025|LLM03:2026|LLM04:2026,custom,mcp,10,4,high,tool_output|tool_schema,4,https://modelcontextprotocol.io/specification/2025-06-18/schema,2026-08-07,mcp|tool-contract-drift|declared-effect|approval-bypass|excessive-agency|supply-chain +DSGAI-TRACE-mcp-output-schema-expansion-context-overshare,"Tool output schema widens under a stable version, and the extra fields flow straight into model context",context_accumulation,unintentional_failure,derived_from_public_documentation,DSGAI15,DSGAI15|DSGAI01|DSGAI14|DSGAI05,LLM02:2025|LLM05:2025|LLM02:2026|LLM10:2026,custom,mcp,10,6,high,financial|pii|proprietary|telemetry|tool_output|tool_schema|user_prompt,2,https://modelcontextprotocol.io/specification/2025-06-18/server/tools,2026-08-07,mcp|tool-contract-drift|output-schema|context-window|over-sharing|telemetry-leakage +DSGAI-TRACE-overbroad-search-context-egress-self-report-gap,Over-broad search scope leaks an HR document through a full-context email the agent's own record does not mention,tool_call,unintentional_failure,hypothetical,DSGAI06,DSGAI06|DSGAI15,,custom,,7,2,high,file_path|financial|pii|retrieved_document|telemetry|token|tool_output|user_prompt,0,,2026-09-15,workspace-search|email-egress|context-oversharing|observability-gap|self-report-divergence diff --git a/datasets/exploit_dataset/croissant.json b/datasets/exploit_dataset/croissant.json new file mode 100644 index 0000000..28b70c4 --- /dev/null +++ b/datasets/exploit_dataset/croissant.json @@ -0,0 +1,327 @@ +{ + "@context": { + "@language": "en", + "@vocab": "https://schema.org/", + "citeAs": "cr:citeAs", + "column": "cr:column", + "conformsTo": "dct:conformsTo", + "cr": "http://mlcommons.org/croissant/", + "rai": "http://mlcommons.org/croissant/RAI/", + "data": { + "@id": "cr:data", + "@type": "@json" + }, + "dataType": { + "@id": "cr:dataType", + "@type": "@vocab" + }, + "dct": "http://purl.org/dc/terms/", + "equivalentProperty": "cr:equivalentProperty", + "examples": { + "@id": "cr:examples", + "@type": "@json" + }, + "extract": "cr:extract", + "field": "cr:field", + "fileProperty": "cr:fileProperty", + "fileObject": "cr:fileObject", + "fileSet": "cr:fileSet", + "format": "cr:format", + "includes": "cr:includes", + "isLiveDataset": "cr:isLiveDataset", + "jsonPath": "cr:jsonPath", + "key": "cr:key", + "md5": "cr:md5", + "parentField": "cr:parentField", + "path": "cr:path", + "recordSet": "cr:recordSet", + "references": "cr:references", + "regex": "cr:regex", + "repeated": "cr:repeated", + "replace": "cr:replace", + "samplingRate": "cr:samplingRate", + "sc": "https://schema.org/", + "separator": "cr:separator", + "source": "cr:source", + "subField": "cr:subField", + "transform": "cr:transform" + }, + "@type": "sc:Dataset", + "name": "exploit_dataset", + "description": "DSGAI Exploit Technique Dataset. Publicly documented attack techniques against GenAI systems, one technique class per entry (how an attacker does something, not a product-specific flaw), mapped to MITRE ATLAS, the DSGAI taxonomy and the OWASP Top 10 for LLM Applications. Most entries follow MITRE ATLAS techniques; the rest are research-derived technique families ATLAS does not track separately.", + "conformsTo": "http://mlcommons.org/croissant/1.1", + "citeAs": "OWASP GenAI Data Security Initiative. DSGAI Exploit Technique Dataset (version 1.0.0). OWASP GenAI Security Project. https://github.com/GenAI-Security-Project/GenAI-Data-Security-Initiative/tree/main/datasets/exploit_dataset", + "dateModified": "2026-05-18", + "datePublished": "2026-05-18", + "license": "https://creativecommons.org/licenses/by-sa/4.0/", + "rai:dataBiases": [ + "About 70% of entries come from the MITRE ATLAS catalog, so coverage follows ATLAS's own emphasis.", + "Weighted toward prompt-injection, jailbreak and poisoning techniques, which dominate the published literature." + ], + "rai:dataCollection": "Curated from the MITRE ATLAS catalog and published research (papers, vendor advisories, conference talks). Each entry cites its sources and links related vulnerability entries.", + "rai:dataCollectionType": [ + "Secondary Data analysis", + "Manual Human Curator" + ], + "rai:dataLimitations": [ + "Describes techniques at the level of public literature; it is not a playbook and omits weaponised detail.", + "ATLAS-derived entries track the ATLAS release they were written against; a monthly job flags retired IDs.", + "Severity is a qualitative judgment of the technique class, not a CVSS score." + ], + "rai:dataReleaseMaintenancePlan": "Maintained by the OWASP GenAI Data Security Initiative (Workstream 5). Contributions arrive as pull requests and must pass data_validation/run_all_checks.py in CI and peer review; weekly online checks re-verify cited CVEs, advisories and links. Versioned releases carry SHA-256 checksums.", + "rai:dataSocialImpact": "Techniques are already public; the dataset organises them for defenders. Dual-use risk is limited by keeping entries at catalog-level detail.", + "rai:dataUseCases": [ + "Red-team planning and coverage analysis of GenAI defences against known technique classes.", + "Linking techniques to concrete vulnerabilities and to DSGAI risks in threat models." + ], + "rai:personalSensitiveInformation": "No personal data.", + "url": "https://github.com/GenAI-Security-Project/GenAI-Data-Security-Initiative/tree/main/datasets/exploit_dataset", + "version": "1.0.0", + "distribution": [ + { + "@type": "cr:FileObject", + "@id": "index.csv", + "name": "index.csv", + "contentUrl": "index.csv", + "encodingFormat": "text/csv", + "sha256": "86af9661d07d15d339b760d06ddcc58b77da9a03babe9e18051688ad57b27194" + }, + { + "@type": "cr:FileObject", + "@id": "schema.json", + "name": "schema.json", + "description": "JSON Schema for the records", + "contentUrl": "schema.json", + "encodingFormat": "application/json", + "sha256": "7107fe0fcc3e0b0d7eb262cd21955c2bf6c464a49ef51808232b4537e0eb46e5" + }, + { + "@type": "cr:FileSet", + "@id": "entries/", + "name": "entries/", + "description": "One JSON record per file", + "encodingFormat": "application/json", + "includes": "entries/*.json" + } + ], + "recordSet": [ + { + "@type": "cr:RecordSet", + "@id": "index", + "name": "index", + "description": "One record per row of index.csv; list-valued columns are joined with '|'.", + "field": [ + { + "@type": "cr:Field", + "@id": "index/exploit_id", + "name": "exploit_id", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "index.csv" + }, + "extract": { + "column": "exploit_id" + } + } + }, + { + "@type": "cr:Field", + "@id": "index/title", + "name": "title", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "index.csv" + }, + "extract": { + "column": "title" + } + } + }, + { + "@type": "cr:Field", + "@id": "index/target_component", + "name": "target_component", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "index.csv" + }, + "extract": { + "column": "target_component" + } + } + }, + { + "@type": "cr:Field", + "@id": "index/qualitative_severity", + "name": "qualitative_severity", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "index.csv" + }, + "extract": { + "column": "qualitative_severity" + } + } + }, + { + "@type": "cr:Field", + "@id": "index/dsgai_mapping", + "name": "dsgai_mapping", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "index.csv" + }, + "extract": { + "column": "dsgai_mapping" + } + } + }, + { + "@type": "cr:Field", + "@id": "index/mitre_atlas_mapping", + "name": "mitre_atlas_mapping", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "index.csv" + }, + "extract": { + "column": "mitre_atlas_mapping" + } + } + }, + { + "@type": "cr:Field", + "@id": "index/owasp_llm_top10_mapping", + "name": "owasp_llm_top10_mapping", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "index.csv" + }, + "extract": { + "column": "owasp_llm_top10_mapping" + } + } + }, + { + "@type": "cr:Field", + "@id": "index/impact", + "name": "impact", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "index.csv" + }, + "extract": { + "column": "impact" + } + } + }, + { + "@type": "cr:Field", + "@id": "index/disclosure_status", + "name": "disclosure_status", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "index.csv" + }, + "extract": { + "column": "disclosure_status" + } + } + }, + { + "@type": "cr:Field", + "@id": "index/exploited_in_the_wild", + "name": "exploited_in_the_wild", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "index.csv" + }, + "extract": { + "column": "exploited_in_the_wild" + } + } + }, + { + "@type": "cr:Field", + "@id": "index/date_documented", + "name": "date_documented", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "index.csv" + }, + "extract": { + "column": "date_documented" + } + } + }, + { + "@type": "cr:Field", + "@id": "index/date_added", + "name": "date_added", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "index.csv" + }, + "extract": { + "column": "date_added" + } + } + }, + { + "@type": "cr:Field", + "@id": "index/related_vulnerabilities", + "name": "related_vulnerabilities", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "index.csv" + }, + "extract": { + "column": "related_vulnerabilities" + } + } + }, + { + "@type": "cr:Field", + "@id": "index/primary_source", + "name": "primary_source", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "index.csv" + }, + "extract": { + "column": "primary_source" + } + } + }, + { + "@type": "cr:Field", + "@id": "index/tags", + "name": "tags", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "index.csv" + }, + "extract": { + "column": "tags" + } + } + } + ] + } + ] +} diff --git a/datasets/promptinj_dataextraction_testcases/croissant.json b/datasets/promptinj_dataextraction_testcases/croissant.json new file mode 100644 index 0000000..afa584f --- /dev/null +++ b/datasets/promptinj_dataextraction_testcases/croissant.json @@ -0,0 +1,683 @@ +{ + "@context": { + "@language": "en", + "@vocab": "https://schema.org/", + "citeAs": "cr:citeAs", + "column": "cr:column", + "conformsTo": "dct:conformsTo", + "cr": "http://mlcommons.org/croissant/", + "rai": "http://mlcommons.org/croissant/RAI/", + "data": { + "@id": "cr:data", + "@type": "@json" + }, + "dataType": { + "@id": "cr:dataType", + "@type": "@vocab" + }, + "dct": "http://purl.org/dc/terms/", + "equivalentProperty": "cr:equivalentProperty", + "examples": { + "@id": "cr:examples", + "@type": "@json" + }, + "extract": "cr:extract", + "field": "cr:field", + "fileProperty": "cr:fileProperty", + "fileObject": "cr:fileObject", + "fileSet": "cr:fileSet", + "format": "cr:format", + "includes": "cr:includes", + "isLiveDataset": "cr:isLiveDataset", + "jsonPath": "cr:jsonPath", + "key": "cr:key", + "md5": "cr:md5", + "parentField": "cr:parentField", + "path": "cr:path", + "recordSet": "cr:recordSet", + "references": "cr:references", + "regex": "cr:regex", + "repeated": "cr:repeated", + "replace": "cr:replace", + "samplingRate": "cr:samplingRate", + "sc": "https://schema.org/", + "separator": "cr:separator", + "source": "cr:source", + "subField": "cr:subField", + "transform": "cr:transform" + }, + "@type": "sc:Dataset", + "name": "promptinj_dataextraction_testcases", + "description": "Prompt Injection and Data Extraction Test Cases. Adversarial prompts with expected secure and vulnerable behaviour, for red-teaming and regression testing of GenAI data-security controls. Current suites are Turkish-language: adapted cases from a public corpus, contrastive attack/benign-control pairs, and a small hand-written set with English glosses.", + "conformsTo": "http://mlcommons.org/croissant/1.1", + "citeAs": "OWASP GenAI Data Security Initiative. Prompt Injection and Data Extraction Test Cases (version 1.0.0). OWASP GenAI Security Project. https://github.com/GenAI-Security-Project/GenAI-Data-Security-Initiative/tree/main/datasets/promptinj_dataextraction_testcases", + "datePublished": "2026-03-23", + "license": [ + "https://creativecommons.org/licenses/by-sa/4.0/", + "https://creativecommons.org/licenses/by/4.0/" + ], + "rai:dataBiases": [ + "Weighted toward system-prompt extraction and direct data extraction; other categories have fewer cases.", + "Reflects the attack styles of its source corpora (authority and urgency framing, morphological and cross-lingual bypasses)." + ], + "rai:dataCollection": "Contributed suites. Most cases adapt public CC BY 4.0 corpora (attribution and source hashes are kept in each case's provenance); the adaptation adds DSGAI mappings, expected behaviours and sandbox prerequisites. A small set was written for this dataset.", + "rai:dataCollectionType": [ + "Secondary Data analysis", + "Manual Human Curator" + ], + "rai:dataLimitations": [ + "Almost entirely Turkish; results do not transfer to other languages without new cases.", + "Expected behaviours are defensive test expectations, not observed results for any model.", + "Lexical deduplication only; paraphrased near-duplicates may remain." + ], + "rai:dataReleaseMaintenancePlan": "Maintained by the OWASP GenAI Data Security Initiative (Workstream 5). Contributions arrive as pull requests and must pass data_validation/run_all_checks.py in CI and peer review; weekly online checks re-verify cited CVEs, advisories and links. Versioned releases carry SHA-256 checksums.", + "rai:dataSocialImpact": "Adversarial prompts are dual-use; they are published at the level already public in their source corpora so defenders can test non-English guardrail gaps.", + "rai:dataUseCases": [ + "Sandboxed red-team exercises and regression tests for prompt-injection and data-extraction defences.", + "Evaluating multilingual (Turkish) robustness of guardrails. Do not run against production systems." + ], + "rai:personalSensitiveInformation": "Synthetic data only: secrets and identifiers in prompts are placeholders, and cases were screened for real personal data and live-secret patterns.", + "url": "https://github.com/GenAI-Security-Project/GenAI-Data-Security-Initiative/tree/main/datasets/promptinj_dataextraction_testcases", + "version": "1.0.0", + "distribution": [ + { + "@type": "cr:FileObject", + "@id": "tr_altaysec_turkish_llm_injection/manifest.csv", + "name": "tr_altaysec_turkish_llm_injection/manifest.csv", + "contentUrl": "tr_altaysec_turkish_llm_injection/manifest.csv", + "encodingFormat": "text/csv", + "sha256": "ecb57c387e54c630a44e42c42cebd1398d5b7c92dbe4d8e88f108c6166ac4aec" + }, + { + "@type": "cr:FileObject", + "@id": "tr_turkish_conversation_prompt_injection_pairs/manifest.csv", + "name": "tr_turkish_conversation_prompt_injection_pairs/manifest.csv", + "contentUrl": "tr_turkish_conversation_prompt_injection_pairs/manifest.csv", + "encodingFormat": "text/csv", + "sha256": "0d33cf89b2bb3e136d029ff0c729539c886ee4a987fc4719f782ab7b9adc08e6" + }, + { + "@type": "cr:FileObject", + "@id": "tr_turkish_conversation_prompt_injection_pairs/contrastive_testcase.schema.json", + "name": "tr_turkish_conversation_prompt_injection_pairs/contrastive_testcase.schema.json", + "description": "JSON Schema for the records", + "contentUrl": "tr_turkish_conversation_prompt_injection_pairs/contrastive_testcase.schema.json", + "encodingFormat": "application/json", + "sha256": "de3341e66b40064629b7d60c35e094fe9a26286c697d4afe6e2b0c7b80f80f98" + }, + { + "@type": "cr:FileSet", + "@id": "tr_altayduel/cases/", + "name": "tr_altayduel/cases/", + "description": "One JSON record per file", + "encodingFormat": "application/json", + "includes": "tr_altayduel/cases/*.json" + }, + { + "@type": "cr:FileSet", + "@id": "tr_altaysec_turkish_llm_injection/cases/", + "name": "tr_altaysec_turkish_llm_injection/cases/", + "description": "One JSON record per file", + "encodingFormat": "application/json", + "includes": "tr_altaysec_turkish_llm_injection/cases/*.json" + }, + { + "@type": "cr:FileSet", + "@id": "tr_turkish_conversation_prompt_injection_pairs/cases/", + "name": "tr_turkish_conversation_prompt_injection_pairs/cases/", + "description": "One JSON record per file", + "encodingFormat": "application/json", + "includes": "tr_turkish_conversation_prompt_injection_pairs/cases/*.json" + } + ], + "recordSet": [ + { + "@type": "cr:RecordSet", + "@id": "tr_altaysec_turkish_llm_injection", + "name": "tr_altaysec_turkish_llm_injection", + "description": "One record per row of manifest.csv; list-valued columns are joined with '|'.", + "field": [ + { + "@type": "cr:Field", + "@id": "tr_altaysec_turkish_llm_injection/path", + "name": "path", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "tr_altaysec_turkish_llm_injection/manifest.csv" + }, + "extract": { + "column": "path" + } + } + }, + { + "@type": "cr:Field", + "@id": "tr_altaysec_turkish_llm_injection/testcase_id", + "name": "testcase_id", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "tr_altaysec_turkish_llm_injection/manifest.csv" + }, + "extract": { + "column": "testcase_id" + } + } + }, + { + "@type": "cr:Field", + "@id": "tr_altaysec_turkish_llm_injection/source_record_id", + "name": "source_record_id", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "tr_altaysec_turkish_llm_injection/manifest.csv" + }, + "extract": { + "column": "source_record_id" + } + } + }, + { + "@type": "cr:Field", + "@id": "tr_altaysec_turkish_llm_injection/source_prompt_hash", + "name": "source_prompt_hash", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "tr_altaysec_turkish_llm_injection/manifest.csv" + }, + "extract": { + "column": "source_prompt_hash" + } + } + }, + { + "@type": "cr:Field", + "@id": "tr_altaysec_turkish_llm_injection/adapted_prompt_sha256", + "name": "adapted_prompt_sha256", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "tr_altaysec_turkish_llm_injection/manifest.csv" + }, + "extract": { + "column": "adapted_prompt_sha256" + } + } + }, + { + "@type": "cr:Field", + "@id": "tr_altaysec_turkish_llm_injection/category", + "name": "category", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "tr_altaysec_turkish_llm_injection/manifest.csv" + }, + "extract": { + "column": "category" + } + } + }, + { + "@type": "cr:Field", + "@id": "tr_altaysec_turkish_llm_injection/dsgai_mapping", + "name": "dsgai_mapping", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "tr_altaysec_turkish_llm_injection/manifest.csv" + }, + "extract": { + "column": "dsgai_mapping" + } + } + }, + { + "@type": "cr:Field", + "@id": "tr_altaysec_turkish_llm_injection/severity", + "name": "severity", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "tr_altaysec_turkish_llm_injection/manifest.csv" + }, + "extract": { + "column": "severity" + } + } + }, + { + "@type": "cr:Field", + "@id": "tr_altaysec_turkish_llm_injection/source_severity", + "name": "source_severity", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "tr_altaysec_turkish_llm_injection/manifest.csv" + }, + "extract": { + "column": "source_severity" + } + } + }, + { + "@type": "cr:Field", + "@id": "tr_altaysec_turkish_llm_injection/language", + "name": "language", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "tr_altaysec_turkish_llm_injection/manifest.csv" + }, + "extract": { + "column": "language" + } + } + }, + { + "@type": "cr:Field", + "@id": "tr_altaysec_turkish_llm_injection/languages", + "name": "languages", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "tr_altaysec_turkish_llm_injection/manifest.csv" + }, + "extract": { + "column": "languages" + } + } + }, + { + "@type": "cr:Field", + "@id": "tr_altaysec_turkish_llm_injection/encoded_payload_language", + "name": "encoded_payload_language", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "tr_altaysec_turkish_llm_injection/manifest.csv" + }, + "extract": { + "column": "encoded_payload_language" + } + } + }, + { + "@type": "cr:Field", + "@id": "tr_altaysec_turkish_llm_injection/source_language_label", + "name": "source_language_label", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "tr_altaysec_turkish_llm_injection/manifest.csv" + }, + "extract": { + "column": "source_language_label" + } + } + }, + { + "@type": "cr:Field", + "@id": "tr_altaysec_turkish_llm_injection/technique", + "name": "technique", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "tr_altaysec_turkish_llm_injection/manifest.csv" + }, + "extract": { + "column": "technique" + } + } + }, + { + "@type": "cr:Field", + "@id": "tr_altaysec_turkish_llm_injection/scope", + "name": "scope", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "tr_altaysec_turkish_llm_injection/manifest.csv" + }, + "extract": { + "column": "scope" + } + } + }, + { + "@type": "cr:Field", + "@id": "tr_altaysec_turkish_llm_injection/source_failure_mode_review", + "name": "source_failure_mode_review", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "tr_altaysec_turkish_llm_injection/manifest.csv" + }, + "extract": { + "column": "source_failure_mode_review" + } + } + }, + { + "@type": "cr:Field", + "@id": "tr_altaysec_turkish_llm_injection/target_scope_review", + "name": "target_scope_review", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "tr_altaysec_turkish_llm_injection/manifest.csv" + }, + "extract": { + "column": "target_scope_review" + } + } + }, + { + "@type": "cr:Field", + "@id": "tr_altaysec_turkish_llm_injection/source_batch", + "name": "source_batch", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "tr_altaysec_turkish_llm_injection/manifest.csv" + }, + "extract": { + "column": "source_batch" + } + } + }, + { + "@type": "cr:Field", + "@id": "tr_altaysec_turkish_llm_injection/source_lineage", + "name": "source_lineage", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "tr_altaysec_turkish_llm_injection/manifest.csv" + }, + "extract": { + "column": "source_lineage" + } + } + }, + { + "@type": "cr:Field", + "@id": "tr_altaysec_turkish_llm_injection/anonymized", + "name": "anonymized", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "tr_altaysec_turkish_llm_injection/manifest.csv" + }, + "extract": { + "column": "anonymized" + } + } + } + ] + }, + { + "@type": "cr:RecordSet", + "@id": "tr_turkish_conversation_prompt_injection_pairs", + "name": "tr_turkish_conversation_prompt_injection_pairs", + "description": "One record per row of manifest.csv; list-valued columns are joined with '|'.", + "field": [ + { + "@type": "cr:Field", + "@id": "tr_turkish_conversation_prompt_injection_pairs/testcase_id", + "name": "testcase_id", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "tr_turkish_conversation_prompt_injection_pairs/manifest.csv" + }, + "extract": { + "column": "testcase_id" + } + } + }, + { + "@type": "cr:Field", + "@id": "tr_turkish_conversation_prompt_injection_pairs/output_file", + "name": "output_file", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "tr_turkish_conversation_prompt_injection_pairs/manifest.csv" + }, + "extract": { + "column": "output_file" + } + } + }, + { + "@type": "cr:Field", + "@id": "tr_turkish_conversation_prompt_injection_pairs/source_pair_id", + "name": "source_pair_id", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "tr_turkish_conversation_prompt_injection_pairs/manifest.csv" + }, + "extract": { + "column": "source_pair_id" + } + } + }, + { + "@type": "cr:Field", + "@id": "tr_turkish_conversation_prompt_injection_pairs/source_attack_record_id", + "name": "source_attack_record_id", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "tr_turkish_conversation_prompt_injection_pairs/manifest.csv" + }, + "extract": { + "column": "source_attack_record_id" + } + } + }, + { + "@type": "cr:Field", + "@id": "tr_turkish_conversation_prompt_injection_pairs/source_control_record_id", + "name": "source_control_record_id", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "tr_turkish_conversation_prompt_injection_pairs/manifest.csv" + }, + "extract": { + "column": "source_control_record_id" + } + } + }, + { + "@type": "cr:Field", + "@id": "tr_turkish_conversation_prompt_injection_pairs/attack_family", + "name": "attack_family", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "tr_turkish_conversation_prompt_injection_pairs/manifest.csv" + }, + "extract": { + "column": "attack_family" + } + } + }, + { + "@type": "cr:Field", + "@id": "tr_turkish_conversation_prompt_injection_pairs/source_context", + "name": "source_context", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "tr_turkish_conversation_prompt_injection_pairs/manifest.csv" + }, + "extract": { + "column": "source_context" + } + } + }, + { + "@type": "cr:Field", + "@id": "tr_turkish_conversation_prompt_injection_pairs/source_split", + "name": "source_split", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "tr_turkish_conversation_prompt_injection_pairs/manifest.csv" + }, + "extract": { + "column": "source_split" + } + } + }, + { + "@type": "cr:Field", + "@id": "tr_turkish_conversation_prompt_injection_pairs/category", + "name": "category", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "tr_turkish_conversation_prompt_injection_pairs/manifest.csv" + }, + "extract": { + "column": "category" + } + } + }, + { + "@type": "cr:Field", + "@id": "tr_turkish_conversation_prompt_injection_pairs/dsgai_mapping", + "name": "dsgai_mapping", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "tr_turkish_conversation_prompt_injection_pairs/manifest.csv" + }, + "extract": { + "column": "dsgai_mapping" + } + } + }, + { + "@type": "cr:Field", + "@id": "tr_turkish_conversation_prompt_injection_pairs/severity", + "name": "severity", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "tr_turkish_conversation_prompt_injection_pairs/manifest.csv" + }, + "extract": { + "column": "severity" + } + } + }, + { + "@type": "cr:Field", + "@id": "tr_turkish_conversation_prompt_injection_pairs/scope", + "name": "scope", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "tr_turkish_conversation_prompt_injection_pairs/manifest.csv" + }, + "extract": { + "column": "scope" + } + } + }, + { + "@type": "cr:Field", + "@id": "tr_turkish_conversation_prompt_injection_pairs/source_file", + "name": "source_file", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "tr_turkish_conversation_prompt_injection_pairs/manifest.csv" + }, + "extract": { + "column": "source_file" + } + } + }, + { + "@type": "cr:Field", + "@id": "tr_turkish_conversation_prompt_injection_pairs/source_file_sha256", + "name": "source_file_sha256", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "tr_turkish_conversation_prompt_injection_pairs/manifest.csv" + }, + "extract": { + "column": "source_file_sha256" + } + } + }, + { + "@type": "cr:Field", + "@id": "tr_turkish_conversation_prompt_injection_pairs/attack_prompt_sha256", + "name": "attack_prompt_sha256", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "tr_turkish_conversation_prompt_injection_pairs/manifest.csv" + }, + "extract": { + "column": "attack_prompt_sha256" + } + } + }, + { + "@type": "cr:Field", + "@id": "tr_turkish_conversation_prompt_injection_pairs/control_prompt_sha256", + "name": "control_prompt_sha256", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "tr_turkish_conversation_prompt_injection_pairs/manifest.csv" + }, + "extract": { + "column": "control_prompt_sha256" + } + } + }, + { + "@type": "cr:Field", + "@id": "tr_turkish_conversation_prompt_injection_pairs/case_file_sha256", + "name": "case_file_sha256", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "tr_turkish_conversation_prompt_injection_pairs/manifest.csv" + }, + "extract": { + "column": "case_file_sha256" + } + } + }, + { + "@type": "cr:Field", + "@id": "tr_turkish_conversation_prompt_injection_pairs/source_revision", + "name": "source_revision", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "tr_turkish_conversation_prompt_injection_pairs/manifest.csv" + }, + "extract": { + "column": "source_revision" + } + } + } + ] + } + ] +} diff --git a/datasets/rag_dataset/croissant.json b/datasets/rag_dataset/croissant.json new file mode 100644 index 0000000..059bf60 --- /dev/null +++ b/datasets/rag_dataset/croissant.json @@ -0,0 +1,76 @@ +{ + "@context": { + "@language": "en", + "@vocab": "https://schema.org/", + "citeAs": "cr:citeAs", + "column": "cr:column", + "conformsTo": "dct:conformsTo", + "cr": "http://mlcommons.org/croissant/", + "rai": "http://mlcommons.org/croissant/RAI/", + "data": { + "@id": "cr:data", + "@type": "@json" + }, + "dataType": { + "@id": "cr:dataType", + "@type": "@vocab" + }, + "dct": "http://purl.org/dc/terms/", + "equivalentProperty": "cr:equivalentProperty", + "examples": { + "@id": "cr:examples", + "@type": "@json" + }, + "extract": "cr:extract", + "field": "cr:field", + "fileProperty": "cr:fileProperty", + "fileObject": "cr:fileObject", + "fileSet": "cr:fileSet", + "format": "cr:format", + "includes": "cr:includes", + "isLiveDataset": "cr:isLiveDataset", + "jsonPath": "cr:jsonPath", + "key": "cr:key", + "md5": "cr:md5", + "parentField": "cr:parentField", + "path": "cr:path", + "recordSet": "cr:recordSet", + "references": "cr:references", + "regex": "cr:regex", + "repeated": "cr:repeated", + "replace": "cr:replace", + "samplingRate": "cr:samplingRate", + "sc": "https://schema.org/", + "separator": "cr:separator", + "source": "cr:source", + "subField": "cr:subField", + "transform": "cr:transform" + }, + "@type": "sc:Dataset", + "name": "rag_dataset", + "description": "RAG Poisoning and Retrieval Integrity Dataset. Synthetic documents and test fixtures for retrieval-augmented generation: poisoned documents, integrity and redaction tests, cross-tenant probes, each with expected secure and vulnerable retrieval behaviour.", + "conformsTo": "http://mlcommons.org/croissant/1.1", + "citeAs": "OWASP GenAI Data Security Initiative. RAG Poisoning and Retrieval Integrity Dataset (version 1.0.0). OWASP GenAI Security Project. https://github.com/GenAI-Security-Project/GenAI-Data-Security-Initiative/tree/main/datasets/rag_dataset", + "datePublished": "2026-03-23", + "license": "https://creativecommons.org/licenses/by-sa/4.0/", + "rai:dataBiases": "Covers one poisoning pattern (a false policy value plus a harmless canary instruction).", + "rai:dataCollection": "Written by contributors as synthetic, safe-to-ingest regression fixtures.", + "rai:dataCollectionType": "Manual Human Curator", + "rai:dataLimitations": "A single fixture so far; it demonstrates the format more than it covers the space.", + "rai:dataReleaseMaintenancePlan": "Maintained by the OWASP GenAI Data Security Initiative (Workstream 5). Contributions arrive as pull requests and must pass data_validation/run_all_checks.py in CI and peer review; weekly online checks re-verify cited CVEs, advisories and links. Versioned releases carry SHA-256 checksums.", + "rai:dataSocialImpact": "Fixtures use harmless canaries so they cannot cause harm if ingested by mistake.", + "rai:dataUseCases": "Regression tests for RAG ingestion quarantine, retrieval filtering and context resilience.", + "rai:personalSensitiveInformation": "No personal data; all content is synthetic and labelled as such in each record's metadata.", + "url": "https://github.com/GenAI-Security-Project/GenAI-Data-Security-Initiative/tree/main/datasets/rag_dataset", + "version": "1.0.0", + "distribution": [ + { + "@type": "cr:FileSet", + "@id": "entries/", + "name": "entries/", + "description": "One JSON record per file", + "encodingFormat": "application/json", + "includes": "entries/*.json" + } + ] +} diff --git a/datasets/riskassessment_dataset/croissant.json b/datasets/riskassessment_dataset/croissant.json new file mode 100644 index 0000000..b1a360c --- /dev/null +++ b/datasets/riskassessment_dataset/croissant.json @@ -0,0 +1,337 @@ +{ + "@context": { + "@language": "en", + "@vocab": "https://schema.org/", + "citeAs": "cr:citeAs", + "column": "cr:column", + "conformsTo": "dct:conformsTo", + "cr": "http://mlcommons.org/croissant/", + "rai": "http://mlcommons.org/croissant/RAI/", + "data": { + "@id": "cr:data", + "@type": "@json" + }, + "dataType": { + "@id": "cr:dataType", + "@type": "@vocab" + }, + "dct": "http://purl.org/dc/terms/", + "equivalentProperty": "cr:equivalentProperty", + "examples": { + "@id": "cr:examples", + "@type": "@json" + }, + "extract": "cr:extract", + "field": "cr:field", + "fileProperty": "cr:fileProperty", + "fileObject": "cr:fileObject", + "fileSet": "cr:fileSet", + "format": "cr:format", + "includes": "cr:includes", + "isLiveDataset": "cr:isLiveDataset", + "jsonPath": "cr:jsonPath", + "key": "cr:key", + "md5": "cr:md5", + "parentField": "cr:parentField", + "path": "cr:path", + "recordSet": "cr:recordSet", + "references": "cr:references", + "regex": "cr:regex", + "repeated": "cr:repeated", + "replace": "cr:replace", + "samplingRate": "cr:samplingRate", + "sc": "https://schema.org/", + "separator": "cr:separator", + "source": "cr:source", + "subField": "cr:subField", + "transform": "cr:transform" + }, + "@type": "sc:Dataset", + "name": "riskassessment_dataset", + "description": "DSGAI Risk Assessment Dataset. Structured risk assessments of GenAI deployment archetypes: for each representative architecture, the DSGAI risks with inherent and residual ratings and rationale, existing controls, control gaps, and alignments to security and AI-governance frameworks.", + "conformsTo": "http://mlcommons.org/croissant/1.1", + "citeAs": "OWASP GenAI Data Security Initiative. DSGAI Risk Assessment Dataset (version 1.0.0). OWASP GenAI Security Project. https://github.com/GenAI-Security-Project/GenAI-Data-Security-Initiative/tree/main/datasets/riskassessment_dataset", + "dateModified": "2026-05-18", + "datePublished": "2026-05-18", + "license": "https://creativecommons.org/licenses/by-sa/4.0/", + "rai:dataBiases": [ + "Sector coverage is uneven: cross-sector templates are the largest group, followed by financial services and SaaS; several sectors have a single template.", + "Framework alignments reflect the frameworks contributors know best." + ], + "rai:dataCollection": "Written by initiative contributors as synthetic-but-realistic templates of common deployment patterns, informed by public guidance and practitioner experience; peer reviewed.", + "rai:dataCollectionType": "Manual Human Curator", + "rai:dataLimitations": [ + "Every entry is a synthetic template of a deployment archetype, not an assessment of a real organisation.", + "Ratings and control gaps are expert judgments for the described archetype; a real deployment needs its own assessment." + ], + "rai:dataReleaseMaintenancePlan": "Maintained by the OWASP GenAI Data Security Initiative (Workstream 5). Contributions arrive as pull requests and must pass data_validation/run_all_checks.py in CI and peer review; weekly online checks re-verify cited CVEs, advisories and links. Versioned releases carry SHA-256 checksums.", + "rai:dataSocialImpact": "Lowers the cost of structured GenAI risk assessment for smaller organisations.", + "rai:dataUseCases": [ + "Starting points and worked examples for GenAI risk assessments and DSGAI training.", + "Benchmark scenarios for comparing control coverage across deployment patterns." + ], + "rai:personalSensitiveInformation": "No personal data: the scenarios are synthetic and describe archetypes, not organisations or people.", + "url": "https://github.com/GenAI-Security-Project/GenAI-Data-Security-Initiative/tree/main/datasets/riskassessment_dataset", + "version": "1.0.0", + "distribution": [ + { + "@type": "cr:FileObject", + "@id": "index.csv", + "name": "index.csv", + "contentUrl": "index.csv", + "encodingFormat": "text/csv", + "sha256": "d6b50e83d0e00b94fb2c2166c854f0a1c2cccf53c4063477d5f78d99134d7b08" + }, + { + "@type": "cr:FileObject", + "@id": "schema.json", + "name": "schema.json", + "description": "JSON Schema for the records", + "contentUrl": "schema.json", + "encodingFormat": "application/json", + "sha256": "75ae9981bc08d69ad0916706acf710946f1a892724d78ba8e0ed9f596305e79d" + }, + { + "@type": "cr:FileSet", + "@id": "entries/", + "name": "entries/", + "description": "One JSON record per file", + "encodingFormat": "application/json", + "includes": "entries/*.json" + } + ], + "recordSet": [ + { + "@type": "cr:RecordSet", + "@id": "index", + "name": "index", + "description": "One record per row of index.csv; list-valued columns are joined with '|'.", + "field": [ + { + "@type": "cr:Field", + "@id": "index/assessment_id", + "name": "assessment_id", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "index.csv" + }, + "extract": { + "column": "assessment_id" + } + } + }, + { + "@type": "cr:Field", + "@id": "index/scenario_name", + "name": "scenario_name", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "index.csv" + }, + "extract": { + "column": "scenario_name" + } + } + }, + { + "@type": "cr:Field", + "@id": "index/entry_type", + "name": "entry_type", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "index.csv" + }, + "extract": { + "column": "entry_type" + } + } + }, + { + "@type": "cr:Field", + "@id": "index/industry_sector", + "name": "industry_sector", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "index.csv" + }, + "extract": { + "column": "industry_sector" + } + } + }, + { + "@type": "cr:Field", + "@id": "index/deployment_pattern", + "name": "deployment_pattern", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "index.csv" + }, + "extract": { + "column": "deployment_pattern" + } + } + }, + { + "@type": "cr:Field", + "@id": "index/maturity_overall", + "name": "maturity_overall", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "index.csv" + }, + "extract": { + "column": "maturity_overall" + } + } + }, + { + "@type": "cr:Field", + "@id": "index/dsgai_risks", + "name": "dsgai_risks", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "index.csv" + }, + "extract": { + "column": "dsgai_risks" + } + } + }, + { + "@type": "cr:Field", + "@id": "index/highest_inherent_rating", + "name": "highest_inherent_rating", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "index.csv" + }, + "extract": { + "column": "highest_inherent_rating" + } + } + }, + { + "@type": "cr:Field", + "@id": "index/highest_residual_rating", + "name": "highest_residual_rating", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "index.csv" + }, + "extract": { + "column": "highest_residual_rating" + } + } + }, + { + "@type": "cr:Field", + "@id": "index/control_count", + "name": "control_count", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "index.csv" + }, + "extract": { + "column": "control_count" + } + } + }, + { + "@type": "cr:Field", + "@id": "index/gap_count", + "name": "gap_count", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "index.csv" + }, + "extract": { + "column": "gap_count" + } + } + }, + { + "@type": "cr:Field", + "@id": "index/immediate_gap_count", + "name": "immediate_gap_count", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "index.csv" + }, + "extract": { + "column": "immediate_gap_count" + } + } + }, + { + "@type": "cr:Field", + "@id": "index/frameworks_mapped", + "name": "frameworks_mapped", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "index.csv" + }, + "extract": { + "column": "frameworks_mapped" + } + } + }, + { + "@type": "cr:Field", + "@id": "index/compliance_obligations", + "name": "compliance_obligations", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "index.csv" + }, + "extract": { + "column": "compliance_obligations" + } + } + }, + { + "@type": "cr:Field", + "@id": "index/date_added", + "name": "date_added", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "index.csv" + }, + "extract": { + "column": "date_added" + } + } + }, + { + "@type": "cr:Field", + "@id": "index/tags", + "name": "tags", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "index.csv" + }, + "extract": { + "column": "tags" + } + } + } + ] + } + ] +} diff --git a/datasets/vulnerability_dataset/croissant.json b/datasets/vulnerability_dataset/croissant.json new file mode 100644 index 0000000..69839cf --- /dev/null +++ b/datasets/vulnerability_dataset/croissant.json @@ -0,0 +1,329 @@ +{ + "@context": { + "@language": "en", + "@vocab": "https://schema.org/", + "citeAs": "cr:citeAs", + "column": "cr:column", + "conformsTo": "dct:conformsTo", + "cr": "http://mlcommons.org/croissant/", + "rai": "http://mlcommons.org/croissant/RAI/", + "data": { + "@id": "cr:data", + "@type": "@json" + }, + "dataType": { + "@id": "cr:dataType", + "@type": "@vocab" + }, + "dct": "http://purl.org/dc/terms/", + "equivalentProperty": "cr:equivalentProperty", + "examples": { + "@id": "cr:examples", + "@type": "@json" + }, + "extract": "cr:extract", + "field": "cr:field", + "fileProperty": "cr:fileProperty", + "fileObject": "cr:fileObject", + "fileSet": "cr:fileSet", + "format": "cr:format", + "includes": "cr:includes", + "isLiveDataset": "cr:isLiveDataset", + "jsonPath": "cr:jsonPath", + "key": "cr:key", + "md5": "cr:md5", + "parentField": "cr:parentField", + "path": "cr:path", + "recordSet": "cr:recordSet", + "references": "cr:references", + "regex": "cr:regex", + "repeated": "cr:repeated", + "replace": "cr:replace", + "samplingRate": "cr:samplingRate", + "sc": "https://schema.org/", + "separator": "cr:separator", + "source": "cr:source", + "subField": "cr:subField", + "transform": "cr:transform" + }, + "@type": "sc:Dataset", + "name": "vulnerability_dataset", + "description": "DSGAI Vulnerability Dataset. Publicly disclosed vulnerabilities in LLM and GenAI applications (CVE-tracked issues and significant published research disclosures), each mapped to the OWASP GenAI Data Security (DSGAI) risk taxonomy, the OWASP Top 10 for LLM Applications (2025 and 2026 editions), CWE and CVSS.", + "conformsTo": "http://mlcommons.org/croissant/1.1", + "citeAs": "OWASP GenAI Data Security Initiative. DSGAI Vulnerability Dataset (version 1.0.0). OWASP GenAI Security Project. https://github.com/GenAI-Security-Project/GenAI-Data-Security-Initiative/tree/main/datasets/vulnerability_dataset", + "dateModified": "2026-05-18", + "datePublished": "2026-05-18", + "license": "https://creativecommons.org/licenses/by-sa/4.0/", + "rai:dataBiases": [ + "Skews toward open-source Python LLM frameworks and inference servers (agent frameworks are about half of the entries), because CVE assignment concentrates there; closed SaaS assistants appear only through public research disclosures.", + "Skews toward High and Critical severity: low-severity issues are rarely publicised or assigned CVEs.", + "Disclosure dates cluster in 2023-2025, the period the corpus was assembled for." + ], + "rai:dataCollection": "Curated by initiative contributors from public sources: NVD and CVE records, vendor and GitHub security advisories, and peer-reviewed or widely cited research. Every entry cites its sources; CVSS vectors and scores are taken from NVD or the assigning CNA.", + "rai:dataCollectionType": [ + "Secondary Data analysis", + "Manual Human Curator" + ], + "rai:dataLimitations": [ + "Covers only publicly disclosed issues; undisclosed and vendor-internal vulnerabilities are absent by design.", + "Not exhaustive: a curated sample, not a census of GenAI CVEs. Absence of a product does not imply it is secure.", + "DSGAI and OWASP mappings are expert judgments reviewed by peers, not mechanically derived." + ], + "rai:dataReleaseMaintenancePlan": "Maintained by the OWASP GenAI Data Security Initiative (Workstream 5). Contributions arrive as pull requests and must pass data_validation/run_all_checks.py in CI and peer review; weekly online checks re-verify cited CVEs, advisories and links. Versioned releases carry SHA-256 checksums.", + "rai:dataSocialImpact": "Helps defenders prioritise GenAI data-security controls. All issues are already public, so the dataset adds aggregation and mapping rather than new attack capability.", + "rai:dataUseCases": [ + "Mapping real GenAI vulnerabilities to DSGAI risks for threat modelling and control prioritisation.", + "Evaluation and regression data for GenAI security scanners and LLM-application security reviews.", + "Not intended for exploit development; entries describe issues at advisory level of detail." + ], + "rai:personalSensitiveInformation": "No personal data. Entries describe software vulnerabilities and cite public advisories; researcher names appear only where a cited public source credits them.", + "url": "https://github.com/GenAI-Security-Project/GenAI-Data-Security-Initiative/tree/main/datasets/vulnerability_dataset", + "version": "1.0.0", + "distribution": [ + { + "@type": "cr:FileObject", + "@id": "index.csv", + "name": "index.csv", + "contentUrl": "index.csv", + "encodingFormat": "text/csv", + "sha256": "649a48d9f4621e5bc7cb49244a6f52e3495cbe62965d25daf24592a035df16a5" + }, + { + "@type": "cr:FileObject", + "@id": "schema.json", + "name": "schema.json", + "description": "JSON Schema for the records", + "contentUrl": "schema.json", + "encodingFormat": "application/json", + "sha256": "fb0a838b4d7c3ca54b240d1ed0281ec8c995ff334dd1c9528e3dad4bf74d3dea" + }, + { + "@type": "cr:FileSet", + "@id": "entries/", + "name": "entries/", + "description": "One JSON record per file", + "encodingFormat": "application/json", + "includes": "entries/*.json" + } + ], + "recordSet": [ + { + "@type": "cr:RecordSet", + "@id": "index", + "name": "index", + "description": "One record per row of index.csv; list-valued columns are joined with '|'.", + "field": [ + { + "@type": "cr:Field", + "@id": "index/vulnerability_id", + "name": "vulnerability_id", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "index.csv" + }, + "extract": { + "column": "vulnerability_id" + } + } + }, + { + "@type": "cr:Field", + "@id": "index/title", + "name": "title", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "index.csv" + }, + "extract": { + "column": "title" + } + } + }, + { + "@type": "cr:Field", + "@id": "index/affected_component", + "name": "affected_component", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "index.csv" + }, + "extract": { + "column": "affected_component" + } + } + }, + { + "@type": "cr:Field", + "@id": "index/qualitative_severity", + "name": "qualitative_severity", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "index.csv" + }, + "extract": { + "column": "qualitative_severity" + } + } + }, + { + "@type": "cr:Field", + "@id": "index/cvss_v3_score", + "name": "cvss_v3_score", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "index.csv" + }, + "extract": { + "column": "cvss_v3_score" + } + } + }, + { + "@type": "cr:Field", + "@id": "index/cve_id", + "name": "cve_id", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "index.csv" + }, + "extract": { + "column": "cve_id" + } + } + }, + { + "@type": "cr:Field", + "@id": "index/dsgai_mapping", + "name": "dsgai_mapping", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "index.csv" + }, + "extract": { + "column": "dsgai_mapping" + } + } + }, + { + "@type": "cr:Field", + "@id": "index/owasp_llm_top10_mapping", + "name": "owasp_llm_top10_mapping", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "index.csv" + }, + "extract": { + "column": "owasp_llm_top10_mapping" + } + } + }, + { + "@type": "cr:Field", + "@id": "index/cwe_ids", + "name": "cwe_ids", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "index.csv" + }, + "extract": { + "column": "cwe_ids" + } + } + }, + { + "@type": "cr:Field", + "@id": "index/disclosure_status", + "name": "disclosure_status", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "index.csv" + }, + "extract": { + "column": "disclosure_status" + } + } + }, + { + "@type": "cr:Field", + "@id": "index/exploit_available", + "name": "exploit_available", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "index.csv" + }, + "extract": { + "column": "exploit_available" + } + } + }, + { + "@type": "cr:Field", + "@id": "index/date_reported", + "name": "date_reported", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "index.csv" + }, + "extract": { + "column": "date_reported" + } + } + }, + { + "@type": "cr:Field", + "@id": "index/date_added", + "name": "date_added", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "index.csv" + }, + "extract": { + "column": "date_added" + } + } + }, + { + "@type": "cr:Field", + "@id": "index/primary_source", + "name": "primary_source", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "index.csv" + }, + "extract": { + "column": "primary_source" + } + } + }, + { + "@type": "cr:Field", + "@id": "index/tags", + "name": "tags", + "dataType": "sc:Text", + "source": { + "fileObject": { + "@id": "index.csv" + }, + "extract": { + "column": "tags" + } + } + } + ] + } + ] +}