Skip to content

fix(seclang): use slash paths for fs.FS include roots on Windows - #1784

Merged
fzipi merged 3 commits into
corazawaf:mainfrom
Thanatos9404:fix/seclang-fs-include-paths-windows
Oct 22, 2026
Merged

fzipi merged 3 commits into
corazawaf:mainfrom
Thanatos9404:fix/seclang-fs-include-paths-windows

Conversation

@Thanatos9404

@Thanatos9404 Thanatos9404 commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

On Windows, Parser.FromFile built relative Include paths and the include directory with filepath, so fs.Sub, embed and mergefs roots (coraza-caddy loads CRS this way) got backslash names, which io/fs rejects. That directory also becomes ConfigDir, which broke @pmFromFile data next to an included file.

Both are now converted to slashes unless the root is io.OSFS, which takes OS paths. UNC and device paths are left alone, and nothing changes on Linux or macOS. This follows #1135 by @jabdr, without the build-tagged reader.

TestEmbedFS and TestGlobIncludeFromSubdirectory already fail on Windows before this change and pass after, so I did not add a test. Tested with the seclang tests on Windows, and on Linux under the default, no_memoize, multiphase and no_regex_multiline tags.

Part of #1140.

  • My code includes positive and negative tests (existing ones).
  • I have an appropriate description with correct grammar.
  • I have read the Contribution guidelines and Code of Conduct.
  • My code is properly linted and passes pre-commit tests (gofmt and vet pass; the pinned golangci-lint fails on Go 1.27).

Summary by CodeRabbit

  • Bug Fixes
    • Improved file path handling when loading parser inputs, including glob matches and relative paths, for more consistent behavior across filesystem types.

FromFile joined relative Include paths and derived the include
directory with filepath, so on Windows an fs.Sub, embed or mergefs
root was handed backslash names that io/fs rejects. The same
directory becomes ConfigDir, so @pmFromFile data next to an included
file could not be found either.

Convert those names to slashes unless the root is io.OSFS, which
takes OS paths. UNC and device paths are left as they are. Nothing
changes where the separator is already a slash.
@Thanatos9404
Thanatos9404 requested a review from a team as a code owner October 19, 2026 10:35
@coderabbitai

coderabbitai Bot commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Important

Review skipped

Review was skipped as selected files did not have any reviewable changes.

⚙️ Run configuration
  • Source mode: Auto
  • Repository: corazawaf/coraza
  • Branch: main
  • File: .coderabbit.yaml
  • Commit: d028be3
  • Layers: Repository YAML (base), Central YAML (inherited), Organization UI (inherited)
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: b1a945ff-705e-404f-bd82-5c47d8e4c149
📥 Commits

Reviewing files that changed from the base of the PR and between be8ea1a and a29b2d5.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository YAML (base), Central YAML (inherited), Organization UI (inherited)
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: ca5a823a-da45-48a8-891e-376b2d1e1263
📥 Commits

Reviewing files that changed from the base of the PR and between b1bae1f and 957c289.

📒 Files selected for processing: 1
  • internal/seclang/parser.go
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

Included review availability: This review used your included allowance. Your plan provides up to 8 included reviews per hour; 7 remain after this review.

📝 Walkthrough

Parser.FromFile now handles glob results separately from relative paths. It applies filesystem-aware path conversion to the selected path and its directory.

Changes: Parser Path Handling

Layer / File(s) Summary
Path selection and conversion
internal/seclang/parser.go
Glob matches are read without joining them to the current directory. Non-glob relative paths are joined to the current directory. The selected path and its directory are normalized through fsPath, which preserves OS filesystem paths and paths with volume names longer than two characters. Other paths are converted to slash-separated form.

Priority: ⬇️ Low

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix

Merge Risk: ⚪ Minimal · up to 957c2

No actionable merge-blocking risk is established for this path-handling change.

Pre-merge checks: Passed 18
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly and concisely identifies the main change: using slash-separated paths for fs.FS include roots on Windows.
Docstring Coverage Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 1…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Adr Required For Structural Changes Passed Passed — not applicable. The diff changes only internal/seclang/parser.go and fixes Windows path handling in Parser.FromFile (internal/seclang/parser.go:58-105). It adds no directive, operator, …
Test Layer Discipline & Duplication Passed Not applicable. The pull request changes only internal/seclang/parser.go; it adds no _test.go file and does not touch testing/engine/ or testing/profile/. The custom check therefore has no tes…
Generated Content Not Hand-Edited Passed Not applicable. The pull request changes only internal/seclang/parser.go; it does not touch any generated .gen.go file or the specified English/Spanish Seclang documentation files.
Documentation Translation Parity Passed Not applicable. The pull request changes only internal/seclang/parser.go in the current repository and does not touch the coraza.io repository or any file under content/en/.
Cgo Memory Safety Passed Not applicable. The pull request changes only internal/seclang/parser.go; it does not change a .go file under libcoraza/ or any .c, .h, or .i file.
Breaking Changes To Public Api & Compatibility Passed No breaking public API or compatibility change is introduced. The PR changes only internal/seclang/parser.go: it adds unexported fsPath and normalizes relative include paths and ConfigDir for no…
Security Fix Process Compliance Passed Not applicable. The PR title, description, commit message, and changed code describe a Windows io/fs path correctness fix. They do not describe an exploitable vulnerability, attack sequence, working…
Owasp Security (Web & Supply Chain) Passed No OWASP security failure is introduced. The PR only normalizes parser include paths and ConfigDir for fs.FS roots in internal/seclang/parser.go:55-67. It does not add secrets, cryptography, dep…
Unpinned Dependencies & Actions Passed Passed: not applicable. The pull request changes only internal/seclang/parser.go; it does not change a dependency manifest, lockfile, Dockerfile, or workflow file covered by this check.
New Dependency Scrutiny Passed The pull request changes only internal/seclang/parser.go (+13/-2). The reviewed diff adds no entry to go.mod or package.json, and adds no workflow uses: step. The dependency scrutiny trigger d…
Install & Build-Time Code Execution Passed PASS. The pull request changes only internal/seclang/parser.go. The diff adds Parser.fsPath and updates path handling; it adds no installer, Docker build fetch, CI setup, shell script, Go checksum…
Secrets, Payloads & Pii In Logs Passed No logging or telemetry code changed. The added code only normalizes filesystem paths in internal/seclang/parser.go; it does not emit request/response data, credentials, tokens, base64 blobs, or aud…
Renovate: Config Present And Valid Passed The pull request changes only internal/seclang/parser.go. It does not touch any Renovate configuration path, and renovate.json exists at the PR head with the required $schema and `github>corazaw…
Full details: Docstring Coverage

Explanation

No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 1 files.

Full details: Adr Required For Structural Changes

Explanation

Passed — not applicable. The diff changes only internal/seclang/parser.go and fixes Windows path handling in Parser.FromFile (internal/seclang/parser.go:58-105). It adds no directive, operator, action, transformation, variable, collection, subsystem, plugin, public API change, or performance-oriented algorithm change. This is an explicit bug fix, which the check exempts. No ADR file was added, and no ADR is required.

Full details: Test Layer Discipline & Duplication

Explanation

Not applicable. The pull request changes only internal/seclang/parser.go; it adds no _test.go file and does not touch testing/engine/ or testing/profile/. The custom check therefore has no test-layer or duplication condition to evaluate.

Full details: Breaking Changes To Public Api & Compatibility

Explanation

No breaking public API or compatibility change is introduced. The PR changes only internal/seclang/parser.go: it adds unexported fsPath and normalizes relative include paths and ConfigDir for non-io.OSFS roots. Parser.FromFile and WithDirectivesFromFile signatures remain unchanged, and OS-backed paths remain unchanged. The behavior fixes Windows fs.FS includes rather than invalidating a previously working configuration. Existing coverage includes TestEmbedFS and TestGlobIncludeFromSubdirectory in internal/seclang/parser_test.go. No documentation update is required by this check.

Full details: Security Fix Process Compliance

Explanation

Not applicable. The PR title, description, commit message, and changed code describe a Windows io/fs path correctness fix. They do not describe an exploitable vulnerability, attack sequence, working payload, impact, CVE, or GHSA. The repository guidance reserves private advisories for exploitable bugs (AGENTS.md:724-734), and this PR contains no such security disclosure.

Full details: Owasp Security (Web & Supply Chain)

Explanation

No OWASP security failure is introduced. The PR only normalizes parser include paths and ConfigDir for fs.FS roots in internal/seclang/parser.go:55-67. It does not add secrets, cryptography, dependencies, network requests, logging changes, or request-derived command/SQL/path construction. Include paths remain configuration input, and the existing filepath.Join behavior is unchanged in purpose.

Full details: New Dependency Scrutiny

Explanation

The pull request changes only internal/seclang/parser.go (+13/-2). The reviewed diff adds no entry to go.mod or package.json, and adds no workflow uses: step. The dependency scrutiny trigger does not apply.

Full details: Install & Build-Time Code Execution

Explanation

PASS. The pull request changes only internal/seclang/parser.go. The diff adds Parser.fsPath and updates path handling; it adds no installer, Docker build fetch, CI setup, shell script, Go checksum bypass, or npm lifecycle script. No custom-check failure condition is introduced.

Full details: Secrets, Payloads & Pii In Logs

Explanation

No logging or telemetry code changed. The added code only normalizes filesystem paths in internal/seclang/parser.go; it does not emit request/response data, credentials, tokens, base64 blobs, or audit records. Existing directive debug logging and read/parse error handling are unchanged. The pull request adds no fixtures or log files.

Full details: Renovate: Config Present And Valid

Explanation

The pull request changes only internal/seclang/parser.go. It does not touch any Renovate configuration path, and renovate.json exists at the PR head with the required $schema and github>corazawaf/renovate-config extension. The trigger condition is not met.

  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@fzipi fzipi left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks, this is the right spot: every include path (Include, WithDirectivesFromFile) goes through FromFile, and the operators already path.Join ConfigDir, so this also fixes @pmFromFile data under an fs.FS root. On Linux and macOS fsPath is a no-op, so nothing changes there. Checked go test ./internal/seclang/... plus GOOS=windows go vet/go test -c locally.

Our CI only runs on Linux, so no test here fails without the fix; noting that the Windows result was checked by hand.

Non-blocking follow-up: in fsPath, the UNC/device check (len(filepath.VolumeName(name)) > 2) only runs for roots that are not io.OSFS, but the comment says only an OS-backed root can open those paths. If no non-OS root can open them, the condition can go; otherwise the comment could name the root type it protects.

@fzipi
fzipi enabled auto-merge (squash) October 22, 2026 10:20
@codecov

codecov Bot commented Oct 22, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 88.58%. Comparing base (d028be3) to head (a29b2d5).

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #1784   +/-   ##
=======================================
  Coverage   88.58%   88.58%           
=======================================
  Files         180      180           
  Lines        9601     9605    +4     
=======================================
+ Hits         8505     8509    +4     
  Misses        824      824           
  Partials      272      272           
Flag Coverage Δ
coraza.no_memoize 88.63% <100.00%> (+<0.01%) ⬆️
coraza.rule.case_sensitive_args_keys 88.55% <100.00%> (+<0.01%) ⬆️
coraza.rule.mandatory_rule_id_check 88.57% <100.00%> (+<0.01%) ⬆️
coraza.rule.multiphase_evaluation 88.35% <100.00%> (+<0.01%) ⬆️
coraza.rule.no_regex_multiline 88.54% <100.00%> (+<0.01%) ⬆️
coraza.rule.rx_prefilter 88.58% <100.00%> (+<0.01%) ⬆️
default 88.58% <100.00%> (+<0.01%) ⬆️
examples+ 16.14% <0.00%> (-0.01%) ⬇️
examples+coraza.no_memoize 86.92% <100.00%> (+<0.01%) ⬆️
examples+coraza.rule.case_sensitive_args_keys 86.93% <100.00%> (+<0.01%) ⬆️
examples+coraza.rule.mandatory_rule_id_check 87.04% <100.00%> (+<0.01%) ⬆️
examples+coraza.rule.multiphase_evaluation 88.35% <100.00%> (+<0.01%) ⬆️
examples+coraza.rule.no_regex_multiline 86.87% <100.00%> (+<0.01%) ⬆️
examples+coraza.rule.rx_prefilter 87.06% <100.00%> (+<0.01%) ⬆️
examples+no_fs_access 86.33% <100.00%> (+<0.01%) ⬆️
ftw 88.58% <100.00%> (+<0.01%) ⬆️
no_fs_access 87.95% <100.00%> (+<0.01%) ⬆️
tinygo 88.53% <100.00%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@fzipi
fzipi merged commit d9cc9be into corazawaf:main Oct 22, 2026
28 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants