Skip to content

fix: add the missing capture group to four regex extractors - #16663

Merged
theamanrawat merged 4 commits into
projectdiscovery:mainfrom
DPS0340:fix/regex-extractor-missing-capture-group
Aug 10, 2026
Merged

theamanrawat merged 4 commits into
projectdiscovery:mainfrom
DPS0340:fix/regex-extractor-missing-capture-group

Conversation

@DPS0340

@DPS0340 DPS0340 commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

What's wrong

Four regex extractors declare group: 1 on a pattern that has no capture group. ExtractRegex skips every submatch (len(match) < group+1), so the value each template promises is never reported — silently, with no error.

http/exposed-panels/oracle-containers-panel.yaml                        version never extracted
http/misconfiguration/springboot/springboot-x-application-context.yaml  header value never extracted
http/exposures/configs/smtp-credentials-exposure.yaml                   JSON form of both credentials missed (x2)

smtp-credentials-exposure is the clearest. Two patterns share one group: 1, and only the XML form captures:

regex:
  - smtp_username":".*"                    # 0 capture groups  <- never extracts
  - <smtp_username>(.*)</smtp_username>    # 1 capture group

Against a body containing both forms it extracts only bob from the XML. The JSON credential — what the template is named for — goes unreported.

How these were found

Scanned all of nuclei-templates: 13,451 yaml files, 2,100 regex extractors with group > 0. These four are the only ones affected, and after this change the scan reports 0.

Verification

Each replacement was checked against a realistic corpus before proposing it:

template pattern extracts
oracle Oracle Containers for J2EE 10g \((.*)\) 10.1.3.5.0
springboot (?m)^X-Application-Context:\s*(\S.+)$ application:prod:8080
smtp user smtp_username":"(.*?)" admin
smtp pass smtp_password":"(.*?)" s3cr3t

All four currently extract nothing.

Two deliberate choices, both tested:

  • (?m) on the springboot pattern. The header part is a multi-line block, so without it ^ only matches at the very start and the extractor still returns nothing — I confirmed that case: no (?m) -> [].
  • Lazy .*? on the smtp patterns. With a greedy .*, a body containing several keys captures everything between the first and last quote:
    greedy .*  -> [admin","other":"x","smtp_username":"second]
    lazy .*?   -> [admin second]
    

End-to-end with nuclei: I built nuclei with the validation from projectdiscovery/nuclei#7612 + #7603, which turns this class into a hard error. The originals are rejected with an exact reason, and these fixed versions validate clean:

before:  regex extractor group 1 is out of range for pattern
         "Oracle Containers for J2EE 10g \(.*\)", which has 0 capture group(s)
after:   All templates validated successfully

Only the extractor patterns changed — matchers are untouched, including the word matcher in the springboot template that shares the same string.

Note

These are worth fixing regardless of whether that nuclei-side validation lands; they're wrong today and have been since they were written. If the maintainers prefer, the group: 1 could be dropped instead of adding the capture — but then the extractor would return the whole match rather than just the value, which reads like a different intent from what the author wrote.

Each of these declares group: 1 on a pattern with no capture group. The
extractor skips every submatch (len(match) < group+1) and silently
produces nothing, so the value the template promises is never reported.

  oracle-containers-panel          version string never extracted
  springboot-x-application-context header value never extracted
  smtp-credentials-exposure        JSON form of both credentials missed

smtp-credentials-exposure is the clearest: two patterns share one
group: 1, and only the XML form captures. Against a body containing both
forms it extracts only the XML match, so the JSON credential the
template is named for goes unreported.

Verified each replacement against a realistic corpus:

  oracle    'Oracle Containers for J2EE 10g \((.*)\)'  -> 10.1.3.5.0
  springboot '(?m)^X-Application-Context:\s*(\S.+)$'   -> application:prod:8080
  smtp      'smtp_username":"(.*?)"'                    -> admin
  smtp      'smtp_password":"(.*?)"'                    -> s3cr3t

Two deliberate choices: the springboot pattern needs (?m) because the
header part is a multi-line block and ^ would otherwise only match at
the start of it; the smtp patterns use a lazy quantifier so a body with
several keys doesn't swallow everything between the first and last
quote.

Only the extractor patterns changed; matchers are untouched.
@DPS0340

DPS0340 commented Jul 26, 2026

Copy link
Copy Markdown
Contributor Author

Heads-up: the 🛠 Tests workflow on this PR is sitting at action_required, not failing — it needs the one-time "approve and run workflows" click that GitHub requires for a first-time contributor to this repo. Nothing is wrong with the change itself; the checks simply haven't started.

For what it's worth, I ran the equivalent locally against a nuclei build:

nuclei -validate -t <changed templates>
[INF] All templates validated successfully

and confirmed the yaml still parses across the full tree.

Happy to wait — just flagging it so the empty check list isn't read as a red build.

@ritikchaddha ritikchaddha added the Done Ready to merge label Aug 9, 2026
@theamanrawat
theamanrawat merged commit b808bbe into projectdiscovery:main Aug 10, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Done Ready to merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants