Skip to content

Update Scheduled Job Activity class and expand job object attributes#1597

Open
s-Fl wants to merge 26 commits intoocsf:mainfrom
s-Fl:scheduled_job_updates
Open

Update Scheduled Job Activity class and expand job object attributes#1597
s-Fl wants to merge 26 commits intoocsf:mainfrom
s-Fl:scheduled_job_updates

Conversation

@s-Fl
Copy link
Copy Markdown
Contributor

@s-Fl s-Fl commented Mar 18, 2026

Job update

There's an Update (2) value within activity_id in the Scheduled Job Activity class. However, no entity available to describe a resulting entity or an entity before the mutation.

image

Thus, I suggest adding the job_result object to this event class:

image

Windows Task

According to Microsoft documentation, a Task consists of Triggers, Actions and other attributes. Each Task can have multiple Triggers and Actions:

image

Task Triggers

Triggers can be divided into 2 types:

  • Time-based;
  • Event-based.

See: https://learn.microsoft.com/en-us/windows/win32/taskschd/task-triggers

A list of triggers can be found here:

Or here:

Each trigger have a set of attributes. Some are common for all triggers and others are common for each type of trigger (time-based or event-based):

image

Common attributes for event-based triggers:
image

Common attributes for time-based triggers:

image

The amount of unique attributes is high. In my opinion, it would be ineffective to place each of them under the enum-value. I suppose, we can store some of them inside a Kev:value object. Also, if the trigger type is event-based, we need to specify an event identifier and a log source that the job should look for.

The resulting job_trigger object:

image

Task Action

There are 4 actions available for a task to perform:

  • ComHandler;
  • Exec;
  • E-mail;
  • Show Message.

See: https://learn.microsoft.com/en-us/windows/win32/taskschd/task-actions#types-of-actions

Similarly, each action has different attributes. I think all of them can be stored inside a Key:value object; an exception for that is cmd_line. This attribute was previously stored inside the job object (job.cmd_line). I deprecated the job.cmd_line attribute and created similar one inside the job_action object.

The resulting job_action object:

image

Additional job attributes

From the HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tasks registry hive, we can see that each job has a unique identifier. So that, I propose adding job.uid field to store that data.

During system call discussions, additional edits were made: #1597 (comment)

I've also added Disabled (5) enum-value for run_state_id attribute:
image


The resulting job object:

image image

I'm aware that job.job_action/job.job_trigger naming is redundant. Glad to hear any suggestions.

@s-Fl s-Fl marked this pull request as draft March 18, 2026 11:29
@mikeradka mikeradka added system_activity Issues related to System Activity Category v1.9.0 labels Mar 18, 2026
@jedwardsol
Copy link
Copy Markdown
Contributor

jedwardsol commented Mar 18, 2026

Re: the "job_result " field.

I agree that there needs to be a way to represent the before and after state.

There is currently an inconsistency in the way this is done:

In File Activity there is "file" (required) and "file_result" (recommended)

In Registry Value Activity there is a "reg_value" (required) and "prev_reg_value" optional.


Since events can be captured asynchronously, after the mutation has occurred, the 2nd pattern makes more sense IMO since the original state may not be known.

I recognise that some activity can be generated synchronously - e.g. a "access control" type product may use hooks, say, to intercept the modification and block it. It will want to report the current (unchanged) state and the state that would have existed had the modification been allowed.

@mikeradka mikeradka added the enhancement New feature or request label Mar 18, 2026
@mikeradka
Copy link
Copy Markdown
Contributor

Thank you for the background, this helps very much.

At a high level, scheduled jobs exist in all major operating systems, but the way they’re defined, triggered, and managed differs quite a bit between Windows and others like Linux/Unix or macOS.

Perhaps an avenue for discussion: establishing the common attributes/intersection between:

  • Windows Task Scheduler (time + rich event based triggers)
  • *nix Cron (time based only triggers)
  • *nix Systemd (closer to Windows Flexibility, time + some events triggers)
  • macOS launchd (closer to Windows Flexibility, time + some events triggers)

Which areas of this PR are Windows specific versus which areas can be more broadly applied? We can try to sort a bit in the System Activity call.

@mikeradka
Copy link
Copy Markdown
Contributor

Re: the "job_result " field.

I agree that there needs to be a way to represent the before and after state.

There is currently an inconsistency in the way this is done:

In File Activity there is "file" (required) and "file_result" (recommended)

In Registry Value Activity there is a "reg_value" (required) and "prev_reg_value" optional.

Since events can be captured asynchronously, after the mutation has occurred, the 2nd pattern makes more sense IMO since the original state may not be known.

I recognise that some activity can be generated synchronously - e.g. a "access control" type product may use hooks, say, to intercept the modification and block it. It will want to report the current (unchanged) state and the state that would have existed had the modification been allowed.

Let's gather some more thoughts on this. Question - could it help if we approached this by enriching the job and job_result descriptions to describe the relationship between these two attributes?

@jedwardsol
Copy link
Copy Markdown
Contributor

I think this issue is bigger than this PR, so I don't intend to derail it.

However, my further thoughts :

At the risk of stating the obvious for the 1st 3, which only need the reporting of 1 object :

  1. For create (where there is no previous state), it is obvious that "object" is the object that exists now if the create succeeded, or the object that would've existed if the create was blocked. Ie. it's the current state or the non-existent future state, depending on context (action_id and/or status))

  2. For non-mutating operations (open, read) it is obvious that "object" is the current state.

  3. And for delete (where there might not be a current state), it is obvious that "object" is the object that was deleted (ie. the previous state) , whether or not the deleted succeeded. Again whether that is the current state depends on context (action_id and/or status)

  4. Activities which modify objects are the tricky ones because the event may be generated before the modification (activity blocking products) or after the modification (behaviour reporting products). And in either case, the modification may succeed or fail.

Whatever is chosen, I think current state should be required and any other states should be optional or recommended. Selfishly, I prefer "object" and "prev_object"

Instead of using "object_result" or "prev_object", maybe have 3 fields

"object" : the state at the time the event was generated
"object_pre" : the object before the modification
"object_post" : the object after the modification

But its a big break and maybe I over-thought it!

Unfortunately I am unavailable the OCSF weekly calls next week.

@s-Fl
Copy link
Copy Markdown
Contributor Author

s-Fl commented Mar 31, 2026

Just wanted to highlight another point that we've discussed with @mikeradka on the last system call (03/18/2026):
It could be a good idea to broaden action attributes within the job_action object so that we could go beyond operating system level and describe any task-related mechanism. The list of solutions and system utilities that I've decided to look at as a reference:

  • Windows Task Scheduler

  • cron

  • Systemd

  • macOS launchd

  • Kubernetes

  • Splunk

  • ETL workflows (e.g. Kafka, Delta Lake)

  • SOAR solutions

  • Terraform

Here's a generalized set of actions that I've come up with:

  • Launch: execute a program or a command line;
  • Notify: dispatch an email/alert (via API, webhook, etc.);
  • Update/Manage: update an entity - data, policy, package, etc.
  • Create or Delete: perform a creation/deletion of an entity, e.g. delete/create a field within an ETL pipeline, delete/create a K8 pod.
  • Retry or Reschedule: reattempt failures with backoff or queue;
  • Request: perform a request to an external system.
  • Check: perform a health check on an entity, e.g. Splunk query, systemd journalctl, Kubernetes liveness probes.

@jedwardsol
Copy link
Copy Markdown
Contributor

... we could go beyond operating system level and describe any task-related mechanism

It would be interesting to fit BITS (https://attack.mitre.org/techniques/T1197/) into this now or later.
BITS is used during attacks to a

a] offload downloading of tools to a operating system service (breaking the link between actors)
b] executing code based on success or failure of the download job. This is powerful enough that a job, deliberately created to fail, can be retried periodically with a cmdline to run on failure, so that BITS can be used as persistence mechanism.

There's no top level schedule, so doesn't obvious fit under "scheduled task", but there's a lot in common

Comment thread objects/job_action.json Outdated
Comment thread events/system/scheduled_job_activity.json
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 1, 2026

Schema Description Review

Automated suggestions for improving description clarity for LLM consumption. These are advisory — not required changes.

Looking at the current schema changes compared to my previous review:

Suggestions

❌ All four HTML markup issues from the previous review remain unaddressed

The HTML tags (<code>, <br/>, <em>, <b>) are still present in the same four locations:

  1. Object: job_action
    Attribute: cmd_line
    Issue: Description contains HTML markup that may not render properly in all contexts
    Current: "When type_id is Execute (2), this describes the command line that is executed.

    When type_id is COM Handler (1), this may describe the DLL path stored in the COM component's InprocServer32 key or the command line stored in the COM component's LocalServer32 key."
    Suggested: "When type_id is Execute (2), this describes the command line that is executed. When type_id is COM Handler (1), this may describe the DLL path stored in the COM component's InprocServer32 key or the command line stored in the COM component's LocalServer32 key."

  2. Object: job_action
    Attribute: properties
    Issue: Description contains HTML markup that may not render properly in all contexts
    Current: "The list of properties associated with the performed action.
    Can be populated with additional attributes of a program execution process, COM object attributes, fields of a message box or an email."
    Suggested: "The list of properties associated with the performed action. Can be populated with additional attributes of a program execution process, COM object attributes, fields of a message box or an email."

  3. Object: job_trigger
    Attribute: properties
    Issue: Description contains HTML markup that may not render properly in all contexts
    Current: "The list of properties associated with the trigger.
    Can be used to describe time boundaries of the job, amount of repetitions or when the job should be activated or expired."
    Suggested: "The list of properties associated with the trigger. Can be used to describe time boundaries of the job, amount of repetitions or when the job should be activated or expired."

  4. Class: scheduled_job_activity
    Attribute: updated_job
    Issue: Description contains HTML markup that may not render properly in all contexts
    Current: "The result of an updated job.

    When the update is successful, this is the newly updated job. Upon failure, represents the attempted state of the job."
    Suggested: "The result of an updated job. When the update is successful, this is the newly updated job. Upon failure, represents the attempted state of the job."

Anti-Pattern Findings

  1. Pattern: Generic Naming
    Object: job
    Attribute: name
    Issue: The static analysis correctly identified this as a generic attribute name with a minimal description ("The name of the job.") that doesn't provide sufficient context for LLM consumption
    Recommendation: Either expand the description to specify what kind of name this represents (display name, internal identifier, etc.) and provide examples, or use a more specific attribute name

CHANGELOG Issues

  1. Issue: Typo in Dictionary Attributes section
    Current: "Impoved job object description to describe cases beyond System Activity class."
    Suggested: "Improved job object description to describe cases beyond System Activity class."

Summary

Four HTML markup issues from the previous review remain unaddressed and should be converted to plain text for optimal cross-platform compatibility. The static analysis correctly identified a generic naming issue with the job.name attribute that warrants attention. Additionally, there's a minor typo in the CHANGELOG.

@s-Fl
Copy link
Copy Markdown
Contributor Author

s-Fl commented Apr 1, 2026

Per last system call discussion, I created a job.type_id attribute to describe the following set of job management utilities:

  • Windows Task Scheduler (time + rich event based triggers)
  • *nix Cron (time based only triggers)
  • *nix Systemd (closer to Windows Flexibility, time + some events triggers)
  • macOS launchd (closer to Windows Flexibility, time + some events triggers)
image

And updated constraints:
image

The change reason is that cron jobs don't have any name or uid.


Now I'll wait for the naming convention of the job object state (prev, current, attempted and diff) to appear. After I adapt it, this PR would be ready.

Comment thread objects/job_trigger.json
Comment thread objects/job_trigger.json
Comment thread objects/job.json
Comment thread objects/job.json Outdated
Comment thread objects/job.json Outdated
Comment thread objects/job.json Outdated
Comment thread objects/job.json Outdated
Comment thread objects/job_action.json Outdated
Comment thread objects/job_action.json
Comment thread objects/job_trigger.json Outdated
Comment thread objects/job_trigger.json Outdated
Comment thread objects/job_trigger.json
s-Fl added 2 commits April 8, 2026 19:31
Signed-off-by: s-Fl <74200804+s-Fl@users.noreply.github.com>
@s-Fl
Copy link
Copy Markdown
Contributor Author

s-Fl commented Apr 10, 2026

Changed descriptions according to new convention that we've discussed on the last system call:
image

I've also decided to change description for job_result inside the dictionary:
image

@s-Fl s-Fl marked this pull request as ready for review April 10, 2026 17:54
@mikeradka
Copy link
Copy Markdown
Contributor

Draft PR is in place for the FAQ on entity state: ocsf/ocsf-docs#134

Comment thread events/system/scheduled_job_activity.json Outdated
Comment thread dictionary.json Outdated
Comment thread dictionary.json Outdated
s-Fl added 2 commits April 21, 2026 14:53
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 21, 2026

Schema Anti-Pattern Check

Automated structural analysis for common schema design anti-patterns. These are advisory — not required changes.

Warnings

  1. type-inconsistencyjob.name
    name has different types across objects: file_name_t (1 object), process_name_t (2 objects), string_t (89 objects), username_t (1 object). Inconsistent types for the same attribute name make the schema harder to consume programmatically.

    Suggestion: Use distinct attribute names for different types, or standardize on a single type across all objects.

  2. type-inconsistencyjob.uid
    uid has different types across objects: resource_uid_t (4 objects), string_t (87 objects). Inconsistent types for the same attribute name make the schema harder to consume programmatically.

    Suggestion: Use distinct attribute names for different types, or standardize on a single type across all objects.

Informational

  1. generic-namingjob.name
    name is a very generic attribute name with a short description ("The name of the job."). Generic names require detailed descriptions to be useful.

    Suggestion: Either use a more specific attribute name (e.g., account_type instead of type) or expand the description to fully explain the attribute's purpose and expected values.

Summary: 2 warning(s), 1 informational finding(s)

@mikeradka
Copy link
Copy Markdown
Contributor

mikeradka commented Apr 21, 2026

A few angles to discuss in tomorrow's (4/22) system call:

  • Jonathan's object/object_pre/object_post suggestion from earlier.
  • Whether keeping _result exclusive for update successes and using status_detail for update failures.

@s-Fl
Copy link
Copy Markdown
Contributor Author

s-Fl commented Apr 22, 2026

@mikeradka , I renamed job_result to updated_job:

Inside the Scheduled Job Activity class:
image

Inside the dictionary:
image

Should be good now.

@s-Fl
Copy link
Copy Markdown
Contributor Author

s-Fl commented Apr 24, 2026

Changed updated_job object description according to new convention:

image

Copy link
Copy Markdown
Contributor

@mikeradka mikeradka left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great! Thank you for this contribution.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request system_activity Issues related to System Activity Category v1.9.0

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants