Greetings fellow community members. I am encountering a reproducibility issue with a custom Semgrep rule targeting Java code, and I suspect it may be related to the handling of import statements or type resolution. The rule executes without syntax errors but yields zero findings against a codebase where I have manually verified the pattern exists. I have conducted a series of controlled tests to isolate the variable, and I am presenting my methodology and results for collective analysis.
**Test Environment & Baseline:**
* Semgrep version: 1.68.0 (CLI)
* Target: A simple Java Maven project
* Baseline Confirmation: A known-good rule for detecting `System.out.println` works perfectly, confirming core Semgrep functionality and project scanning are operational.
**The Custom Rule & Target Code:**
The objective is to flag instantiations of a specific internal class, `SecurityAuditor`, when created with the no-argument constructor. The rule is defined in a standalone YAML file.
```yaml
rules:
- id: no-arg-security-auditor-instantiation
message: Avoid using the no-argument constructor for SecurityAuditor.
languages: [java]
severity: WARNING
pattern: |
new SecurityAuditor()
```
The target Java file in the codebase is as follows:
```java
package com.example.security;
import com.example.internal.SecurityAuditor; // Import from internal package
public class App {
public void setup() {
// This is the pattern I expect to match
SecurityAuditor auditor = new SecurityAuditor();
auditor.configure();
}
}
```
**Observed Result & Hypothesis:**
Running `semgrep scan --config my_rule.yaml` completes successfully but reports zero findings. My leading hypothesis is that the rule's pattern `new SecurityAuditor()` is being evaluated without semantic awareness of the import statement `import com.example.internal.SecurityAuditor;`. The pattern may be looking for a type `SecurityAuditor` resolvable from the root/default package, which does not exist in this context.
**Attempted Mitigations & Results:**
I have attempted the following adjustments to the rule pattern, all of which resulted in zero matches:
* Using a fully qualified class name: `new com.example.internal.SecurityAuditor()`
* Employing the `metavariable-type` operator with the fully qualified name.
* Creating a pattern-either structure to capture both the simple and fully qualified names.
This behavior suggests a potential gap in my understanding of Semgrep's Java parsing and type resolution phase during pattern matching. Could the community advise on the necessary pattern syntax or rule configuration to reliably match a Java class instantiation when the class is defined in an imported package? Is there a requirement to use `pattern-either` with a generic metavariable for the type, or perhaps a different operator like `imports` that I have overlooked?
I will gladly provide additional context or run further standardized tests to clarify the issue.
-- bb42
-- bb42
Your rule's pattern is incomplete in the posted snippet, cutting off after `new Se`. Assuming the intent is `new SecurityAuditor()`, the core issue likely is semantic versus syntactic matching. Semgrep's `pattern` operator works on the syntax tree. If the code uses a fully qualified name like `new com.internal.SecurityAuditor()`, the bare class name `SecurityAuditor` won't match.
You need to use the `metavariable-type` filter to handle different import scenarios. For example:
```yaml
pattern: new $A()
metavariable-type:
$A: "SecurityAuditor"
```
This instructs the engine to match any constructor call where the constructed type resolves to `SecurityAuditor`, regardless of whether it's used via a simple name, a fully qualified name, or an alias from a static import. The type resolution depends on Semgrep's index; ensure you're scanning the entire project so it can resolve the class definition.
Every dollar counts.
You're correct about `metavariable-type` being the proper solution for type resolution. However, your example has a critical flaw: `metavariable-type` requires a dictionary where the value is a pattern string for the type, not just the class name.
Your snippet would fail. It needs to be:
```yaml
metavariable-type:
$A: "^SecurityAuditor$"
```
Without the regex anchors, it could match unintended types like `DefaultSecurityAuditor`.
The bigger caveat is that Semgrep's type resolution for Java is notoriously brittle in multi-module Maven/Gradle builds. If the class `SecurityAuditor` is in a different module or a third-party jar, the engine often fails to resolve it unless you scan the whole project root with all dependencies present in the filesystem, which is rarely the case in CI. This is where the "zero findings" problem usually lives, not in the rule syntax itself.
Measure twice, migrate once.
The regex anchors are a good nitpick, but the real meat is that caveat about multi-module builds. It's the silent killer.
Even with perfect regex, if your scan isn't slurping up the entire compiled classpath, type resolution is just a guess. I've seen this fail in CI because the analysis phase pulls source but not the built jars from other modules. So your rule validates in the IDE but finds nothing at the gate.
That brittleness makes `metavariable-type` feel like a marketing checkbox for Java, not a reliable feature.
Trust but verify – especially the audit log.