PABCD Initiative Documentation Hub pabcd_initiative codexclaw cli-jaw

Language-Specific Security Quirks

Source: dev-security/references/language-quirks.md

Language-Specific Security Quirks

These are the quiet pitfalls that often survive ordinary code review.

Use this file when the code looks normal but still feels risky.

JavaScript and TypeScript

1. Prototype pollution through object merge

const payload = { ...req.body };
Object.assign(userSettings, payload);

Validate strictly and copy only approved keys.

2. eval and Function execute attacker-controlled code

const result = eval(req.query.expression as string);

Model expressions as data, not executable code.

3. child_process.exec injects shell syntax

exec(`convert ${req.query.file} output.png`);

Use execFile or spawn with validated argument arrays.

4. dangerouslySetInnerHTML bypasses JSX escaping

<div dangerouslySetInnerHTML={{ __html: userBio }} />

Sanitize HTML and use CSP when rich text is intentional.

5. String-built SQL bypasses ORM safety

await db.$queryRawUnsafe(`SELECT * FROM users WHERE email = '${email}'`);

Use tagged templates or parameter placeholders.

6. Open redirects via unchecked URLs

res.redirect(String(req.query.next || '/'));

Allow only same-origin or allowlisted relative paths.

7. Implicit JSON serialization leaks fields

res.json(user);

Serialize through an explicit DTO that excludes secrets and internal flags.

8. Browser token storage is reachable by XSS

localStorage.setItem('access_token', token);

Prefer secure cookies for browser sessions.

9. Regex denial of service from user patterns

new RegExp(req.query.pattern as string).test(target);

Avoid dynamic regex or constrain length and syntax aggressively.

10. URL construction can smuggle SSRF targets

const url = `https://${req.body.host}/status`;

Resolve against an allowlist or internal service registry.

Python

1. pickle.loads executes serialized code

data = pickle.loads(request.data)

Use JSON, MessagePack with schema validation, or typed parsers.

2. yaml.load with unsafe loader is code execution

config = yaml.load(raw_text, Loader=yaml.Loader)

Use yaml.safe_load for untrusted YAML.

3. subprocess.run(..., shell=True) injects shell commands

subprocess.run(f"convert {filename} out.png", shell=True)

Pass a list with shell=False.

4. assert is not an auth or validation check

assert request.user.is_admin

Raise explicit exceptions or return explicit HTTP errors.

5. Django mark_safe bypasses output escaping

return mark_safe(user_bio)

Escape by default and sanitize only approved rich text.

6. eval, exec, and ast.literal_eval on untrusted data

query = eval(request.args["filter"])

Parse into a constrained schema instead.

7. Mass assignment through model constructors

user = User(**request.json)

Bind only the fields the server explicitly accepts.

8. Pandas query and eval accept attacker syntax

df.query(request.args["where"])

Build filters from allowed columns and operators.

SQL

1. String interpolation is still injection

SELECT * FROM users WHERE email = '${email}';

Use parameter placeholders from the driver.

2. Dynamic ORDER BY can be injected

SELECT * FROM orders ORDER BY ${sort};

Map user choices to an allowlisted column set.

3. Wildcard search can become data exfiltration

WHERE email LIKE '%' || :term || '%'

Constrain searchable fields and rate limit broad queries.

4. Tenant scoping must live in the query

SELECT * FROM invoices WHERE id = $1;

Add tenant or owner filters in every access path.

5. Collation and case-folding can bypass uniqueness assumptions

SELECT * FROM users WHERE email = $1;

Normalize canonical values before storage and lookup.

6. Bulk updates without precise filters become integrity failures

UPDATE sessions SET revoked = true;

Require actor, tenant, or token family filters for every destructive statement.

Go

1. fmt.Sprintf query building is SQL injection

query := fmt.Sprintf("SELECT * FROM users WHERE email = '%s'", email)

Use db.QueryContext(ctx, ..., email) with parameters.

2. html/template and text/template are not interchangeable

tmpl := template.Must(texttemplate.New("page").Parse(userHTML))

Use html/template for HTML output and avoid untrusted templates.

3. Missing defer cancel() leaks work and weakens timeouts

ctx, cancel := context.WithTimeout(r.Context(), 3*time.Second)
_ = cancel

Always defer cancel() immediately.

4. File path joins can still escape a base directory

path := filepath.Join(uploadDir, r.FormValue("name"))

Clean, validate, and confirm the final path stays within the intended root.

5. Unbounded JSON decoding accepts oversized input

decoder := json.NewDecoder(r.Body)

Wrap the body with http.MaxBytesReader before decoding.

Use this file together with references/owasp-top10.md A05 when the issue involves input, output, or execution sinks.