From cce17743bb0e88808e02fd4b25753992daed13f8 Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Mon, 30 Jun 2025 14:12:36 +0200 Subject: [PATCH] Ql4Ql: Re-factor the ql/mising-security-metadata query. --- ql/ql/src/codeql_ql/ast/Ast.qll | 26 ++++++++-- .../queries/style/MissingSecurityMetadata.ql | 49 +++++++------------ .../MissingSecurityMetadata.expected | 2 +- 3 files changed, 40 insertions(+), 37 deletions(-) diff --git a/ql/ql/src/codeql_ql/ast/Ast.qll b/ql/ql/src/codeql_ql/ast/Ast.qll index 89bdf14d4b2..5713e21592b 100644 --- a/ql/ql/src/codeql_ql/ast/Ast.qll +++ b/ql/ql/src/codeql_ql/ast/Ast.qll @@ -202,25 +202,43 @@ class QueryDoc extends QLDoc { override string getAPrimaryQlClass() { result = "QueryDoc" } - /** Gets the @kind for the query */ + /** Gets the @kind for the query. */ string getQueryKind() { result = this.getContents().regexpCapture("(?s).*@kind ([\\w-]+)\\s.*", 1) } - /** Gets the @name for the query */ + /** Gets the @name for the query. */ string getQueryName() { result = this.getContents().regexpCapture("(?s).*@name (.+?)(?=\\n).*", 1) } - /** Gets the id part (without language) of the @id */ + /** Gets the id part (without language) of the @id. */ string getQueryId() { result = this.getContents().regexpCapture("(?s).*@id (\\w+)/([\\w\\-/]+)\\s.*", 2) } - /** Gets the language of the @id */ + /** Gets the language of the @id. */ string getQueryLanguage() { result = this.getContents().regexpCapture("(?s).*@id (\\w+)/([\\w\\-/]+)\\s.*", 1) } + + /** Gets the @precision for the query. */ + string getQueryPrecision() { + result = this.getContents().regexpCapture("(?s).*@precision ([\\w\\-]+)\\s.*", 1) + } + + /** Gets the @security-severity for the query. */ + string getQuerySecuritySeverity() { + result = this.getContents().regexpCapture("(?s).*@security\\-severity ([\\d\\.]+)\\s.*", 1) + } + + /** Gets the individual @tags for the query. */ + string getQueryTags() { + exists(string tags | tags = this.getContents().regexpCapture("(?s).*@tags ([^@]+)", 1) | + result = tags.splitAt("*").trim() and + result.regexpMatch("[\\w\\s\\-]+") + ) + } } class BlockComment extends TBlockComment, Comment { diff --git a/ql/ql/src/queries/style/MissingSecurityMetadata.ql b/ql/ql/src/queries/style/MissingSecurityMetadata.ql index 10f50fb3f99..fea75d36302 100644 --- a/ql/ql/src/queries/style/MissingSecurityMetadata.ql +++ b/ql/ql/src/queries/style/MissingSecurityMetadata.ql @@ -10,45 +10,30 @@ import ql -predicate missingSecuritySeverity(QLDoc doc) { - exists(string s | s = doc.getContents() | - exists(string securityTag | securityTag = s.splitAt("@") | - securityTag.matches("tags%security%") - ) and - exists(string precisionTag | precisionTag = s.splitAt("@") | - precisionTag.matches("precision %") - ) and - not exists(string securitySeverity | securitySeverity = s.splitAt("@") | - securitySeverity.matches("security-severity %") - ) - ) +private predicate unInterestingLocation(File f) { + f.getRelativePath().matches("%/" + ["experimental", "examples", "test"] + "/%") } -predicate missingSecurityTag(QLDoc doc) { - exists(string s | s = doc.getContents() | - exists(string securitySeverity | securitySeverity = s.splitAt("@") | - securitySeverity.matches("security-severity %") - ) and - exists(string precisionTag | precisionTag = s.splitAt("@") | - precisionTag.matches("precision %") - ) and - not exists(string securityTag | securityTag = s.splitAt("@") | - securityTag.matches("tags%security%") - ) - ) +predicate missingSecuritySeverity(QueryDoc doc) { + doc.getQueryTags() = "security" and + exists(doc.getQueryPrecision()) and + not exists(doc.getQuerySecuritySeverity()) } -from TopLevel t, string msg +predicate missingSecurityTag(QueryDoc doc) { + exists(doc.getQuerySecuritySeverity()) and + exists(doc.getQueryPrecision()) and + not doc.getQueryTags() = "security" +} + +from TopLevel t, QueryDoc doc, string msg where - t.getLocation().getFile().getBaseName().matches("%.ql") and - not t.getLocation() - .getFile() - .getRelativePath() - .matches("%/" + ["experimental", "examples", "test"] + "/%") and + doc = t.getQLDoc() and + not unInterestingLocation(t.getLocation().getFile()) and ( - missingSecuritySeverity(t.getQLDoc()) and + missingSecuritySeverity(doc) and msg = "This query file is missing a `@security-severity` tag." or - missingSecurityTag(t.getQLDoc()) and msg = "This query file is missing a `@tag security`." + missingSecurityTag(doc) and msg = "This query file is missing a `@tags security`." ) select t, msg diff --git a/ql/ql/test/queries/style/MissingSecurityMetadata/MissingSecurityMetadata.expected b/ql/ql/test/queries/style/MissingSecurityMetadata/MissingSecurityMetadata.expected index 28421838ae3..af2fbd54acb 100644 --- a/ql/ql/test/queries/style/MissingSecurityMetadata/MissingSecurityMetadata.expected +++ b/ql/ql/test/queries/style/MissingSecurityMetadata/MissingSecurityMetadata.expected @@ -1,2 +1,2 @@ -| testcases/BadNoSecurity.ql:1:1:16:9 | TopLevel | This query file is missing a `@tag security`. | +| testcases/BadNoSecurity.ql:1:1:16:9 | TopLevel | This query file is missing a `@tags security`. | | testcases/BadNoSeverity.ql:1:1:16:9 | TopLevel | This query file is missing a `@security-severity` tag. |