Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Alternate threat model implementation #14582

Draft
wants to merge 9 commits into
base: main
Choose a base branch
from
Draft

Conversation

dbartol
Copy link
Contributor

@dbartol dbartol commented Oct 24, 2023

This is an alternate implementation of threat models that depends on a new CLI option (--threat-model) that generates a temporary extension pack to configure the supported threat models. Compare to #14548, which does not require a new CLI option.

This implementation has a few advantages over the other:

  • It allows disabling of a threat model that was enabled earlier in the configuration. This is useful for multi-level configuration scenarios where the org-level configuration specifies a particular threat model, but the repo-level configuration wants to disable it. It also helps within a single configuration when trying to enable all of the threat models in a group except for one particular one (e.g., all local sources except environment).
  • It allows disabling of the default threat model via the same mechanism as disabling any other threat model.
  • The all threat model works as originally intended.

The downside is that we have to add a new configuration setting to half a dozen places.

Implementation details

codeql database analyze will accept a new --threat-model option that can be specified multiple times. Each instance of the option accepts a string argument with the name of a threat model, optionally preceded by !. Without a !, the option enables the specified threat model, or, if the specified model is a group, all of its descendants. With a !, the option disables the specified threat model or its descendants. The options are processed in order.

Before running the analysis, the CLI will generate a temporary extension pack that extends the threatModelConfiguration predicate with one row for each instance of the --threat-model option. The row will contain the following columns:

  • kind - The name of the threat model, without any ! prefix.
  • enabled - A boolean value set to false if the argument had a ! prefix, and true, otherwise.
  • priority - An int value specifying the order in which the option was processed. The first instance gets priority 0, the next gets priority 1, and so on.

At evaluation time, the codeql/threat-models library processes the threatModelConfiguration table to determine which threat models are actually enabled.

@github-actions github-actions bot added the Java label Oct 24, 2023
@michaelnebel
Copy link
Contributor

This looks really nice @dbartol!
I have taken the liberty to update existing tests and add an extra one for the "subtraction".

Comment on lines +48 to +65
/**
* Gets the `enabled` column of the highest-priority configuration row whose `kind` column includes
* the specified threat model kind.
*/
private boolean threatModelExplicitState(string kind) {
// Find the highest-oriority configuration row whose `kind` column includes the specified threat
// model kind. If such a row exists and its `enabled` column is `true`, then the threat model is
// enabled.
(knownThreatModel(kind) or kind = "<other>") and
result =
max(boolean enabled, int priority |
exists(string configuredKind | configuredKind = getParentThreatModel*(kind) |
threatModelConfiguration(configuredKind, enabled, priority)
)
|
enabled order by priority
)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
/**
* Gets the `enabled` column of the highest-priority configuration row whose `kind` column includes
* the specified threat model kind.
*/
private boolean threatModelExplicitState(string kind) {
// Find the highest-oriority configuration row whose `kind` column includes the specified threat
// model kind. If such a row exists and its `enabled` column is `true`, then the threat model is
// enabled.
(knownThreatModel(kind) or kind = "<other>") and
result =
max(boolean enabled, int priority |
exists(string configuredKind | configuredKind = getParentThreatModel*(kind) |
threatModelConfiguration(configuredKind, enabled, priority)
)
|
enabled order by priority
)
}
/**
* Holds if the `enabled` column is set to `true` of the highest-priority configuration row
* whose `kind` column includes the specified threat model kind.
*/
private predicate threatModelEnabled(string kind) {
// Find the highest-oriority configuration row whose `kind` column includes the specified threat
// model kind. If such a row exists and its `enabled` column is `true`, then the threat model is
// enabled.
knownThreatModel(kind) and
max(boolean enabled, int priority |
exists(string configuredKind | configuredKind = getParentThreatModel*(kind) |
threatModelConfiguration(configuredKind, enabled, priority)
)
|
enabled order by priority
) = true
}

// Find the highest-oriority configuration row whose `kind` column includes the specified threat
// model kind. If such a row exists and its `enabled` column is `true`, then the threat model is
// enabled.
(knownThreatModel(kind) or kind = "<other>") and
Copy link
Contributor

Choose a reason for hiding this comment

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

What does kind = <other> represent?

*/
bindingset[kind]
predicate currentThreatModel(string kind) {
knownThreatModel(kind) and threatModelExplicitState(kind) = true
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
knownThreatModel(kind) and threatModelExplicitState(kind) = true
knownThreatModel(kind) and threatModelEnabled(kind)

or
// For any threat model kind not mentioned in the configuration or grouping tables, its state of
// enablement is controlled only by the entries that specifiy the "all" kind.
not knownThreatModel(kind) and threatModelExplicitState("all") = true
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
not knownThreatModel(kind) and threatModelExplicitState("all") = true
not knownThreatModel(kind) and threatModelEnabled("all")

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants