Repository navigation
Pin the OCSF mapping to 1.9.0 and use OCSF's class names - #258
Conversation
Bar decided on #121 to pin OCSF 1.9.0 and use OCSF's own captions. Class 5001 is "Device Inventory Info" and 6002 is "Application Lifecycle" at every OCSF release, so the agbom/* rows and the five 6002 rows were mislabeled. The class numbers already meant these classes, so only the names change. OCSF requires activity_id on every event, and steps/skillRegister, agbom/snapshot and agbom/changed had none. They take 2 (Collect), the closer fit of 5001's two activities for a registration and a snapshot. The skillRegister note no longer names the old caption. Detection Finding calls its finding object finding_info, which the deny example already uses, so decision_class.required_fields now names it. evidences and verdict_id stay for #228, and the allow sentence stays for #198. The docs pin 1.9.0 everywhere they said 1.5+, including the unmapped.acs note and metadata.version in the three examples. The 2004 and 5001 examples also gain the type_uid, metadata.product and device.type_id that the 1.9.0 validator requires. The 1007 example still lacks device, which is the class-fit question in #235. Signed-off-by: Rock Lambros <rock@rockcyber.com>
|
This pull request's description says it closes #121, which is on the project roadmap. When it merges, GitHub closes that issue and the roadmap counts it as delivered. Please confirm the change delivers the whole issue before merging. |
| "type": "array", | ||
| "items": { "type": "string" }, | ||
| "default": ["finding.title", "finding.uid", "evidences", "verdict_id"] | ||
| "default": ["finding_info", "evidences", "verdict_id"] |
There was a problem hiding this comment.
@rocklambros just noting that this drops the title: finding.title was required before, and finding_info alone doesn't require one (OCSF only recommends title). Not dramatic, but not sure it's intended.
There was a problem hiding this comment.
Good catch, that wasn't intended. finding_info.title is back in required_fields in 79407d9, so the title stays required the way finding.title was.
finding.title was required before the move to finding_info, and OCSF only recommends finding_info.title, so the mapping lists it explicitly. Signed-off-by: rocklambros <rock@rockcyber.com>
|
Merged with the admin bypass. @bar-capsule approved |
The embedded schemas follow integration after GenAI-Security-Project#63, GenAI-Security-Project#258 and GenAI-Security-Project#261. The parity recording stores the git object IDs of the deciding TypeScript paths instead of a commit, so a squash merge no longer makes TestRecordingIsCurrent fail. The paths include agt.lock and the agt-bridge package.json, which pin the AGT commit and SDK. The recorder and the test read them from one list; the test fails when the recording names other paths or was made from another corpus, and the recorder refuses uncommitted changes to them. A test checks that the Go workflow runs on every deciding path. agt/README.md tells a TypeScript contributor when to re-record. A test requires agt-native.lock and agt.lock to pin the same AGT repo and commit. The native build fails when AGT at that commit changes ffi.rs, which agteval/acs.h is written from, or fetches another opa than agt-native.lock pins. Under the agt evaluator, policy.opa_timeout must be shorter than protocol.decision_timeout; guardian.yaml ships 4s. Otherwise a slow opa lets the agent stop waiting before AGT's deny arrives (GenAI-Security-Project#269). make load measures either evaluator under concurrent clients, selected by EVALUATOR like the other targets. Under agt each decision runs one opa process; on a 20-core host decisions stop rising near 16 concurrent ones, and at 256 they reach the 5s timeout. guardian.yaml now ships limits.max_engine_calls 32, and docs/load.md records the results. The load run found that an engine call gave its slot back only after its answer was sent, so a client's next step could be refused engine_saturated with no call running; callEngine now releases the slot first, also after a panic. When the host adapter's audit log cannot be written, the record goes to stderr as one JSON line with the final disposition, and the refusal's reasoning says whether the record went to stderr or nowhere. The audit file's close error now counts. The Codex and OpenCode hooks pass their own stderr. The §6.3 row says that ALLOW at a hook that permits no DENY is an interpretation (GenAI-Security-Project#270), and the docs say only the adapter library reaches those hooks. Dependabot proposes Go updates, one pull request per dependency across both modules. The Go workflow runs weekly, so govulncheck sees advisories for the toolchain that Dependabot does not move, triggers on the agt-bridge package.json, and no longer fetches full history. A test checks that the method table permits DENY exactly where hooks.md does, and fails on a Decision line it cannot classify. The coverage floor counts every package except commands, examples and test helpers. The Guardian meets the expectations GenAI-Security-Project#256 sets for reference implementations, mapped to tests in docs/conformance.md. audit.max_file_bytes and audit.max_files rotate each audit file; guardian.yaml keeps at most 1 GiB per log; max_file_bytes needs max_files of at least 1, so a rotation never deletes the live log. make load can set the rotation and fails if the log drops, splits or reorders a record or exceeds its bound; docs/load.md records a run and the cost of long sessions. storage.provider names the session store. The HMAC secret file holds base64 of at least 32 bytes. key_id is a configured label with no default, an unknown key_id is refused (GenAI-Security-Project#118, GenAI-Security-Project#272), and the hooks and the conformance harness take it as a flag. A toolCallResult whose request_id_ref matches no request is recorded (GenAI-Security-Project#272). Decisions from other pull requests that the Go code contradicted: - A shell command's URL ends only at ASCII whitespace; U+FEFF or U+00A0 in the userinfo no longer hides the host curl reaches (GenAI-Security-Project#268). - Versions are compatible when they share X.Y under 0.x; the handshake negotiates only such a version, and a step must match it (GenAI-Security-Project#196, GenAI-Security-Project#255). - A policy target that is not a string is denied evaluation_failed; the TypeScript fix is in GenAI-Security-Project#229, so two recorded cases are listed as ahead of the recording until it is re-recorded. - The host adapter records every decision failure under either posture, with its class, handshake failures included (GenAI-Security-Project#37). - The host adapter denies under any posture a signed error other than -32603, an unverified answer and a malformed answer; the docs mark this as an interpretation of §6.4 ahead of GenAI-Security-Project#32, which is open. The version rule is marked the same way against §3. - The audit directory is 0700; a symlinked audit path or an audit file open to group or others is refused (GenAI-Security-Project#71). Claude-Session: https://claude.ai/code/session_01DFdYnoBitHhPcUSq7wMWs1 Signed-off-by: Konstantin Trunin <konstantin@trunin.com>
What changed
ocsf-mapping.jsonnow pins OCSF 1.9.0 and uses OCSF's own class captions, as Bar decided on #121. Class 5001 is "Device Inventory Info" and 6002 is "Application Lifecycle" at every OCSF release, so theagbom/*rows and the five 6002 rows were mislabeled. The class numbers already meant these classes, so only the names change.steps/skillRegister,agbom/snapshotandagbom/changedgain"activity_id": 2(Collect), because OCSF requiresactivity_idon every event.decision_class.required_fieldsnamesfinding_info, the object Detection Finding defines, in place offinding.titleandfinding.uid. The class tables and examples inevents.mdandextend_ocsf.mdfollow.Reviewers are @bar-capsule, @afogel and @artmaro, and one approval lands this. Bar and Ariel lead the Spec workstream, so the proposals below need an answer from one of them first. After that, any one of the three can approve.
Which issue does this implement
Closes #121
Base branch
integration, because this touches the specification, schemas, a reference implementation, an adapter, tests, or CImain, because every changed path is on the documentation lane allowlist in CONTRIBUTING.mdType of change
Specification changes
Breaking for implementers? Only for a deployment that copied the old captions into
class_name. Everyclass_uidis unchanged. A deployment emitting OCSF forsteps/skillRegisteroragbom/*should now setactivity_id2, which OCSF already required.No Discussion was opened. The decisions are on #121.
Decided by a Spec lead. Bar's decision (6059681393) covers the 1.9.0 pin, the 5001 and 6002 captions, the version strings, and
finding_infoinrequired_fields.Proposed by me, for a Spec lead to confirm. My notes on #121 (6117227902) add two things Bar's list does not include.
steps/skillRegister,agbom/snapshotandagbom/changedgetactivity_id2 (Collect), because OCSF requires anactivity_idand 5001 offers only 1 (Log) and 2 (Collect). TheskillRegisternote no longer says "modeled as Inventory Info". Please say if you'd rather have 1 (Log).I ran the three examples in
extend_ocsf.mdonce, by hand, throughhttps://schema.ocsf.io/api/v2/validate, which validated against its default schema version, 1.9.0. That check does not look insideunmapped, and nothing in CI repeats it. Before this change, each failed on missing required attributes and warned about the 1.5.0 version. The 5001 example also warned about its caption. After it, the deny example (2004) and the AgBOM example (5001) validate with no errors or warnings. They gainedtype_uid, plusmetadata.productanddevice.type_idon the 5001 example. The tool call example (1007) still fails on one error, a missingdevice. That is the class-fit problem in #235, so it stays open there.Not changed
allowsentence indecision_class.descriptionstays for [Docs] Trace events page omits the OCSF class for allow that ocsf-mapping.json defines #198.evidencesandverdict_idindecision_class.required_fieldsstay for [Bug]: acs.decision trace event cannot carry reason_codes, policy_references, cited_provenance_ids, or chain_hash, so replay from the trace alone is not possible #228, which decides what goes in them.docs/acs.mdandimplementation_examples.mdstay for [Docs] OCSF examples in acs.md and implementation_examples.md contradict the normative mapping #234.activity_id(the 6002, 1007 and 6005 rows) belong with [Bug] ACS events can't fill the fields their OCSF classes require #235. Application Lifecycle's activities are install, remove, start, stop and similar, which a user message does not fit. Choosing an id there is a class-fit decision, not a rename.Merging
Signed-off-bylines. The repository squashes with the PR body by default, which drops the sign-off.cd reference-implementations/agt-go && go generate ./internal/schemaand commit the result to this branch before merging.I tested this
uv run pytest -vpasses on my machineuv run mkdocs build --strictpasses on my machinepytest reports 907 passed and 1 skipped. The hook taxonomy guard passes unchanged, because no
steps/*key changes.Checklist
git commit -s(required by the DCO)Security