Reglas por lenguaje
Colección de reglas personalizadas organizadas por lenguaje, listas para copiar a tu proyecto.
Python
Inyección SQL (Django ORM)
rules:
- id: django-raw-sql
patterns:
- pattern-either:
- pattern: RawSQL(...)
- pattern: $MODEL.objects.raw($QUERY, ...)
- pattern: connection.cursor().execute($QUERY, ...)
- pattern-not: $MODEL.objects.raw("...", [...])
message: >
Uso de SQL raw — verifica que los parámetros estén parametrizados
y no concatenados en el string.
languages: [python]
severity: ERROR
metadata:
cwe: "CWE-89"
Deserialización insegura
rules:
- id: unsafe-pickle
pattern-either:
- pattern: pickle.loads(...)
- pattern: pickle.load(...)
- pattern: cPickle.loads(...)
- pattern: cPickle.load(...)
message: >
pickle.load() ejecuta código arbitrario — nunca deserialices datos
de fuentes no confiables. Usa json o msgpack.
languages: [python]
severity: ERROR
metadata:
cwe: "CWE-502"
SSRF
rules:
- id: python-ssrf
patterns:
- pattern-either:
- pattern: requests.get($URL, ...)
- pattern: requests.post($URL, ...)
- pattern: urllib.request.urlopen($URL, ...)
- pattern: httpx.get($URL, ...)
- pattern-not: requests.get("...", ...)
- pattern-not: requests.post("...", ...)
- pattern-not: urllib.request.urlopen("...", ...)
- pattern-not: httpx.get("...", ...)
message: >
URL dinámica en petición HTTP — valida contra una allowlist
para prevenir SSRF.
languages: [python]
severity: WARNING
metadata:
cwe: "CWE-918"
Subprocess con shell=True
rules:
- id: subprocess-shell
pattern: subprocess.call(..., shell=True, ...)
fix: subprocess.call(..., shell=False, ...)
message: >
shell=True permite inyección de comandos — usa shell=False
y pasa argumentos como lista.
languages: [python]
severity: ERROR
metadata:
cwe: "CWE-78"
JavaScript / TypeScript
XSS con dangerouslySetInnerHTML
rules:
- id: react-dangerously-set-innerhtml
pattern: <$TAG dangerouslySetInnerHTML={...} />
message: >
dangerouslySetInnerHTML puede causar XSS — sanitiza el HTML
con DOMPurify antes de renderizar.
languages: [typescript, javascript]
severity: ERROR
metadata:
cwe: "CWE-79"
Prototype pollution
rules:
- id: prototype-pollution
patterns:
- pattern: $OBJ[$KEY] = $VAL
- pattern-inside: |
function $FUNC(..., $KEY, ...) {
...
}
message: >
Asignación dinámica de propiedad con clave controlada por usuario —
puede causar prototype pollution. Valida $KEY contra una allowlist.
languages: [javascript, typescript]
severity: WARNING
metadata:
cwe: "CWE-1321"
Regex denial of service (ReDoS)
rules:
- id: regex-dos
pattern-either:
- pattern: new RegExp($INPUT)
- pattern: new RegExp($INPUT, ...)
message: >
Regex construido con input de usuario — puede causar ReDoS.
Usa una librería segura como re2 o valida el patrón primero.
languages: [javascript, typescript]
severity: WARNING
metadata:
cwe: "CWE-1333"
eval / Function constructor
rules:
- id: js-code-injection
pattern-either:
- pattern: eval(...)
- pattern: new Function(...)
- pattern: setTimeout($CODE, ...)
- pattern: setInterval($CODE, ...)
message: >
Ejecución dinámica de código — evita eval() y Function().
Si es inevitable, nunca pases input de usuario.
languages: [javascript, typescript]
severity: ERROR
metadata:
cwe: "CWE-94"
Go
Inyección SQL
rules:
- id: go-sqli
patterns:
- pattern-either:
- pattern: $DB.Query(fmt.Sprintf("...", ...), ...)
- pattern: $DB.Exec(fmt.Sprintf("...", ...), ...)
- pattern: $DB.QueryRow(fmt.Sprintf("...", ...), ...)
- pattern: $DB.Query($Q + $V, ...)
- pattern-not: $DB.Query("...", ...)
message: >
SQL construido con concatenación/Sprintf — usa placeholders:
db.Query("SELECT * FROM users WHERE id = $1", id)
languages: [go]
severity: ERROR
metadata:
cwe: "CWE-89"
Path traversal
rules:
- id: go-path-traversal
patterns:
- pattern-either:
- pattern: os.Open(filepath.Join($BASE, $INPUT))
- pattern: os.ReadFile(filepath.Join($BASE, $INPUT))
- pattern: http.ServeFile($W, $R, $PATH)
- pattern-not-inside: |
if !strings.Contains($INPUT, "..") {
...
}
message: >
Posible path traversal — valida que el path resuelto
esté dentro del directorio esperado con filepath.Rel().
languages: [go]
severity: ERROR
metadata:
cwe: "CWE-22"
Crypto débil
rules:
- id: go-weak-crypto
pattern-either:
- pattern: md5.New()
- pattern: md5.Sum(...)
- pattern: sha1.New()
- pattern: sha1.Sum(...)
- pattern: des.NewCipher(...)
- pattern: rc4.NewCipher(...)
message: >
Algoritmo criptográfico débil — usa sha256, aes
u otros algoritmos modernos.
languages: [go]
severity: WARNING
metadata:
cwe: "CWE-327"
Uso
Guarda las reglas en un directorio semgrep-rules/ y ejecútalas:
# Todas las reglas locales
semgrep --config=semgrep-rules/ src/
# Reglas locales + registry
semgrep --config=semgrep-rules/ --config=p/ci src/
# Solo un archivo de reglas
semgrep --config=semgrep-rules/python.yaml src/
Referencias
- https://semgrep.dev/docs/writing-rules/overview
- https://semgrep.dev/docs/writing-rules/pattern-syntax
- https://semgrep.dev/playground — probar reglas interactivamente