Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ jobs:
- run: buf format -d --exit-code
- run: buf lint
- run: buf generate && git diff --exit-code
- run: go generate ./analyzers/semgrep && git diff --exit-code
- run: go vet ./...
- run: go test ./...
- run: go test -race ./...
Expand Down
4 changes: 4 additions & 0 deletions analyzers/semgrep/generate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// Package semgrep owns Room's generated Semgrep configuration.
package semgrep

//go:generate go run ../../cmd/semgrep-rule-bundler -rules rules -output room.yml
242 changes: 118 additions & 124 deletions analyzers/semgrep/room.yml
Original file line number Diff line number Diff line change
@@ -1,17 +1,5 @@
# Code generated by semgrep-rule-bundler; DO NOT EDIT.
rules:
- id: room.source.high-confidence-secret-literal
message: A string literal with a recognized credential token format is embedded in source.
severity: ERROR
languages: [go, rust]
metadata:
room_signal: SIGNAL_KIND_SECRET_LITERAL
room_confidence_basis_points: 9500
patterns:
- pattern: $SECRET
- metavariable-regex:
metavariable: $SECRET
regex: '^"(?:gh[pousr]_[A-Za-z0-9]{36,255}|github_pat_[A-Za-z0-9_]{40,255}|sk-(?:proj-)?[A-Za-z0-9_-]{32,255}|xox[baprs]-[A-Za-z0-9-]{20,255})"$'

- id: room.go.dynamic-sql-with-untrusted-input
message: Untrusted HTTP input reaches the SQL query text.
severity: ERROR
Expand Down Expand Up @@ -39,7 +27,6 @@ rules:
- pattern: $DB.Prepare($QUERY)
- pattern: $DB.PrepareContext($CTX, $QUERY)
- focus-metavariable: $QUERY

- id: room.go.untrusted-outbound-destination
message: Untrusted HTTP input reaches an outbound request destination.
severity: ERROR
Expand All @@ -64,7 +51,111 @@ rules:
- pattern: http.NewRequest($METHOD, $URL, ...)
- pattern: http.NewRequestWithContext($CTX, $METHOD, $URL, ...)
- focus-metavariable: $URL

- id: room.rust.blocking-lock-across-await
message: A blocking lock guard remains live across an await point.
severity: ERROR
languages: [rust]
metadata:
room_signal: SIGNAL_KIND_RUST_BLOCKING_LOCK_ACROSS_AWAIT
room_confidence_basis_points: 9000
patterns:
- pattern-either:
- pattern: |
let $GUARD = $LOCK.lock().unwrap();
...
$AWAITED.await
- pattern: |
let $GUARD = $LOCK.read().unwrap();
...
$AWAITED.await
- pattern: |
let $GUARD = $LOCK.write().unwrap();
...
$AWAITED.await
- pattern: |
let mut $GUARD = $LOCK.lock().unwrap();
...
$AWAITED.await
- pattern: |
let mut $GUARD = $LOCK.read().unwrap();
...
$AWAITED.await
- pattern: |
let mut $GUARD = $LOCK.write().unwrap();
...
$AWAITED.await
- pattern: |
let $GUARD = $LOCK.lock().expect(...);
...
$AWAITED.await
- pattern: |
let $GUARD = $LOCK.read().expect(...);
...
$AWAITED.await
- pattern: |
let $GUARD = $LOCK.write().expect(...);
...
$AWAITED.await
- pattern: |
let $GUARD = $LOCK.blocking_lock();
...
$AWAITED.await
- pattern: |
let $GUARD = $LOCK.blocking_read();
...
$AWAITED.await
- pattern: |
let $GUARD = $LOCK.blocking_write();
...
$AWAITED.await
- pattern: |
let mut $GUARD = $LOCK.blocking_lock();
...
$AWAITED.await
- pattern: |
let mut $GUARD = $LOCK.blocking_read();
...
$AWAITED.await
- pattern: |
let mut $GUARD = $LOCK.blocking_write();
...
$AWAITED.await
- pattern-not: |
let $GUARD = $ACQUIRE;
...
drop($GUARD);
...
$AWAITED.await
- pattern-not: |
let mut $GUARD = $ACQUIRE;
...
drop($GUARD);
...
$AWAITED.await
- pattern-not: |
let $GUARD = $ACQUIRE;
...
std::mem::drop($GUARD);
...
$AWAITED.await
- pattern-not: |
let mut $GUARD = $ACQUIRE;
...
std::mem::drop($GUARD);
...
$AWAITED.await
- pattern-not: |
let $GUARD = $ACQUIRE;
...
core::mem::drop($GUARD);
...
$AWAITED.await
- pattern-not: |
let mut $GUARD = $ACQUIRE;
...
core::mem::drop($GUARD);
...
$AWAITED.await
- id: room.rust.command-with-untrusted-argument
message: Untrusted process or request input reaches a process command or argument.
severity: ERROR
Expand Down Expand Up @@ -115,7 +206,6 @@ rules:
let $COMMAND = tokio::process::Command::new(...);
...
- focus-metavariable: $VALUE

- id: room.rust.request-input-panics
message: Request-derived input reaches unwrap, expect, or an explicit panic.
severity: ERROR
Expand Down Expand Up @@ -143,7 +233,6 @@ rules:
- pattern: panic!($VALUE)
- pattern: panic!(..., $VALUE, ...)
- focus-metavariable: $VALUE

- id: room.rust.untrusted-filesystem-path
message: Process or request input reaches a filesystem path operation.
severity: ERROR
Expand Down Expand Up @@ -226,113 +315,6 @@ rules:
- pattern: tokio::fs::rename(..., $PATH)
- pattern: tokio::fs::copy(..., $PATH)
- focus-metavariable: $PATH

- id: room.rust.blocking-lock-across-await
message: A blocking lock guard remains live across an await point.
severity: ERROR
languages: [rust]
metadata:
room_signal: SIGNAL_KIND_RUST_BLOCKING_LOCK_ACROSS_AWAIT
room_confidence_basis_points: 9000
patterns:
- pattern-either:
- pattern: |
let $GUARD = $LOCK.lock().unwrap();
...
$AWAITED.await
- pattern: |
let $GUARD = $LOCK.read().unwrap();
...
$AWAITED.await
- pattern: |
let $GUARD = $LOCK.write().unwrap();
...
$AWAITED.await
- pattern: |
let mut $GUARD = $LOCK.lock().unwrap();
...
$AWAITED.await
- pattern: |
let mut $GUARD = $LOCK.read().unwrap();
...
$AWAITED.await
- pattern: |
let mut $GUARD = $LOCK.write().unwrap();
...
$AWAITED.await
- pattern: |
let $GUARD = $LOCK.lock().expect(...);
...
$AWAITED.await
- pattern: |
let $GUARD = $LOCK.read().expect(...);
...
$AWAITED.await
- pattern: |
let $GUARD = $LOCK.write().expect(...);
...
$AWAITED.await
- pattern: |
let $GUARD = $LOCK.blocking_lock();
...
$AWAITED.await
- pattern: |
let $GUARD = $LOCK.blocking_read();
...
$AWAITED.await
- pattern: |
let $GUARD = $LOCK.blocking_write();
...
$AWAITED.await
- pattern: |
let mut $GUARD = $LOCK.blocking_lock();
...
$AWAITED.await
- pattern: |
let mut $GUARD = $LOCK.blocking_read();
...
$AWAITED.await
- pattern: |
let mut $GUARD = $LOCK.blocking_write();
...
$AWAITED.await
- pattern-not: |
let $GUARD = $ACQUIRE;
...
drop($GUARD);
...
$AWAITED.await
- pattern-not: |
let mut $GUARD = $ACQUIRE;
...
drop($GUARD);
...
$AWAITED.await
- pattern-not: |
let $GUARD = $ACQUIRE;
...
std::mem::drop($GUARD);
...
$AWAITED.await
- pattern-not: |
let mut $GUARD = $ACQUIRE;
...
std::mem::drop($GUARD);
...
$AWAITED.await
- pattern-not: |
let $GUARD = $ACQUIRE;
...
core::mem::drop($GUARD);
...
$AWAITED.await
- pattern-not: |
let mut $GUARD = $ACQUIRE;
...
core::mem::drop($GUARD);
...
$AWAITED.await

- id: room.rust.weak-rng-for-secret
message: A secret-like value is generated with a known non-cryptographic RNG.
severity: ERROR
Expand Down Expand Up @@ -384,3 +366,15 @@ rules:
metavariable: $SECRET
regex: '(?i)^(?:.*_)?(?:secret|token|api_key|private_key|password|passwd|session_id|session_token|nonce|salt|otp)(?:_.*)?$'
- focus-metavariable: $VALUE
- id: room.source.high-confidence-secret-literal
message: A string literal with a recognized credential token format is embedded in source.
severity: ERROR
languages: [go, rust]
metadata:
room_signal: SIGNAL_KIND_SECRET_LITERAL
room_confidence_basis_points: 9500
patterns:
- pattern: $SECRET
- metavariable-regex:
metavariable: $SECRET
regex: '^"(?:gh[pousr]_[A-Za-z0-9]{36,255}|github_pat_[A-Za-z0-9_]{40,255}|sk-(?:proj-)?[A-Za-z0-9_-]{32,255}|xox[baprs]-[A-Za-z0-9-]{20,255})"$'
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
rules:
- id: room.go.dynamic-sql-with-untrusted-input
message: Untrusted HTTP input reaches the SQL query text.
severity: ERROR
languages: [go]
mode: taint
metadata:
room_signal: SIGNAL_KIND_DYNAMIC_SQL_WITH_UNTRUSTED_INPUT
room_confidence_basis_points: 9000
pattern-sources:
- pattern-either:
- pattern: $REQ.URL.Query().Get(...)
- pattern: $REQ.FormValue(...)
- pattern: $REQ.PostFormValue(...)
- pattern: $REQ.Header.Get(...)
- pattern: $REQ.PathValue(...)
pattern-sinks:
- patterns:
- pattern-either:
- pattern: $DB.Query($QUERY, ...)
- pattern: $DB.QueryContext($CTX, $QUERY, ...)
- pattern: $DB.QueryRow($QUERY, ...)
- pattern: $DB.QueryRowContext($CTX, $QUERY, ...)
- pattern: $DB.Exec($QUERY, ...)
- pattern: $DB.ExecContext($CTX, $QUERY, ...)
- pattern: $DB.Prepare($QUERY)
- pattern: $DB.PrepareContext($CTX, $QUERY)
- focus-metavariable: $QUERY
25 changes: 25 additions & 0 deletions analyzers/semgrep/rules/room.go.untrusted-outbound-destination.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
rules:
- id: room.go.untrusted-outbound-destination
message: Untrusted HTTP input reaches an outbound request destination.
severity: ERROR
languages: [go]
mode: taint
metadata:
room_signal: SIGNAL_KIND_UNTRUSTED_OUTBOUND_DESTINATION
room_confidence_basis_points: 9000
pattern-sources:
- pattern-either:
- pattern: $REQ.URL.Query().Get(...)
- pattern: $REQ.FormValue(...)
- pattern: $REQ.PostFormValue(...)
- pattern: $REQ.Header.Get(...)
- pattern: $REQ.PathValue(...)
pattern-sinks:
- patterns:
- pattern-either:
- pattern: http.Get($URL)
- pattern: http.Post($URL, ...)
- pattern: http.PostForm($URL, ...)
- pattern: http.NewRequest($METHOD, $URL, ...)
- pattern: http.NewRequestWithContext($CTX, $METHOD, $URL, ...)
- focus-metavariable: $URL
Loading
Loading