Analysis Mode
Use xgrep's built-in native analyzers via mode: analysis rules.
Analysis Mode
Some checks are too context-dependent to express as a pattern. "Is this imported
name ever used?", "does this self.x read refer to an attribute the class never
defines?", "is this regex vulnerable to ReDoS?" — answering these accurately
needs whole-file or semantic analysis, not text/AST shape matching. xgrep ships
these as native analyzers, dispatched with mode: analysis.
A pattern rule that tries to approximate one of these checks is almost always a false-positive factory; the native analyzer is the precise implementation.
Writing an analysis-mode rule
Set mode: analysis and name an analyzer with analyzer:. The rule carries no
pattern — the analyzer produces all findings:
rules:
- id: my-undefined-attribute-rule
languages: [python]
severity: ERROR
message: Attribute is never defined on the class; this raises AttributeError.
mode: analysis
analyzer: undefined-attribute
metadata:
category: correctnessRules of the mode (enforced at load time, mirroring how mode: taint forbids
pattern):
analyzer:is required and must name a known analyzer — an unknown name is a load error, not a silent no-op.- A pattern clause (
pattern,pattern-regex,pattern-either, …) is not allowed alongsidemode: analysis. Writinganalyzer:alone impliesmode: analysis. languages:still scopes which files the rule runs on; each analyzer is also internally gated to the language(s) it supports.
Built-in analyzers
analyzer: | Languages | Detects |
|---|---|---|
unused-import | python | Imported names never referenced in the file. |
unreachable-code | python | Statements after a return/raise/break/continue in the same suite. |
go-unreachable-code | go | Statements after a return/break/continue/goto/panic in the same statement list. A terminator inside an if/for/switch branch does not make the code after that branch dead, and a labelled statement stays reachable because a goto can jump to it. |
go-no-effect | go | A call statement whose result is discarded and whose callee, declared in the same file, does nothing else — the value-receiver mistake, where t.addDays(7) should be t = t.addDays(7). A callee that returns nothing, can panic, or is not declared in this file is never flagged. |
non-callable | python | A call whose callee is provably not callable. |
no-effect | python | A bare comparison/arithmetic statement whose result is discarded. |
inconsistent-return | python | A function that returns a value on some paths and None/implicitly on others. |
conflicting-signature | python | A method overriding a local base method with an incompatible arity. |
equality-types | python | ==/!= between operands of known incompatible types (b"x" == "x"). |
wrong-arg-constructor | python | A constructor / self-method call with an argument count __init__ cannot accept. |
wrong-arg-call | python | A module-function call with an incompatible positional-argument count. |
first-param-not-self | python | An instance method whose first parameter is not self. |
invalid-escape | python | A non-raw string/bytes literal with an unrecognized backslash escape ("\d"). |
undefined-attribute | python | A self.x read where x is never defined on the class or a local base. |
use-before-def | python | A local variable read on a path where it is never bound first (UnboundLocalError). |
empty-except | python | A try whose except handler body is a single pass, silently swallowing the error (CWE-390). |
redundant-comparison | python | A comparison made constant by a preceding elif/guard over the same operands (CWE-570). |
redos-static | python | A re.* call whose string-literal pattern has catastrophic-backtracking (ReDoS) shape (CWE-1333). |
duplicate-binding | javascript, typescript | A name bound twice in one parameter list or destructuring pattern. |
duplicate-property | javascript | An object literal that declares the same data-property key more than once. |
duplicate-var-decl | javascript | A var name declared more than once in the same function scope. |
javascript-unused-variable | javascript, typescript, tsx | A variable declared with an initializer and never referenced in its scope. |
use-of-returnless-function | javascript | The result of a function that never returns a value is used (always undefined). |
prototype-pollution | javascript, typescript | A for…in / Object.keys() copy into an object without prototype-key guards. |
incomplete-url-scheme | javascript, typescript | A scheme allowlist recognizing some but not all of javascript:/data:/vbscript:. |
incomplete-url-substring | javascript, typescript | A substring hostname check not anchored to the URL's host. |
incomplete-html-sanitization | javascript, typescript | A .replace() chain missing some attribute-breaking characters. |
unsafe-cert-trust | java | TLS endpoint identification disabled or never enabled. |
expose-representation | java | A public method returns a private array/Map field by reference, or stores a parameter straight into one. |
java-compare-identical | java | A comparison whose two operands are the identical value (x == x), always constant — a likely copy-paste bug. |
java-confusing-method-name | java | A class declaring public boolean equals(SameType) — a confusing overload of equals(Object), never invoked by standard callers. |
java-control-chars | java | A string/char literal containing a literal control or zero-width character instead of an explicit escape. |
java-equals-array | java | equals()/hashCode() called on an ARRAY receiver, which compares/hashes identity rather than contents — use java.util.Arrays (CWE-595). |
java-inner-class-could-be-static | java | A non-static nested class whose body never uses the enclosing instance, so the implicit outer reference is pure overhead (CWE-1070). |
java-pointless-forwarding | java | A one-parameter method whose whole body forwards that parameter (plus one more argument) to another method — removable indirection. |
java-self-assignment | java | A plain assignment whose two sides are the identical expression (x = x) — a no-op, likely a missing this. qualifier. |
implicit-pending-intent | java | A mutable implicit PendingIntent reaching a broadcast/activity sink (CWE-927). |
sensitive-broadcast | java | Sensitive data broadcast in Intent extras without a permission (CWE-927). |
insecure-basic-auth | java | A Basic auth header sent after a plaintext http:// URL (CWE-522). |
lock-order | java | Inconsistent lock acquisition order across methods (deadlock, CWE-833). |
type-narrowing | java | A compound assignment narrowing a wider type (int += long, CWE-190). |
ruby-incomplete-sanitization | ruby | A .sub/.sub! that removes only the first occurrence of a metacharacter. |
javascript-asi-hazard | javascript | A statement that ends without its semicolon in a file that otherwise uses them — at least 90% of the file's terminable statements do — so automatic semicolon insertion decides where the statement ends (CWE-670). A file written without semicolons is silent entirely, and a trailing comment folded into the statement node is looked past so the report lands where the semicolon belongs. |
javascript-misleading-indentation | javascript | A statement indented to the body column of a preceding brace-less if/else/while/for, so it reads as a second body statement but always runs (CWE-483). A braced body, a follower at the control statement's own column, a body not indented past its control statement, and do … while are all silent. |
javascript-missing-this-qualifier | javascript, typescript | A bare identifier inside a class method that names one of that class's own members — a field, a method, or a this.X = … target — so the reference reaches a global or an outer binding instead of the member (CWE-682). A name bound anywhere in the file, a standard global, a call to the enclosing method itself, and constructor are all silent. |
javascript-property-write-on-primitive | javascript | A property or index WRITE whose receiver is provably a primitive: a literal ((0).foo = 42), or a local the file binds only to primitive literals. The write is silently discarded (CWE-704). A null/undefined receiver throws rather than no-opping and belongs to a different rule; parameters, uninitialised locals, and any name assigned more than once are silent. |
nodejs-cyclic-import | javascript, typescript, tsx | A require/import whose resolved target can reach back to the importing file through the project's resolved module edges — a circular dependency — rather than every require indiscriminately. |
nodejs-unresolvable-import | javascript, typescript, tsx | A relative import that resolves to no scanned file, or a bare import that is neither a Node builtin nor a declared dependency (only when the project has a package.json) — a module that will not resolve at runtime. |
nodejs-dubious-import | javascript, typescript, tsx | A subpath import that reaches past a dependency's declared public interface (its package.json exports) into an internal file Node would refuse to resolve. |
nodejs-missing-exports | javascript, typescript, tsx | A named import (import { x } / const { x } = require) of a binding the target module — statically enumerable — does not export. |
ruby-dead-store-of-local | ruby | A local variable assigned a value that the immediately following statement overwrites without reading it (CWE-563). Both statements must be plain name = expr assignments to the same local and the overwriting right-hand side must never mention the name, so an accumulator (x = x + 1, s = s.upcase), a conditional overwrite (x = 2 if c), an x += 1 operator assignment, a non-local target (@ivar, CONST, h[:k], obj.attr =), a multiple assignment, and any variable an enclosing rescue/ensure mentions all stay silent. |
swift-cleartext-logging-string-write | swift | A sensitive value written into a String (print/debugPrint/dump(SENSITIVE, to: &s), s.write(SENSITIVE), SENSITIVE.write(to: &s)) that is later console-logged bare (print/debugPrint/dump(s) with no to: redirect) — indirect cleartext logging (CWE-312/532). A string that only received harmless data, or a sensitive write into a string that is never bare-logged, stays silent. |
go-integer-overflow-conversion | go | A strconv parse result narrowed to a smaller fixed-width integer type without a bounds check, where the value is not used as a size or index — a correctness smell (CWE-190/681, audit). |
go-integer-overflow-conversion-sink | go | A strconv parse result narrowed without a bounds check whose value reaches a make size, a slice index, or a slice bound — an undersized allocation or out-of-range index from attacker input (CWE-190/681). |
go-ssh-auth-bypass | go | An ssh.ServerConfig auth callback whose body always returns a nil error, accepting every client (CWE-287). |
go-slice-bounds | go | A constant index/slice bound that provably exceeds a slice's known length/capacity, panicking at runtime (CWE-125). |
go-dead-store | go | An assignment to a local variable whose value is never read before being overwritten or returned, via backward liveness (CWE-563). |
csharp-dead-store | csharp | An assignment to a local variable whose value is never read before being overwritten or the scope exits, via backward liveness (CWE-563). |
csharp-unused-label | csharp | A labeled statement whose name is never named by a goto in the same method/function scope, dead code (CWE-561). |
csharp-null-deref | csharp | A dereference of a local flow-sensitively bound to null (T x = null; … x.M) with no intervening null guard or reassignment (CWE-476). |
csharp-self-assignment | csharp | A no-op assignment whose left- and right-hand sides are the identical lvalue (x = x, obj.P = obj.P), CWE-480/-561. |
csharp-nested-loop-shared-var | csharp | A nested for-loop that mutates a loop variable declared by an enclosing for-loop, clobbering the outer counter (CWE-670/-682). |
csharp-stringbuilder-char-init | csharp | A StringBuilder constructed with a character-literal argument, which binds to the int-capacity overload instead of setting content (CWE-704). |
csharp-redundant-tostring | csharp | A no-argument .ToString() used as an operand of string concatenation, where + already converts it (CWE-561). |
csharp-int-get-hash-code | csharp | A GetHashCode() call on a provably small-int receiver (default(int) / (int) cast of int/short/ushort/byte/sbyte), whose hash is the value itself — a useless call (CWE-561). |
csharp-hashed-but-no-hash | csharp | this used as a key/element of a hash-based collection (Dictionary/HashSet/Hashtable/ConcurrentDictionary) inside a type that overrides exactly one of Equals/GetHashCode — a silent lookup-failure bug (CWE-697). |
csharp-dead-binding-store | csharp | A binding that introduces a local never read in its scope: an is/case declaration-pattern variable, or a using-statement resource variable, whose value is discarded (CWE-563). |
csharp-futile-conditional-empty-if | csharp | An if with an else clause whose then-branch AND else-branch are both empty (an empty block or ;, with no comment trivia) — the whole conditional is a no-op (CWE-561). |
c-buffer-bounds | c, cpp | A copy/write whose constant byte length provably exceeds a fixed-size destination buffer's known capacity, an out-of-bounds write (CWE-787/121/122). |
c-oversized-read | c, cpp | A byte-oriented read (read/pread/recv/recvfrom/fgets/fread) whose CONSTANT byte length provably exceeds the known capacity of a fixed-size local destination buffer — a stack/heap array, or a constant-sized malloc/calloc/alloca/new[] pointer not since reassigned — so external input overruns it (CWE-120/CWE-787); the safe sizeof(dst)-bounded idiom (length == capacity) and any non-constant length are not flagged. |
c-free-not-on-heap | c, cpp | A free()/delete of a pointer provably bound to non-heap storage — a stack array, alloca, &local, or string literal (CWE-590). |
c-mismatched-free | c, cpp | A deallocation whose routine does not match the allocation — free() of a C++ new/new[] pointer, or delete/delete[] mismatching new[]/new/malloc (CWE-762). |
c-uninitialized-var | c, cpp | A read of a local scalar/pointer variable declared with no initializer and never written before the read (CWE-457). |
c-improper-init | c, cpp | A read of a fixed-size char/wchar_t array whose contents were never initialized — the buffer (or a pointer aliased onto it) reaches a string-read sink (strcat/strncat/strlen/printLine…) with no earlier memset/strcpy/element-write/&escape initializing it (CWE-665); the aggregate companion to c-uninitialized-var. |
c-memory-leak | c, cpp | A heap allocation stored in a local pointer that reaches function exit never freed, returned, stored, or handed to an unknown callee (CWE-401). |
c-explicit-null-deref | c, cpp | A dereference of a local pointer provably bound to a NULL constant (int *p = NULL; … *p), the explicit-NULL half of CWE-476 that taint cannot source. |
c-interproc-uaf | c, cpp | A use-after-free where an in-file helper unconditionally frees a pointer parameter — a C++ reference-to-pointer (void f(T *&p){ … free(p); }) or a by-value pointer (void f(T *p){ … free(p); }) — and the caller then dereferences the dangling pointer (CWE-416). |
c-unchecked-return-value | c, cpp | A call to a fallible libc function (scanf/fscanf/sscanf/fread/fgets/rename/remove/system/setuid…) whose return value is discarded — the call is a bare expression statement — so a failure or short read goes undetected (CWE-252). |
c-incorrect-return-value-check | c, cpp | A return-value check that cannot detect failure: a pointer-returning call (fgets/fopen/strchr…) in an ordered comparison with 0, or a size_t-returning call (fread/fwrite/strlen…) compared < 0 (always false) (CWE-253). |
c-sizeof-pointer-type | c, cpp | A sizeof(p) on a local pointer used as an allocation/copy size — malloc(sizeof(p)) / memset(buf, 0, sizeof(p)) — which sizes by the pointer width, not the pointed-to object (CWE-467). |
c-assignment-in-condition | c, cpp | An if/while/do condition that is directly an assignment (if (x = 5)) rather than a comparison — a likely == typo; the deliberate forms if ((x = 5)) / while ((c = f()) != EOF) are not flagged (CWE-481). |
c-comparison-no-effect | c, cpp | A bare ==/!= comparison used as an expression statement (x == 5;) whose result is discarded — a no-effect statement likely meant to be an assignment (CWE-482). |
c-empty-return-nonvoid | c, cpp | A return; with no value in a function whose declared return type is not void, so the caller reads an indeterminate value (CWE-758). |
c-return-stack-address | c, cpp | A function returning a local array (which decays to a pointer into the frame) or the address of a non-static local (return &x;) — a dangling pointer once the frame is torn down (CWE-562). |
c-switch-missing-default | c, cpp | A switch statement with no default: label, so an unhandled value passes silently (CWE-478). |
c-switch-fallthrough | c, cpp | A non-empty switch case that does not end in break/return/goto/continue/throw and is followed by another label — an omitted break (CWE-484); empty stacked labels are not flagged. |
cpp-catch-generic | cpp | A catch(...) or catch(std::exception&) that swallows every exception where specific handling was intended (CWE-396). |
cpp-throw-generic | cpp | A function declared throw(std::exception) or a throw of a bare std::exception object, rather than a specific type (CWE-397). |
cpp-xxe-unconfigured-parser | cpp | A locally-constructed Xerces parser that reaches parse() with no hardening call dominating the parse (setDisableDefaultEntityResolution(true) on every path, following reference aliases) and no other interaction — default entity resolution left enabled (CWE-611). |
c-fixed-address-pointer | c, cpp | A pointer set to a hard-coded numeric address (char *p = (char *)0x400000;) — not a real object, so a dereference is undefined behavior (CWE-587). |
c-empty-error-handler | c, cpp | An if that tests errno but whose body is empty — the error is detected and then ignored (CWE-390). |
c-suspicious-comment | c, cpp | A comment containing a developer-marker keyword (TODO/FIXME/HACK/BUG/XXX/KLUDGE/LATER) — an in-code admission of unfinished or known-broken work (CWE-546). |
c-heap-inspection | c, cpp | A heap buffer holding a password — read via fgets/fgetws and authenticated via LogonUser* — released by free/realloc/HeapFree without a prior memset/SecureZeroMemory/ZeroMemory clear, leaving the plaintext in freed heap memory (CWE-244). |
c-unlock-not-locked | c, cpp | A lock release/unlock call (stdThreadLockRelease/pthread_mutex_unlock/LeaveCriticalSection/ReleaseSRWLock*) on a lock with no prior acquire of the same lock earlier in the function — released before ever locked (CWE-832). |
c-missing-fd-release | c, cpp | A file descriptor or OS handle opened into a local (fopen/open/CreateFile family) that reaches function exit never closed, returned, stored, or passed to any callee — the descriptor/handle leaks (CWE-775, ref CWE-773). |
c-lock-not-released | c, cpp | A mutex acquired by a lock-acquire call (pthread_mutex_lock/EnterCriticalSection/AcquireSRWLock*/stdThreadLockAcquire) that reaches function exit still held — no unlock, pthread_cond_wait, or handoff of the same lock appears later in the function (CWE-667). A caller-passed lock parameter (acquired on the caller's behalf) is not flagged. |
c-missing-crypto-step | c, cpp | A Windows CryptoAPI encryption pipeline (gated by CryptAcquireContext) that omits a required step, leaving a consumer using an uninitialized handle: CryptHashData on a hash never CryptCreateHash'd, CryptDeriveKey from a hash never CryptHashData'd, or CryptEncrypt/CryptDecrypt with a key no producer (CryptDeriveKey/CryptGenKey/CryptImportKey) ever created (CWE-325). |
cpp-dangling-string-cstr | cpp | A pointer into a temporary std::string's buffer — .c_str()/.data() on a std::string(...)/to_string(...) temporary — stored in a variable, assignment, or return, so it dangles once the temporary is destroyed at the end of the full expression (CWE-416); a call argument or immediate subscript (which do not outlive the statement) is not flagged. |
c-strncpy-flipped-args | c, cpp | A bounded string copy/concat (strncpy/wcsncpy/strncat/wcsncat) whose count argument is derived from the SOURCE operand — sizeof(src), a strlen/wcslen-family call on src, or the source identifier itself (possibly + arithmetic) — instead of the destination's capacity, so a source longer than the destination overflows it (CWE-119/CWE-787); a count that references the destination (sizeof(dst), min(strlen(src), sizeof(dst)-1)) or a constant count is not flagged. |
cpp-uniqueptr-uaf | cpp | A pointer or address into a std::unique_ptr's object used after the object is destroyed (CWE-416): the receiver is a make_unique(...)/std::unique_ptr<T>(...) temporary — or a call to a same-file function whose by-value return type is unique_ptr — whose .get(), &*, &(->member), or reference-bound *temp escapes into a variable/assignment/return; or a named unique_ptr is unconditionally reset(...)/reassigned between a .get() borrow and a later raw->/*raw/raw[i] dereference. A value copy, a call-argument consumption, a reference-returning receiver, a rebind, a use before the reset, an address-of, and passing the pointer to a call all stay silent. |
cpp-iterator-invalidation | cpp | An iterator, element pointer, or element reference into a std::vector/std::string that outlives the container's storage (CWE-416). Two shapes: (1) a handle into a locally-declared container (v.begin()/v.data()/&v[i]/T& r = v[i]) used after an unconditional invalidating call on it (push_back/emplace_back/insert/erase/resize/reserve/clear/assign, or a string append/+=), with no re-binding in between; (2) a reference/handle into an ELEMENT of a temporary container (temp[i]/temp.at(i), where temp is a by-value container return or constructor) that escapes via a range-for, an auto&&/T& reference binding, or a reference-returning return. A use before the mutation, a re-bind after it, a conditional mutation, a parameter container, a handle passed to a function, iterating a whole temporary, or a by-value copy of an element is not flagged. |
cpp-istream-fixed-buffer | cpp | An unbounded C++ istream operator>> extraction into a fixed-size char/wchar_t array (std::cin >> buf; where char buf[N]) — a gets()-class read that writes an arbitrary-length token past the array with no bound (CWE-676/CWE-120). Fires only when the base of the >> chain is a known istream (cin/wcin, or an istream-typed local) and the extraction is unbounded; a std::setw-width-limited chain, a std::string target, a scalar or single-char lvalue, and a bare pointer are all left silent. |
solidity-reentrancy | solidity | A contract state variable written after an external ether-transfer call, with no reentrancy guard, violating checks-effects-interactions (SWC-107). |
dataflow-taint | java, python, php, kotlin, scala, lua, go, csharp, rust, swift, c, cpp, javascript, typescript | Source→sink taint via the unified dataflow engine. |
regex-hostname-dot | any | An unescaped . in a hostname regex. |
regex-unanchored-hostname | any | A hostname regex lacking start/end anchors. |
regex-semi-anchored | any | An anchor (^/$) that binds only one alternation branch (^a|b). |
regex-useless-escape | any | Unnecessary backslash escapes in a regex. |
regex-unbound-backref | any | A regex backreference to a capturing group that does not exist — \1 with no group 1, or \k<name> naming an undefined group. |
regex-backref-before-group | any | A regex backreference that appears before the group it targets is defined — a forward reference that only matches the empty string. A backref inside a lookbehind is excluded. |
regex-backref-into-neg-lookahead | any | A regex backreference to a group defined inside a negative lookahead, referenced from outside it — a negative lookahead never captures, so it only matches the empty string. |
regex-backspace-escape | any | A \b escape inside a character class, where it means the backspace character (U+0008) rather than a word boundary — almost always a mistake. |
regex-malformed | javascript, typescript, tsx | A pattern that is invalid in every ECMAScript mode and throws a SyntaxError when compiled: an unclosed group or character class, a quantifier with nothing to repeat, stacked quantifiers, or bounds written in the wrong order ({3,2}). Only RegExp(…) arguments are analyzed, where a bad pattern is a runtime failure; a malformed regex literal is a syntax error the file cannot survive. Patterns that are invalid only under the u flag (\!x, a{1, a]b) are not flagged, because the flag is not visible from the pattern and they are valid literals without it. |
regex-duplicate-char-in-class | any | A character class that lists the same character twice, by evaluated code point — under any spelling ([??], [\x0a\x0a], [:|\\|]) — which is redundant and has no effect. A character merely inside a range is not a duplicate; classes using u/v-flag syntax (\u{…}, \p{…}, &&, --) are not analyzed. |
regex-always-matches | any | A regex used in .test()/.search() that always matches because it can match the empty string on a universally-reachable path (optional/starred content, reachable at ^, $, or anywhere). A both-ends-anchored empty, a \b assertion, a universal wildcard .*, and a $-only optional under .search are not flagged. |
regex-bad-tag-filter | any | A regex HTML/XML tag filter that can be bypassed. |
regex-unmatchable-caret | any | A ^ in a position where it can never match. |
regex-unmatchable-dollar | any | A $ in a position where it can never match. |
regex-suspicious-range | any | A suspicious character range in a […] class (cross-case, digit-to-letter). |
regex-suspicious-character | any | A suspicious escape such as \a (bell) or \b (backspace) in a regex. |
gha-env-laundered-injection | yaml | An untrusted GitHub Actions context stored in an env: variable and then written to a $GITHUB_ENV/$GITHUB_OUTPUT/$GITHUB_PATH environment file. |
gha-run-shell-injection | yaml | An untrusted GitHub Actions context stored in an env: variable and then re-evaluated as shell code (eval, sh -c/bash -c, command position, or command substitution $( … )/backticks) in a run: step. |
gha-script-injection | yaml | An untrusted GitHub Actions context laundered through an env: var, read inside an embedded script through the interpreter's environment API (python os.environ, node process.env, Ruby ENV[…], Perl $ENV{…}, PHP getenv/$_ENV) and reaching a code-execution sink there (os.system, eval, subprocess(shell=True), child_process.exec, Ruby/Perl single-string system/exec and backticks/qx, PHP shell_exec/passthru/proc_open). The multi-argument argv form, which runs no shell, stays silent. |
gha-github-script-injection | yaml | An untrusted GitHub Actions context interpolated into an actions/github-script script: input, spliced into and executed as JavaScript. |
gha-cross-job-injection | yaml | An attacker-controlled job output — set directly, or indirectly from a steps.<id>.outputs.* write of an arbitrary/laundered value — consumed as needs.<job>.outputs.<name> in a downstream run: step. |
gha-command-injection | yaml | An untrusted GitHub Actions context interpolated into a run: shell command, a shell-argument action input (subcommand:/args:), or an input a curated third-party action executes as a script (Amadevus/pwsh-script script:, mikefarah/yq cmd:, addnab/docker-run-action run:/options:, …), via the workflow IR (no YAML-sibling scoping bug). Matrix dimensions the job builds from an untrusted value resolve to arbitrary, so ${{ matrix.x }} from a dynamic matrix fires. |
gha-composite-action-injection | yaml | A caller-controlled inputs.* value (or another attacker-controlled context) interpolated into a run: shell command inside a composite action.yml/action.yaml, across the caller/action boundary. |
gha-env-var-injection | yaml | An arbitrary GitHub Actions context written to $GITHUB_ENV (or ::set-env), injecting an environment variable that hijacks a later step. |
gha-env-path-injection | yaml | An arbitrary GitHub Actions context written to $GITHUB_PATH, prepending an attacker-controlled directory to PATH. |
gha-output-clobbering | yaml | An arbitrary GitHub Actions context written to $GITHUB_OUTPUT (or ::set-output), clobbering a step output a later step trusts. |
gha-ssrf-request-forgery | yaml | An arbitrary GitHub Actions context reaching the request route/URL input of an HTTP-request action (e.g. octokit/request-action route:), letting an attacker control the request target (SSRF). |
gha-cache-poisoning | yaml | A build cache reachable across the trust boundary: a release/publishing workflow using a cache-aware step (incl. implicit setup-* caching), or a job that both checks out untrusted PR code and caches — so a poisoned cache entry can be shipped or planted. |
gha-reusable-workflow-injection | yaml | A caller-controlled inputs.* value of a reusable workflow (on: workflow_call) interpolated into a run: shell command. Review-grade MEDIUM on its own; promoted to HIGH (CRITICAL under a privileged external trigger) when a same-repo caller is found passing an attacker-controlled context to that input. |
gha-argument-injection | yaml | An untrusted GitHub Actions value reaching the program argument of a text-processing tool — a sed expression or an awk program — where the argument is executed as a program (GNU sed's e command, awk's system()) rather than passed as data. Sources are the laundered lane: an env:-bound arbitrary context, the runner-provided GITHUB_HEAD_REF, or git metadata read back inside the script ($(git log --format=%s)). A tainted file operand, here-string or awk -v assignment is data and stays silent. |
gha-secret-in-log | yaml | A secret (${{ secrets.* }} bound to an env: var) transformed by a masking-defeating operation (base64/jq/cut/tr/rev/xxd/substring/…) and then printed with echo/printf. GitHub masks the raw secret in logs, but the transformed value is not masked, so it leaks into the build log. |
The any-language regex analyzers are scoped by the rule's own languages:
field and adapt to the language internally (for example, Ruby hostname anchors
are \A/\z rather than ^/$).
Configuration
Analysis-mode rules take no parameters in metadata. When an analyzer needs to
vary, it does so by analyzer identity (the regex kinds are separate
analyzer: names rather than a kind option) or by intrinsic behaviour. A
future structured options: block is the planned home for any genuinely
rule-configurable value.
See also
- Writing rules — the rule format and supported features.
- Taint analysis — the other non-
searchmode.