{"id":34925412,"url":"https://github.com/seqra/seqra-rules","last_synced_at":"2026-03-03T02:04:37.812Z","repository":{"id":321236303,"uuid":"1047650893","full_name":"seqra/seqra-rules","owner":"seqra","description":null,"archived":false,"fork":false,"pushed_at":"2026-01-15T09:58:00.000Z","size":446,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-01-15T15:37:29.045Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/seqra.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-08-30T22:40:22.000Z","updated_at":"2026-01-15T09:57:07.000Z","dependencies_parsed_at":"2025-10-28T16:23:32.927Z","dependency_job_id":"328e547b-69fc-4119-997b-7e525346e40d","html_url":"https://github.com/seqra/seqra-rules","commit_stats":null,"previous_names":["seqra/seqra-rules"],"tags_count":9,"template":false,"template_full_name":null,"purl":"pkg:github/seqra/seqra-rules","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seqra%2Fseqra-rules","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seqra%2Fseqra-rules/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seqra%2Fseqra-rules/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seqra%2Fseqra-rules/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/seqra","download_url":"https://codeload.github.com/seqra/seqra-rules/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seqra%2Fseqra-rules/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28635120,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-21T14:50:40.221Z","status":"ssl_error","status_checked_at":"2026-01-21T14:48:59.225Z","response_time":86,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-12-26T14:28:26.937Z","updated_at":"2026-01-21T15:00:52.532Z","avatar_url":"https://github.com/seqra.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Seqra Security Rules\n\n[![GitHub release](https://img.shields.io/github/release/seqra/seqra-rules.svg)](https://github.com/seqra/seqra-rules/releases)\n\nA curated collection of security rules for [Seqra](https://github.com/seqra/seqra), a static analysis engine for Java and Kotlin that combines Semgrep-style pattern matching with dataflow/taint analysis.\n\nThe repository provides:\n\n- A logically structured set of executable security rules for real-world Java/Kotlin applications\n- A shared library of reusable rule components (sources, sinks, propagators, etc.)\n- A test suite that validates rule behavior and enforces coverage for all enabled rules\n\n---\n\n## Repository Structure\n\n```text\n.\n├─ rules/java/\n│  ├─ security/       # Executable rules run against user code (one file per vulnerability class)\n│  └─ lib/            # Reusable rule fragments, not executed directly (marked as lib: true)\n└─ test/\n   └─ src/main/java/\n      └─ security/  # Rule tests with @PositiveRuleSample / @NegativeRuleSample\n```\n\n### `rules/`: Executable Security Rules\n\nAll rules that are intended to run on user code live under `rules/`. Each file groups a *class of vulnerability*.\n\nExample:\n\n```text\nrules/java/security/\n  command-injection.yaml\n  sqli.yaml\n  xss.yaml\n  xxe.yaml\n```\n\nCharacteristics:\n\n- Rules are written in **Semgrep-compatible YAML**.\n- Each rule entry has an `id`, `severity`, `message`, `metadata`, `languages`, and pattern/mode fields (`mode: taint`, `pattern`, `patterns`, `pattern-either`, `pattern-sources`, `pattern-sinks`, etc.).\n- Rules in `rules/` are considered **executable** unless:\n  - `options.disabled: \u003creason\u003e` — the rule is disabled\n  - `options.lib: true` — the rule is a library component (should normally reside in `lib/`)\n\n### `lib/`: Reusable Rule Components\n\nThe `lib/` directory contains rule fragments that are **not executed standalone**. They are building blocks (sources, sinks, propagators, etc.) that other rules compose via `mode: join` or standard taint rules.\n\nStructure is by technology, example:\n\n```text\nlib/\n  java/\n    generic/\n      command-injection-sinks.yaml\n      servlet-sqli-sinks.yaml\n      servlet-untrusted-data-source.yaml\n      servlet-xss-sinks.yaml\n      xxe-sinks.yaml\n    spring/\n      jdbc-sqli-sinks.yaml\n      spring-xss-sinks.yaml\n      untrusted-data-source.yaml\n```\n\nAll library rules are marked:\n\n```yaml\nrules:\n  - id: java-servlet-untrusted-data-source\n    options:\n      lib: true\n    ...\n```\n\nKey points:\n\n- **`lib: true`** explicitly marks a rule as non-executable; it will not be run by Seqra as a top-level rule.\n- Library rules are typically:\n  - Source definitions (`*untrusted-data-source*`)\n  - Sink definitions (`*sinks*`)\n  - Propagation or helper patterns shared across multiple vulnerabilities\n\n---\n\n## Join Mode\n\nMany rules under `rules/` combine multiple library rules using **`mode: join`**.\n\nExample (from `rules/java/security/ssrf.yaml`):\n\n```yaml\n- id: ssrf-in-servlet-app\n  languages:\n    - java\n  mode: join\n  join:\n    refs:\n      - rule: java/lib/generic/servlet-untrusted-data-source.yaml#java-servlet-untrusted-data-source\n        as: untrusted-data\n      - rule: java/lib/generic/ssrf-sinks.yaml#java-ssrf-sink\n        as: sink\n    on:\n      - 'untrusted-data.$UNTRUSTED -\u003e sink.$UNTRUSTED'\n```\n\nSemantics:\n\n- `mode: join` derives a composite rule from other rules referenced in `join.refs`.\n- `refs` defines:\n  - `rule`: path to the library rule file plus `#\u003crule-id\u003e` inside that YAML\n  - `as`: local alias for referencing captures/variables from that rule\n- `on` describes how to correlate matches from referenced rules:\n  - `untrusted-data.$UNTRUSTED -\u003e sink.$UNTRUSTED` expresses a **dataflow relationship** between the `$UNTRUSTED` captured in the source rule and the same `$UNTRUSTED` captured in the sink rule.\n\nThis join mode is **based on Semgrep's join mode**, but Seqra extends it with custom features (such as the `-\u003e` notation in the `on` section) to express taint-style flows across multiple rule components.\n\n---\n\n## Rule Semantics\n\nRules follow Semgrep syntax and concepts:\n\n- **Pattern-based** rules:\n  - `pattern`, `patterns`, `pattern-either`, `pattern-inside`, `pattern-not-inside`, `metavariable-regex`, etc.\n- **Taint-style rules**:\n  - `mode: taint`\n  - `pattern-sources`, `pattern-propagators`, `pattern-sanitizers`, `pattern-sinks`\n  - Dataflow through methods, fields, and variables\n- **Metadata**:\n  - `cwe`, `short-description`, `full-description` (where provided)\n  - External references (OWASP, CWE, upstream rule sources)\n  - Optional `license` and `provenance`\n\n---\n\n## Testing and Rule Coverage\n\nRule behavior is validated via Java test snippets under:\n\n```text\ntest/src/main/java/security/\n```\n\nEach test class declares **inline code samples** annotated with:\n\n- `@PositiveRuleSample(...)` — code that **must** trigger a specific rule\n- `@NegativeRuleSample(...)` — code that **must not** trigger that rule (not shown above but typically paired with positives)\n\nAnnotation usage (conceptually):\n\n```java\n@PositiveRuleSample(\n    value = \"java/security/xss.yaml\",\n    id = \"xss-in-servlet-app\"\n)\nclass SomeServletXssSample {\n    // vulnerable code here\n}\n```\n\n### Rule Coverage Enforcement\n\nThe CI helper `RuleCoverageCheck` (in `test/src/main/java/rules/RuleCoverageCheck.java`) enforces:\n\n1. **YAML validity** for every file in `rules/`:\n   - Root is a map and contains a `rules` list.\n   - Each rule has a non-blank `id`.\n2. **Test coverage for all active rules**:\n   - Active rules are those in `rules/` where:\n     - `options.disabled` is not `true`, and\n     - `options.lib` is not `true`\n   - Each such rule must have at least one `@PositiveRuleSample` referencing:\n     - `value = \"\u003crelative-path-to-rule-yaml\u003e\"` (e.g. `java/security/xss.yaml`)\n     - `id = \"\u003crule-id\u003e\"` (the rule's `id` value)\n\nIf any active rule is not covered by a positive sample, or if any YAML is invalid, the checker:\n\n- Prints detailed errors (uncounted rules, invalid YAML, etc.)\n- Exits with a non-zero status (breaking the build/CI)\n\n---\n\n## Gradle Integration\n\nThis repository exposes a Gradle verification task:\n\n- **`verification/checkRulesCoverage`**\n\nBehavior:\n\n- Runs the `RuleCoverageCheck` helper\n- Ensures:\n  - All rule YAMLs in `rules/` are syntactically valid\n  - Every enabled, non-lib rule has at least one positive test sample\n\nUsage (from the `test/root` subdirectory):\n\n```bash\ncd test/root\n../gradlew verification/checkRulesCoverage\n```\n\nOn success:\n\n- `\"Rule coverage check passed: all rules valid and covered.\"` is printed.\n\nOn failure:\n\n- It prints all problems (invalid YAML, uncovered rules) and fails the task.\n\n---\n\n## Adding or Modifying Rules\n\nWhen introducing or changing rules, follow these guidelines:\n\n1. **Choose the correct location**\n   - Executable vulnerability rules → `java/security/\u003cvuln-class\u003e.yaml`\n   - Shared sources, sinks, or helpers → `java/lib/generic/` or `java/lib/spring/`\n\n2. **Mark library-only rules**\n   - Add `options.lib: true` for library fragments in `lib/` (or exceptionally in `rules/` if they are not meant to be executed directly).\n\n3. **Avoid duplicates**\n   - Reuse existing library rules from `lib/` and compose them via `mode: join` where applicable.\n\n4. **Update tests**\n   - Add at least one `@PositiveRuleSample` (and typically `@NegativeRuleSample`) under `test/src/main/java/security/`.\n   - Reference the rule by:\n     - `value = \"\u003crelative YAML path under project root\u003e\"`\n     - `id = \"\u003crule id\u003e\"`\n\n5. **Run coverage checks**\n   - From the `test/root` subdirectory execute `../gradlew verification/checkRulesCoverage` to ensure:\n     - No YAML errors\n     - All executable rules are covered by tests\n\n---\n\n## License\n\nThis project is licensed under the MIT License — see the [LICENSE](LICENSE) file for details.\n\nRule content may incorporate or adapt patterns originally published under various open-source licenses (for example, from community rule sets). Where applicable, original provenance and license information is recorded in rule `metadata`.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fseqra%2Fseqra-rules","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fseqra%2Fseqra-rules","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fseqra%2Fseqra-rules/lists"}