Skip to content

Commit e4a3c1b

Browse files
committed
add tool assessment type
Signed-off-by: JosephKyser <josephkyserjr@gmail.com>
1 parent a3a6254 commit e4a3c1b

1 file changed

Lines changed: 286 additions & 0 deletions

File tree

spec/predicates/tool-assessment.md

Lines changed: 286 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,286 @@
1+
# Predicate type: Tool Assessment
2+
3+
Type URI: https://in-toto.io/attestation/tool-assessment/v0.1
4+
5+
Version: v0.1.0
6+
7+
## Purpose
8+
9+
**The tool assessment attestation references the results and metadata associated with tools used to assess software before or after its creation.** It's primary purpose is to provide an immutable attestation of tool assessment of a software so that it can be bundled with its provenance. This enables to mapping of build provenances to assessments on a per build basis and can reflect entire DevSecOps pipeline processes.
10+
11+
However, this attestation can be used to describe the assessment of any target using any tool for any purpose and is not restricted to pipelines.
12+
13+
There are many existing predicates that describe the use of specific tool types. While these predicates are well defined, they are narrowly scoped. There should exist a predicate that is general enough to effectively attest the use of any tool that can be used if a tool type does not have a predicate type yet. The tool assessment attestation type aims to solve this.
14+
15+
- The [cyclonedx](cyclonedx.md) and [spdx](spdx.md) predicate types describe SBOM standards.
16+
- The [test result](test-result.md) predicate type describes test running tests in the software supply chain.
17+
- The [vulnerabilities](vulns_02.md) predicate type describes the results of a vulnerability scan. This predicate closely resembles the type of information desired to be captured by the tool assessment attestation but is too narrowly scoped to producers of vulnerability information.
18+
- The [SCAI](scai.md) predicate type captures functional attribute and integrity information about software and its supply chain. It is the closest predicate for this use-case but fails to cleanly map a result to its tooling while providing appropriate metadata on the tooling or the policy requiring its execution. The tool assessment attestation would serve well as an attribute predicate in the SCAI framework.
19+
20+
Prior existing predicates still have their own important use-cases. This predicate type does not aim to replace them but to provide a specification flexible enough to use for any type of tool.
21+
22+
## Use Cases
23+
24+
### Control Gates
25+
26+
Control gates are an essential and increasingly prevalent requirement in many
27+
DevSecOps pipelines where continuous integration is adopted as a standard of
28+
assessment for a piece of software to be deployed and operated.
29+
Tool assessment attestations enable security control assessors to audit compliance to policy in an immutable format.
30+
31+
### Policy as Code Enabling via Attachment to Build Artifacts
32+
33+
Tool assessment attestations bundled with container build provenance can enable policy-as-code enforcement of containers or software on IT systems.
34+
35+
## Prerequisites
36+
37+
- [in-toto Attestation Framework](https://github.com/in-toto/attestation/blob/main/spec/README.md)
38+
- Appropriate knowledge in capturing tool metadata and processing results
39+
40+
## Model
41+
42+
This predicate type is based on three parts: describing the tool, its configuration, and the results of the tool. Due to the generalness of the predicate, some fields will be optional. The `summary` field is included as a non-prescribed object for producers to include more specific data to be attested to from the ran tool.
43+
44+
This also defines the `Profile` object type.
45+
46+
## Schema
47+
48+
```jsonc
49+
{
50+
// Standard attestation fields:
51+
"_type": "https://in-toto.io/Statement/v1",
52+
"subject": [{ ... }],
53+
54+
// Predicate:
55+
"predicateType": "https://in-toto.io/attestation/tool-assessment/v1",
56+
"predicate": {
57+
"tool": {
58+
"name": "<NAME>",
59+
"type": "<TOOL_DESCRIPTION>",
60+
"uri": "<URI>",
61+
"version": "<VERSION>"
62+
},
63+
"config": {
64+
"profiles": [ Profile ],
65+
"exclusions": ["<EXCLUSIONS>"],
66+
"files": [ ResourceDescriptor ], // .ignores, config files, etc
67+
"full_command": "<FULL_CMD_LINE>"
68+
},
69+
"result": "<RESULT>",
70+
"output": [ ResourceDescriptor ],
71+
"summary": { /* object */ },
72+
}
73+
}
74+
75+
// Profile Object Type
76+
Profile: {
77+
"profile": "<PROFILE_NAME_OR_DECRIPTION>",
78+
"uri": "<PROFILE_URI>",
79+
"version": "<VERISON>",
80+
"last_updated": "<TIME_STAMP>",
81+
"annotations": { /* object */ }
82+
}
83+
84+
```
85+
86+
### Parsing Rules
87+
88+
- Consumers MUST ignore unrecognized fields unless otherwise noted.
89+
- Acceptable formats of the `summary` and `annotations` fields are up to the producer and consumer.
90+
91+
### Fields
92+
93+
**tool, required** object
94+
95+
> Object associated with identifying the tool.
96+
97+
**tool.name, required** string
98+
99+
>> Name of tool.
100+
101+
**tool.type, required** string
102+
103+
>> Description of the type of tool (SAST, DAST, SECRETS, etc).
104+
105+
**tool.uri, required** string (ResourceURI)
106+
107+
>> URI indicating the identity of the source of the tool.
108+
109+
**tool.version, optional** string
110+
111+
>> Version of the tool.
112+
113+
**config, required** object
114+
115+
> Object that describes the configuration of the tool.
116+
> This object should be descriptive enough to reproduce the results of the tool based on its entries.
117+
118+
**config.profiles, optional** Profile list
119+
120+
>> Contains a list of profiles used in the tool. Profiles describe the set of data that the tool references in its execution that may modify the behavior of the tool or its results. This includes: rulesets, databases, policies, etc.
121+
122+
**config.exclusions, optional** string list
123+
124+
>> List of deviations from the profile, such as rule IDs, file names, ignores, etc.
125+
126+
**config.files, optional** ResourceDescriptor list
127+
128+
>> Reference to files used by the tool to modify configuration.
129+
130+
**config.full_command, required** string
131+
132+
>> Command used to run the tool.
133+
134+
**result, required** string
135+
136+
> Result of the tool execution. Usually `PASS` or `FAIL`.
137+
138+
**output, required** ResourceDescriptor list
139+
140+
> Artifacts associated with the result of the execution of the tool.
141+
142+
**summary, optional** object
143+
144+
> Object containing extra fields associated with the execution of the tool that contribute to the understanding of a tools results. Acceptable formats are up to the producer and consumer of the attestation.
145+
146+
---
147+
148+
**Profile.profile, required** string
149+
150+
>> Name or description of the profile.
151+
152+
**Profile.uri, required** string
153+
154+
>> URI identifying the source of the profile
155+
156+
**Profile.version, optional** string
157+
158+
>> Version of the profile
159+
160+
**Profile.last_updated, optional** string
161+
162+
>> Timestamp of the last update of the profile
163+
164+
**Profile.annoations, optional** object
165+
166+
>> Extraneous data associated with the tool assessment.
167+
168+
## Example
169+
170+
### Semgrep
171+
172+
```jsonc
173+
{
174+
"_type": "https://in-toto.io/Statement/v1",
175+
"subject": [{
176+
"name": "foo",
177+
"digest": { "sha256": "78ec328..." }
178+
}],
179+
"predicateType": "https://in-toto.io/attestation/tool-assessment/v0.1",
180+
"predicate": {
181+
"tool": {
182+
"name": "Semgrep",
183+
"type": "SAST",
184+
"uri": "pkg:github/semgrep/semgrep@984f760",
185+
"version": "1.139.0"
186+
},
187+
"config": {
188+
"profiles": [
189+
{
190+
"profile": "Default Python",
191+
"uri": "https://semgrep.dev/p/python"
192+
},
193+
{
194+
"profile": "Community Python",
195+
"uri": "https://github.com/semgrep/semgrep-rules/tree/d375208f04370b4e8d3ca7fe668db6f0465bb643/python",
196+
"last_updated": "2025-06-04T19:25:00Z"
197+
}],
198+
"exclusions": ["bar.py"],
199+
"full_command": "semgrep scan --config p/python --config rules/python --exclude='bar.py'"
200+
},
201+
"result": "PASS",
202+
"output": ["<ResourceDescriptor(semgrep_output.txt)>"]
203+
}
204+
}
205+
```
206+
207+
### Trufflehog
208+
209+
```jsonc
210+
{
211+
"_type": "https://in-toto.io/Statement/v1",
212+
"subject": [{
213+
"name": "foo",
214+
"digest": { "sha256": "78ec328..." }
215+
}],
216+
"predicateType": "https://in-toto.io/attestation/tool-assessment/v0.1",
217+
"predicate": {
218+
"tool": {
219+
"name": "Trufflehog",
220+
"type": "Secrets Scanning",
221+
"uri": "pkg:github/trufflesecurity/trufflehog@466da4b",
222+
"version": "3.90.8"
223+
},
224+
"config": {
225+
"profiles": [
226+
{
227+
"profile": "Custom",
228+
"uri": "https://example.com/trufflehog_config.yml",
229+
"last_updated": "2025-06-04T19:25:00Z"
230+
}],
231+
"exclusions": ["excluded_files.txt"],
232+
"files": [
233+
"<ResourceDescriptor(trufflehog_config.yml)>",
234+
"<ResourceDescriptor(excluded_files.txt)>"
235+
],
236+
"full_command": "trufflehog --config=trugglehog_config.yml --no-update git file://. --exclude-paths='excluded_files.txt' --json > th.json"
237+
},
238+
"result": "PASS",
239+
"output": ["<ResourceDescriptor(th.json)>"]
240+
}
241+
}
242+
```
243+
244+
### OpenSCAP
245+
246+
```jsonc
247+
{
248+
"_type": "https://in-toto.io/Statement/v1",
249+
"subject": [{
250+
"name": "foo",
251+
"digest": { "sha256": "78ec328..." }
252+
}],
253+
"predicateType": "https://in-toto.io/attestation/tool-assessment/v0.1",
254+
"predicate": {
255+
"tool": {
256+
"name": "Openscap",
257+
"type": "STIG Compliance Scan",
258+
"uri": "pkg:github/OpenSCAP/openscap@e9b2a41",
259+
"version": "1.4.2"
260+
},
261+
"config": {
262+
"profiles": [
263+
{
264+
"profile": "Ubuntu",
265+
"uri": "https://example.com/1.3/xccdf_ubuntu_profile.xml",
266+
"last_updated": "2025-06-04T19:25:00Z",
267+
"version": "v1.3"
268+
}],
269+
"files": ["<ResourceDescriptor(xccdf_ubuntu_profile.xml)>"],
270+
"full_command": "oscap xccdf eval --profile Ubuntu --results xccdf-results.xml xccdf_ubuntu_profile.xml"
271+
},
272+
"result": "PASS",
273+
"output": ["<ResourceDescriptor(xccdf-results.xml)>"],
274+
"summary": {
275+
"score": 98,
276+
"total": 214,
277+
"pass": 21,
278+
"fail": 2,
279+
"not_checked": 3,
280+
"not_applicable": 188
281+
}
282+
}
283+
}
284+
```
285+
286+
## Changelog and Migrations

0 commit comments

Comments
 (0)