coreruleset / coreruleset/coreruleset
RFC: CRS Access Control Dimensions - Design Exploration
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 3.3k
- Forks
- 470
- Avg merge
- 1d 20h
- Merged PRs (30d)
- 11
Description
Current decision model
Today CRS has essentially a 2D model:
| Dimension | Controls | Values |
|---|---|---|
| Paranoia Level | which rules are active (detection breadth) | PL1–PL4 |
| Severity | how much each match contributes (score weight) | CRITICAL=5, ERROR=4, WARNING=3, NOTICE=2 |
These feed into a single aggregate anomaly score compared against a single threshold. It's a flat sum - every match is fungible.
Unused data already in the rules
CRS already tracks rich metadata that is logged but never used for decisions:
1. Attack category scores (8 categories, all wasted)
tx.sql_injection_score, tx.xss_score, tx.rfi_score, tx.lfi_score, tx.rce_score, tx.php_injection_score, tx.http_violation_score, tx.session_fixation_score
These are accumulated per-request and reported in rule 980170, but never compared to any threshold. This is the lowest-hanging fruit — we could add per-category thresholds:
tx.rce_score_threshold=5 # zero tolerance for RCE
tx.http_violation_score_threshold=15 # lenient on protocol noise
This lets operators say "block immediately on any RCE signal, but tolerate a few HTTP violations." The data pipeline already exists — we just need the decision point.
2. Platform / language tags (24 platforms, 10 languages)
Every rule is tagged with things like platform-mysql, language-java, platform-windows. But there's no mechanism to say "my stack is Java on Linux with PostgreSQL" and have CRS weight rules accordingly.
This could manifest as a platform profile — not disabling rules (which loses detection), but adjusting score contribution:
- rules matching your stack -> full weight
- rules targeting other platforms -> reduced weight or detection-only
3. CAPEC tags (32 unique attack patterns)
These provide a richer attack taxonomy than the 8 category scores. They could enable more granular policy, though the complexity may not be worth it for most deployments.
New dimensions worth considering
4. Confidence (doesn't exist yet, highest value)
This is the biggest gap. Today, severity measures impact (how bad is this attack if real), but nothing measures how likely the match is a true positive. Consider:
- Rule matching
UNION SELECT FROMin a query parameter -> high confidence - Rule matching
orin a cookie value -> low confidence - Rule matching
../../../etc/passwd-> high confidence - Rule matching a 3-char SQL keyword in a Base64 blob -> low confidence
A confidence tag would let CRS weight matches differently:
high confidence + critical severity → 5 points (as today)
low confidence + critical severity → 2 points (reduced)
This directly addresses the core CRS tension: PL2+ rules exist because they catch real attacks, but they're noisy. Confidence separates "this rule is aggressive" (PL) from "this particular match is suspicious" (confidence). Rules at PL2 could carry a confidence:low tag, and the scoring engine could discount them rather than the current all-or-nothing PL gate.
5. Match location weighting
Where a pattern matched matters. SQLi in ARGS:username is more suspicious than SQLi-like patterns in REQUEST_HEADERS:Referer (which often contains legitimate URLs with SQL-like tokens). Today all variables contribute equally.
This could be a per-variable weight multiplier:
ARGS-> 1.0x (full weight)
REQUEST_HEADERS:Referer -> 0.5x
REQUEST_COOKIES -> 0.7x
6. Request context
HTTP method + content type + endpoint pattern define a request's risk profile. A POST /api/admin/query with application/json is a very different context than GET /images/logo.png. This is hard to generalize but could work as operator-defined profiles.
What I'd prioritize
| Priority | Dimension | Effort | Impact |
|---|---|---|---|
| 1 | Per-category thresholds | Low (data exists) | High - granular blocking policy |
| 2 | Confidence | Medium (needs rule tagging) | Very high — fundamentally improves scoring |
| 3 | Platform profile | Medium (tags exist) | Medium — reduces noise for known stacks |
| 4 | Match location weight | High (engine changes) | Medium — address FP hotspots |
Per-category thresholds could be a first move — the infrastructure already exists, it's just the decision logic in REQUEST-949 that needs to check tx.*_score variables against configurable thresholds. Confidence is the most transformative but requires a project-wide effort to tag every rule.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the decision logic in REQUEST-949 and the existing category-score reporting in rule 980170. Trace how the tx.*_score variables are accumulated and identify the scope of the proposed dimensions. Done requires a settled design and implementation boundary, since the issue currently presents several alternatives rather than one defined change.
Written by the indexing model from the issue text.
Assessment
- Domain
- security
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100