Skip to content

feat(security): SEC003 / SEC005 / SEC008 multi-language strengthen (PR #19)#19

Merged
wei9072 merged 1 commit into
mainfrom
feat/sec3-5-8-strengthen
May 7, 2026
Merged

feat(security): SEC003 / SEC005 / SEC008 multi-language strengthen (PR #19)#19
wei9072 merged 1 commit into
mainfrom
feat/sec3-5-8-strengthen

Conversation

@wei9072
Copy link
Copy Markdown
Owner

@wei9072 wei9072 commented May 7, 2026

Summary

Continues PR #18's audit. The three rules I marked "decent
multi-language coverage" each had specific gaps that surface in
real-world auth / DB / serialization code.

SEC003 — TLS verification disabled

Added Pattern
PHP curl `CURLOPT_SSL_VERIFYPEER => false/0`, `CURLOPT_SSL_VERIFYHOST => 0`; both positional and inline-array forms
Ruby OpenSSL `VERIFY_NONE` / `OpenSSL::SSL::VERIFY_NONE`
Java `NoopHostnameVerifier` / `TrustAllHostnameVerifier` class names

Deferred-via-variable PHP form intentionally not caught (needs
dataflow). Java arbitrary anonymous-inner-class trust managers
also out of scope.

SEC005 — SQL string concat

Receiver-method matcher expanded across families:

  • JDBC: + `executeLargeUpdate`, `executeBatch`
  • Go / Node.js: + `Query` / `QueryRow` / `QueryContext` /
    `Exec` / `ExecContext`
  • PHP PDO: + `exec`, `prepare`
  • Ruby: + `find_by_sql`
  • PHP global: + `mysqli_query` / `mysql_query` / `pg_query` / `sqlite_query`

Plus three under-the-hood fixes:

  1. `leaf_method_name` used to support PHP `::` / `->` separators
  2. `text_has_interp` (from PR feat(security): SEC004 + SEC007 multi-language dispatch (PR #18) #18) replaces SEC005's Python-shaped
    local check, picking up PHP `.` concat
  3. `contains_sql_in_string_literal` extended to recognise PHP's
    `encapsed_string` + `string_value` plus heredoc / template
    literal kinds — so the SQL-keyword gate sees the string content
    in PHP code

SEC008 — insecure deserialization

Dangerous-call list extended across 5 languages:

Language Added
Python + `shelve.open`, `dill.loads`, `dill.load`
Java + `XMLDecoder.readObject`
PHP + `unserialize` (textbook unsafe path)
Ruby + `Marshal.load`, `YAML.load`, `Oj.load`
C# / .NET + `BinaryFormatter.Deserialize`, `SoapFormatter.Deserialize`, `NetDataContractSerializer.ReadObject`
Go + `gob.NewDecoder`

Tests

7 new (SEC003 PHP curl ×3, SEC005 Go db.Query + PHP mysqli_query,
SEC008 PHP unserialize + C# BinaryFormatter).

`cargo test --workspace`: 184 → 191 tests pass.

Test plan

  • All new SEC003/005/008 tests pass
  • No regression on existing 184 tests
  • PHP `encapsed_string` reaches contains_sql_in_string_literal
    walker
  • CURLOPT_SSL_VERIFYPEER 1 (safe value) stays silent
  • CI green on push

🤖 Generated with Claude Code

…#19)

Continues PR #18's audit. SEC003/005/008 already had decent
multi-language coverage, but each had specific gaps that surface
in real-world auth / DB / serialization code.

## SEC003 — TLS verification disabled

Added detection for:

- **PHP curl**: \`CURLOPT_SSL_VERIFYPEER => false / 0\` and
  \`CURLOPT_SSL_VERIFYHOST => 0\`. Both positional
  (\`curl_setopt($ch, OPT, 0)\`) and inline-array
  (\`curl_setopt_array($ch, array(OPT => false))\`) forms.
  Deferred-via-variable form intentionally not caught (would need
  dataflow).
- **Ruby OpenSSL**: \`VERIFY_NONE\` / \`OpenSSL::SSL::VERIFY_NONE\`.
- **Java**: \`NoopHostnameVerifier\` / \`TrustAllHostnameVerifier\`
  class names. Doesn't catch arbitrary anonymous-inner-class trust
  managers — those need real flow analysis.

## SEC005 — SQL string concat

Receiver-method matcher expanded:

| Family | Methods added |
|---|---|
| Python | (existing: execute, executemany) |
| JDBC | + executeLargeUpdate, executeBatch |
| Node.js / Go | + Query, QueryRow, QueryContext, Exec, ExecContext |
| PHP PDO | + exec, prepare |
| Ruby | + find_by_sql |
| PHP global | + mysqli_query, mysql_query, pg_query, sqlite_query |

Plus:
- \`leaf_method_name\` used (handles PHP \`::\` / \`->\`).
- \`text_has_interp\` (introduced in PR #18) replaces SEC005's
  Python-shaped local check, picking up PHP \`.\` concat correctly.
- \`contains_sql_in_string_literal\` extended to recognize PHP's
  \`encapsed_string\` / \`string_value\` and heredoc / template
  literal kinds, so the SQL-keyword gate sees the string content.

## SEC008 — insecure deserialization

Dangerous-call list extended:

| Language | Added |
|---|---|
| Python | + shelve.open, dill.loads, dill.load |
| Java | + XMLDecoder.readObject |
| **PHP** | + unserialize (textbook unsafe path) |
| **Ruby** | + Marshal.load, YAML.load, Oj.load |
| **C# / .NET** | + BinaryFormatter.Deserialize, SoapFormatter.Deserialize, NetDataContractSerializer.ReadObject |
| Go | + gob.NewDecoder |

## Tests

7 new (SEC003 PHP curl ×3, SEC005 Go db.Query + PHP mysqli_query,
SEC008 PHP unserialize + C# BinaryFormatter). 184 → 191 total
tests pass.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@wei9072 wei9072 merged commit 0b89a25 into main May 7, 2026
1 check passed
@wei9072 wei9072 deleted the feat/sec3-5-8-strengthen branch May 7, 2026 09:00
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.

1 participant