tl;dr
ATT&CK techniques are useful, but they are not enough on their own.
The missing layer is often the procedure: the concrete way a technique is executed in a real environment.
If you have not read Using Attack Flow to Model the Procedure Layer Missing in ATT&CK, read that first.
This post picks up from there and focuses on the next question: if procedures matter this much, what should a STIX procedure object actually look like?
In this post
This post is narrower than the earlier one.
We’ll cover:
- why Attack Flow was the right first answer, but not the whole answer
- what role a
procedureobject should play in STIX - what should and should not live on that object
- how the schema could look in
stix2extensions - how a
procedureobject would link to the rest of the graph
Quick recap
The earlier post made the operational case for procedures.
The short version is this:
- ATT&CK techniques classify behavior
- procedures describe how that behavior is actually executed
- Attack Flow gives us a strong way to model procedure sequence
That solved the first problem.
It gave us a structured way to represent procedures without inventing a new STIX object too early.
This post starts where that one stopped.
The question now is not “do procedures matter?”
The question is “what should the STIX object for a procedure actually be?”
Making it real
The next question is practical: if we want procedures in STIX, what should the object actually be?
The wrong move here is jumping straight into a schema.
Before building a procedure object, there are a few design questions to answer first.
1) Does this need a new object at all?
Attack Flow already gives us a good way to model procedural sequence through:
attack-flowattack-actionattack-conditionattack-operatorattack-asset
That means a new procedure object should not exist just to duplicate Attack Flow.
If it exists, it needs a different purpose.
I still think that was the right first move.
It gave us a structured way to represent procedure logic without inventing a new STIX object too early.
But it also falls short in a few important ways, and those limitations are exactly why I think a separate procedure object is worth considering.
Attack Flow is very good at expressing:
- execution sequence
- branching logic
- command context
- asset context
What it is less good at expressing is a stable, reusable unit of tradecraft that can be referenced across many places without dragging a whole flow graph with it.
If I want to answer questions like:
- what procedures do we already know?
- which reports reference the same procedure?
- which detections map to that procedure family?
- which adversaries or malware families reuse that procedure?
Attack Flow alone starts to feel too low-level for that job.
It gives me the path, but not quite the catalogue entry.
An Attack Flow is often the best representation of how a procedure unfolds.
But it is not always the best representation of the procedure as a reusable intelligence object in its own right.
The most useful role would be a stable summary object: something that names a recognisable procedural pattern, links it to ATT&CK techniques, and points to related flows, detections, reports, and controls.
In other words:
- Attack Flow models the sequence
- a procedure object identifies the tradecraft pattern
That is cleaner than trying to force one object to do both.
2) What is the unit of meaning?
This is the hardest design question.
Is a procedure one command chain? One attacker playbook? One environment-specific implementation of a technique? One family of related tradecraft?
If the object is too broad, it becomes another name for an ATT&CK technique.
If it is too narrow, it becomes incident evidence rather than reusable intelligence.
I think the right unit is: a recognisable procedural pattern that is operationally specific, but still reusable across multiple incidents.
For example:
- too broad:
Inhibit System Recovery - too narrow:
vssadmin delete shadows /all /quiet executed on SERVER-19 at 02:13 UTC - probably right:
Shadow copy deletion via vssadmin before ransomware deployment on backup infrastructure
That middle version is specific enough to matter, but still abstract enough to reuse.
3) What kind of STIX object should it be?
I think this should be a new SDO, not an SCO and not just a property extension.
A procedure is not an observable like a process, a file, or an IP address.
It also has its own relationships and lifecycle, which makes it awkward as just an extra property on another object.
So if this gets implemented, it wants to be a new top-level object, something like: procedure
That also aligns well with the stix2extensions workflow, where a proper schema and extension-definition can make the object shareable by default.
4) What should actually live on the object?
This is where restraint matters.
If the object tries to carry everything, it becomes a bad clone of Attack Flow, ATT&CK, indicator, and observed-data all at once.
At minimum, I think a procedure object would need:
namedescription- an
objectiveor intended effect - a
procedure_contextor scope field - a way to capture known
variants
Potentially useful additions:
preconditionsrequired_permissionstargeted_asset_typesdetection_notescommand_line_refto a STIXprocessobject for representative command context
But I would avoid putting detailed sequence logic directly onto the object.
That belongs in Attack Flow.
The procedure object should summarise the pattern.
Attack Flow should model how it unfolds.
5) How should it relate to ATT&CK?
This is the core relationship.
A procedure object should sit underneath ATT&CK techniques, not replace them.
One procedure may implement:
- one ATT&CK technique in a specific way
- several ATT&CK techniques as part of a single operational pattern
- a threat-specific variant of well-known ATT&CK behavior
So the object should link cleanly to ATT&CK attack-pattern objects using standard STIX relationships wherever possible.
That keeps the meaning clear:
- ATT&CK technique = category of behavior
- procedure = concrete operational realization of that behavior
6) What should not live on the object?
I would avoid putting these directly on a procedure object:
- raw telemetry
- one-off incident evidence
- full branching logic
- embedded detection rules
- embedded defensive controls
STIX already has better homes for those:
observed-datafor evidenceindicatorfor detection logiccourse-of-actionfor controls- Attack Flow objects for sequence and conditions
The procedure object should be the stable tradecraft layer that ties these together, not the place where all of them get flattened.
7) What would make it reusable?
If this is built with stix2extensions, the design should optimise for reuse from day one.
That means:
- clear property descriptions and examples
- narrow, defensible semantics for each field
- relationship-first modeling instead of giant embedded blobs
That is the difference between “we made a custom object” and “we made a STIX extension other teams can actually adopt.”
Defining the schema
Once those design choices are in place, the first version of a procedure object should stay deliberately small.
The goal is not to rebuild Attack Flow in a second schema.
The goal is to create a reusable SDO that identifies a procedural pattern cleanly enough for everything else to link to it.
At minimum, I think version one would include:
name: the recognisable procedure namedescription: a plain-language explanation of the patternobjective: the attacker goal or intended effectprocedure_context: the operational context in which the procedure is relevantvariants: known variants of the same underlying procedure
Useful but optional additions:
preconditionsrequired_permissionstargeted_asset_types
Everything else can stay outside the object for now:
- sequence in Attack Flow
- evidence in
observed-data - detections in
indicator - controls in
course-of-action
To create this object I would use our stix2extensions repository. You can read how to use it here.
Here is my stix2extensions config for my proposed Procedure object.
There are a few design choices worth calling out.
First, I have intentionally kept most references out of the object definition.
The reason is simple: the more references we embed directly on the object, the more the object stops being “a reusable description of a procedural pattern” and starts becoming a container for everything around it.
At that point it becomes unclear whether the object is supposed to be:
- a procedure catalog entry
- an ATT&CK mapping record
- a detection bundle
- a control bundle
- or a mini Attack Flow
That is exactly the kind of schema sprawl I want to avoid.
STIX is already good at linking things together through relationships.
So my preference is to keep the procedure object focused on identity and description, then let the surrounding graph carry the joins to:
attack-patternobjectsattack-flowobjectsindicatorobjectscourse-of-actionobjects- reports, malware, campaigns, and intrusion sets
That keeps the object small, the semantics clear, and the extension easier to reuse across different tooling and use cases.
The one reference I would make an exception for is command_line_ref.
I think that is useful because command execution is often part of what makes a procedure operationally distinct, and linking to a representative process object gives that context without stuffing raw command syntax into the object itself.
I would still keep it optional.
Not every procedure is best expressed through a command line, and even when it is, a procedure object should usually point to a representative execution pattern, not every observed invocation.
Relationships should still do most of the joining work here:
usesorrelated-tofrom malware, intrusion sets, or campaigns- links to ATT&CK
attack-patternobjects - links to one or more Attack Flows that show full execution paths
- links to
indicatorandcourse-of-actionobjects
That keeps the object small and lets the surrounding graph do what STIX is already good at.
Second, the fields are mostly descriptive, not procedural in the sequencing sense.
That is deliberate.
The object should answer:
“What is this procedural pattern?”
Attack Flow should answer:
“How does this procedural pattern unfold?”
That split gives us the cleanest first implementation.
How it links
The easiest way to think about the proposed procedure object is as the stable tradecraft node in the middle of the graph.
It does not replace ATT&CK techniques.
It does not replace Attack Flow.
It does not replace process or indicator.
It links them.
In practice, I would expect a procedure object to connect to:
- a representative
processobject showing how it is commonly executed - one or more ATT&CK
attack-patternobjects - optional
indicatorobjects for detections
That looks roughly like this:
procedure->processprocedure->attack-patternindicator->procedure
Below is a compact STIX bundle showing that pattern.
If you’re wondering how you can programmatically generate STIX Procedure objects, read this post
The point of this bundle is not that these exact relationship types are final.
The point is that once a procedure object exists, the rest of the graph becomes much cleaner:
- ATT&CK still models the behavior category
processstill models command execution- the
procedureobject becomes the reusable tradecraft node joining them together
Closing
If procedures are going to become first-class intelligence, they need a first-class object.
By introducing a Procedure object, it gives us a stable way to catalog procedures, link them to ATT&CK, detections, controls, and flows, and reuse them across reports instead of rebuilding the same tradecraft context every time.
Attack Flow still matters. It models how a procedure unfolds.
This procedure object now models what that procedure is.
Also worth calling out Sherman Chu who has also been working on this same problem and doing good things in this area, which has helped sharpen my own thinking on it.
CTI Butler
The most important cyber threat intelligence knowledgebases.
Discuss this post
Head on over to the dogesec community to discuss this post.
Open-Source Projects
All dogesec commercial products are built in-part from code-bases we have made available under permissive licenses.
Never miss an update
Sign up to receive new articles in your inbox as they published.
